importer-storage 1.0.16 → 1.0.18

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/dist/index.cjs CHANGED
@@ -62,6 +62,7 @@ var import_axios = __toESM(require("axios"), 1);
62
62
  var import_jimp = require("jimp");
63
63
  var import_https_proxy_agent = require("https-proxy-agent");
64
64
  var import_perf_hooks = require("perf_hooks");
65
+ var import_p_limit = __toESM(require("p-limit"), 1);
65
66
  (0, import_dotenv.config)();
66
67
  if (!process.env.AWS_EXECUTION_ENV && !process.env.AWS_ACCESS_KEY_ID) {
67
68
  throw new Error("'AWS_ACCESS_KEY_ID' not set");
@@ -92,110 +93,147 @@ if (!BUCKET_NAME) {
92
93
  function isHttp(url) {
93
94
  return url.startsWith("http://") || url.startsWith("https://");
94
95
  }
96
+ var processRecord = (_0, _1, _2) => __async(null, [_0, _1, _2], function* ({
97
+ filePath,
98
+ key
99
+ }, options, proxyAgent) {
100
+ const start = import_perf_hooks.performance.now();
101
+ if (options.logging) {
102
+ console.info(`
103
+ [Processing Start] key=${key}, filePath=${filePath}`);
104
+ }
105
+ try {
106
+ const s3Key = `${options.savePath}/${key}`;
107
+ if (options.logging) {
108
+ console.info(`[S3 Key] ${s3Key}`);
109
+ }
110
+ let stream = void 0;
111
+ let buffer = void 0;
112
+ if (isHttp(filePath)) {
113
+ if (options.logging) {
114
+ console.info(`[Download Start] ${filePath}`);
115
+ }
116
+ const axiosResponse = yield import_axios.default.get(filePath, {
117
+ responseType: "arraybuffer",
118
+ headers: options.headers,
119
+ httpsAgent: proxyAgent
120
+ });
121
+ if (options.logging) {
122
+ console.info(`[Download Success] ${filePath}`);
123
+ }
124
+ buffer = Buffer.from(axiosResponse.data);
125
+ } else {
126
+ if (options.logging) {
127
+ console.info(`[Read from FS] ${filePath}`);
128
+ }
129
+ stream = (0, import_fs.createReadStream)(filePath);
130
+ }
131
+ const tagString = options.tags.map(
132
+ (tag) => `${encodeURIComponent(tag.split(":")[0])}=${encodeURIComponent(tag.split(":")[1])}`
133
+ ).join("&");
134
+ if (!stream && !buffer) {
135
+ if (options.logging) {
136
+ console.warn(`[Error] Neither stream nor buffer is set for ${key}`);
137
+ }
138
+ throw new Error("buffer or stream not set");
139
+ }
140
+ if (options.logging) {
141
+ console.info(`[Image Processing Start] ${key}`);
142
+ }
143
+ const image = buffer ? yield import_jimp.Jimp.fromBuffer(buffer) : yield import_jimp.Jimp.read(filePath);
144
+ if (options.logging) {
145
+ console.info(
146
+ `[Image Loaded] key=${key}, width=${image.width}, height=${image.height}`
147
+ );
148
+ }
149
+ const command = new import_client_s3.PutObjectCommand({
150
+ Body: buffer || stream,
151
+ Bucket: BUCKET_NAME,
152
+ Key: s3Key,
153
+ Tagging: tagString || void 0,
154
+ ContentType: `image/${extractFileInfo(key).extension}`,
155
+ ContentDisposition: "inline",
156
+ Metadata: {
157
+ "img-width": image.width.toString(),
158
+ "img-height": image.height.toString()
159
+ }
160
+ });
161
+ if (options.logging) {
162
+ console.info(`[Uploading] ${key} to S3...`);
163
+ }
164
+ yield s3.send(command);
165
+ if (options.logging) {
166
+ console.info(`[Upload Success] ${key}`);
167
+ }
168
+ return {
169
+ error: false,
170
+ key,
171
+ filePath,
172
+ uploadUrl: `https://${BUCKET_NAME}.s3.${process.env.AWS_REGION}.amazonaws.com/${s3Key}`
173
+ };
174
+ } catch (e) {
175
+ const error = e;
176
+ if (options.logging) {
177
+ console.error(`[Upload Error] key=${key}, error=${error.message}`);
178
+ }
179
+ return {
180
+ error: true,
181
+ key,
182
+ filePath,
183
+ message: error.message
184
+ };
185
+ } finally {
186
+ const end = import_perf_hooks.performance.now();
187
+ if (options.logging) {
188
+ console.info(
189
+ `[Processing End] key=${key}, duration=${(end - start).toFixed(0)}ms`
190
+ );
191
+ }
192
+ }
193
+ });
95
194
  var S3Storage = class {
96
195
  saveFiles(keys, options) {
97
196
  return __async(this, null, function* () {
197
+ const parallelLimit = options.parallelLimit || 2;
198
+ const limit = (0, import_p_limit.default)(parallelLimit);
98
199
  const result = [];
99
200
  const errored = [];
100
201
  const proxyAgent = (options == null ? void 0 : options.proxyUrl) && new import_https_proxy_agent.HttpsProxyAgent(options == null ? void 0 : options.proxyUrl);
101
202
  if (options.logging) {
102
203
  console.info(`[SaveFiles] Start saving ${keys.length} file(s)`);
103
- console.time(`[SaveFiles] Total time`);
204
+ console.time(`[SaveFiles] Total time ${parallelLimit}`);
104
205
  }
105
- for (const { key, filePath } of keys) {
106
- const start = import_perf_hooks.performance.now();
107
- if (options.logging) {
108
- console.info(`
109
- [Processing Start] key=${key}, filePath=${filePath}`);
110
- }
111
- try {
112
- const s3Key = `${options.savePath}/${key}`;
113
- if (options.logging) {
114
- console.info(`[S3 Key] ${s3Key}`);
115
- }
116
- let stream = void 0;
117
- let buffer = void 0;
118
- if (isHttp(filePath)) {
206
+ yield Promise.all(
207
+ keys.map(
208
+ (record, index) => limit(() => __async(null, null, function* () {
119
209
  if (options.logging) {
120
- console.info(`[Download Start] ${filePath}`);
210
+ console.info(
211
+ `Running p-limit task ${index}, limit: ${parallelLimit}`
212
+ );
121
213
  }
122
- const axiosResponse = yield import_axios.default.get(filePath, {
123
- responseType: "arraybuffer",
124
- headers: options.headers,
125
- httpsAgent: proxyAgent
126
- });
127
- if (options.logging) {
128
- console.info(`[Download Success] ${filePath}`);
129
- }
130
- buffer = Buffer.from(axiosResponse.data);
131
- } else {
132
- if (options.logging) {
133
- console.info(`[Read from FS] ${filePath}`);
134
- }
135
- stream = (0, import_fs.createReadStream)(filePath);
136
- }
137
- const tagString = options.tags.map(
138
- (tag) => `${encodeURIComponent(tag.split(":")[0])}=${encodeURIComponent(tag.split(":")[1])}`
139
- ).join("&");
140
- if (!stream && !buffer) {
141
- if (options.logging) {
142
- console.warn(`[Error] Neither stream nor buffer is set for ${key}`);
143
- }
144
- throw new Error("buffer or stream not set");
145
- }
146
- if (options.logging) {
147
- console.info(`[Image Processing Start] ${key}`);
148
- }
149
- const image = buffer ? yield import_jimp.Jimp.fromBuffer(buffer) : yield import_jimp.Jimp.read(filePath);
150
- if (options.logging) {
151
- console.info(
152
- `[Image Loaded] key=${key}, width=${image.width}, height=${image.height}`
214
+ const processResult = yield processRecord(
215
+ record,
216
+ options,
217
+ proxyAgent || void 0
153
218
  );
154
- }
155
- const command = new import_client_s3.PutObjectCommand({
156
- Body: buffer || stream,
157
- Bucket: BUCKET_NAME,
158
- Key: s3Key,
159
- Tagging: tagString || void 0,
160
- ContentType: `image/${extractFileInfo(key).extension}`,
161
- ContentDisposition: "inline",
162
- Metadata: {
163
- "img-width": image.width.toString(),
164
- "img-height": image.height.toString()
219
+ if (processResult.message) {
220
+ errored.push({
221
+ key: processResult.key,
222
+ filePath: processResult.filePath,
223
+ message: processResult.message
224
+ });
225
+ } else if (processResult.uploadUrl) {
226
+ result.push({
227
+ key: processResult.key,
228
+ filePath: processResult.filePath,
229
+ uploadUrl: processResult.uploadUrl
230
+ });
165
231
  }
166
- });
167
- result.push({
168
- key,
169
- filePath,
170
- uploadUrl: `https://${BUCKET_NAME}.s3.${process.env.AWS_REGION}.amazonaws.com/${s3Key}`
171
- });
172
- if (options.logging) {
173
- console.info(`[Uploading] ${key} to S3...`);
174
- }
175
- yield s3.send(command);
176
- if (options.logging) {
177
- console.info(`[Upload Success] ${key}`);
178
- }
179
- } catch (e) {
180
- const error = e;
181
- if (options.logging) {
182
- console.error(`[Upload Error] key=${key}, error=${error.message}`);
183
- }
184
- errored.push({
185
- key,
186
- filePath,
187
- message: error.message
188
- });
189
- }
190
- const end = import_perf_hooks.performance.now();
191
- if (options.logging) {
192
- console.info(
193
- `[Processing End] key=${key}, duration=${(end - start).toFixed(0)}ms`
194
- );
195
- }
196
- }
232
+ }))
233
+ )
234
+ );
197
235
  if (options.logging) {
198
- console.timeEnd(`[SaveFiles] Total time`);
236
+ console.timeEnd(`[SaveFiles] Total time ${parallelLimit}`);
199
237
  console.info(
200
238
  `[SaveFiles] Completed. Success: ${result.length}, Failed: ${errored.length}`
201
239
  );
package/dist/index.d.cts CHANGED
@@ -25,17 +25,19 @@ interface IStorage {
25
25
  removeTag(savePath: string, tags: Array<StorageTag>): Promise<void>;
26
26
  }
27
27
 
28
+ type Options = {
29
+ tags: Array<StorageTag>;
30
+ savePath: string;
31
+ headers?: Record<string, string>;
32
+ logging?: boolean;
33
+ proxyUrl?: string;
34
+ parallelLimit?: number;
35
+ };
28
36
  declare class S3Storage implements IStorage {
29
37
  saveFiles(keys: Array<{
30
38
  key: string;
31
39
  filePath: string;
32
- }>, options: {
33
- tags: Array<StorageTag>;
34
- savePath: string;
35
- headers?: Record<string, string>;
36
- logging?: boolean;
37
- proxyUrl?: string;
38
- }): Promise<{
40
+ }>, options: Options): Promise<{
39
41
  result: {
40
42
  key: string;
41
43
  filePath: string;
package/dist/index.d.ts CHANGED
@@ -25,17 +25,19 @@ interface IStorage {
25
25
  removeTag(savePath: string, tags: Array<StorageTag>): Promise<void>;
26
26
  }
27
27
 
28
+ type Options = {
29
+ tags: Array<StorageTag>;
30
+ savePath: string;
31
+ headers?: Record<string, string>;
32
+ logging?: boolean;
33
+ proxyUrl?: string;
34
+ parallelLimit?: number;
35
+ };
28
36
  declare class S3Storage implements IStorage {
29
37
  saveFiles(keys: Array<{
30
38
  key: string;
31
39
  filePath: string;
32
- }>, options: {
33
- tags: Array<StorageTag>;
34
- savePath: string;
35
- headers?: Record<string, string>;
36
- logging?: boolean;
37
- proxyUrl?: string;
38
- }): Promise<{
40
+ }>, options: Options): Promise<{
39
41
  result: {
40
42
  key: string;
41
43
  filePath: string;
@@ -74,6 +74,18 @@ var CalculatorModule = (() => {
74
74
  ));
75
75
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
76
76
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
77
+ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
78
+ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
79
+ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
80
+ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
81
+ var __privateWrapper = (obj, member, setter, getter) => ({
82
+ set _(value) {
83
+ __privateSet(obj, member, value, setter);
84
+ },
85
+ get _() {
86
+ return __privateGet(obj, member, getter);
87
+ }
88
+ });
77
89
  var __async = (__this, __arguments, generator) => {
78
90
  return new Promise((resolve2, reject2) => {
79
91
  var fulfilled = (value) => {
@@ -76711,6 +76723,156 @@ For more information please go to https://github.com/aws/aws-sdk-js-v3#functiona
76711
76723
  // src/logic/storage.ts
76712
76724
  var import_https_proxy_agent = __toESM(require_dist2(), 1);
76713
76725
  var import_perf_hooks = __require("perf_hooks");
76726
+
76727
+ // node_modules/yocto-queue/index.js
76728
+ var Node = class {
76729
+ constructor(value) {
76730
+ __publicField(this, "value");
76731
+ __publicField(this, "next");
76732
+ this.value = value;
76733
+ }
76734
+ };
76735
+ var _head, _tail, _size;
76736
+ var Queue = class {
76737
+ constructor() {
76738
+ __privateAdd(this, _head);
76739
+ __privateAdd(this, _tail);
76740
+ __privateAdd(this, _size);
76741
+ this.clear();
76742
+ }
76743
+ enqueue(value) {
76744
+ const node = new Node(value);
76745
+ if (__privateGet(this, _head)) {
76746
+ __privateGet(this, _tail).next = node;
76747
+ __privateSet(this, _tail, node);
76748
+ } else {
76749
+ __privateSet(this, _head, node);
76750
+ __privateSet(this, _tail, node);
76751
+ }
76752
+ __privateWrapper(this, _size)._++;
76753
+ }
76754
+ dequeue() {
76755
+ const current = __privateGet(this, _head);
76756
+ if (!current) {
76757
+ return;
76758
+ }
76759
+ __privateSet(this, _head, __privateGet(this, _head).next);
76760
+ __privateWrapper(this, _size)._--;
76761
+ if (!__privateGet(this, _head)) {
76762
+ __privateSet(this, _tail, void 0);
76763
+ }
76764
+ return current.value;
76765
+ }
76766
+ peek() {
76767
+ if (!__privateGet(this, _head)) {
76768
+ return;
76769
+ }
76770
+ return __privateGet(this, _head).value;
76771
+ }
76772
+ clear() {
76773
+ __privateSet(this, _head, void 0);
76774
+ __privateSet(this, _tail, void 0);
76775
+ __privateSet(this, _size, 0);
76776
+ }
76777
+ get size() {
76778
+ return __privateGet(this, _size);
76779
+ }
76780
+ *[Symbol.iterator]() {
76781
+ let current = __privateGet(this, _head);
76782
+ while (current) {
76783
+ yield current.value;
76784
+ current = current.next;
76785
+ }
76786
+ }
76787
+ *drain() {
76788
+ while (__privateGet(this, _head)) {
76789
+ yield this.dequeue();
76790
+ }
76791
+ }
76792
+ };
76793
+ _head = new WeakMap();
76794
+ _tail = new WeakMap();
76795
+ _size = new WeakMap();
76796
+
76797
+ // node_modules/p-limit/index.js
76798
+ function pLimit(concurrency) {
76799
+ validateConcurrency(concurrency);
76800
+ const queue = new Queue();
76801
+ let activeCount = 0;
76802
+ const resumeNext = () => {
76803
+ if (activeCount < concurrency && queue.size > 0) {
76804
+ activeCount++;
76805
+ queue.dequeue()();
76806
+ }
76807
+ };
76808
+ const next = () => {
76809
+ activeCount--;
76810
+ resumeNext();
76811
+ };
76812
+ const run = (function_, resolve2, arguments_) => __async(null, null, function* () {
76813
+ const result = (() => __async(null, null, function* () {
76814
+ return function_(...arguments_);
76815
+ }))();
76816
+ resolve2(result);
76817
+ try {
76818
+ yield result;
76819
+ } catch (e5) {
76820
+ }
76821
+ next();
76822
+ });
76823
+ const enqueue = (function_, resolve2, arguments_) => {
76824
+ new Promise((internalResolve) => {
76825
+ queue.enqueue(internalResolve);
76826
+ }).then(run.bind(void 0, function_, resolve2, arguments_));
76827
+ if (activeCount < concurrency) {
76828
+ resumeNext();
76829
+ }
76830
+ };
76831
+ const generator = (function_, ...arguments_) => new Promise((resolve2) => {
76832
+ enqueue(function_, resolve2, arguments_);
76833
+ });
76834
+ Object.defineProperties(generator, {
76835
+ activeCount: {
76836
+ get: () => activeCount
76837
+ },
76838
+ pendingCount: {
76839
+ get: () => queue.size
76840
+ },
76841
+ clearQueue: {
76842
+ value() {
76843
+ queue.clear();
76844
+ }
76845
+ },
76846
+ concurrency: {
76847
+ get: () => concurrency,
76848
+ set(newConcurrency) {
76849
+ validateConcurrency(newConcurrency);
76850
+ concurrency = newConcurrency;
76851
+ queueMicrotask(() => {
76852
+ while (activeCount < concurrency && queue.size > 0) {
76853
+ resumeNext();
76854
+ }
76855
+ });
76856
+ }
76857
+ },
76858
+ map: {
76859
+ value(iterable, function_) {
76860
+ return __async(this, null, function* () {
76861
+ const promises = Array.from(iterable, (value, index) => this(function_, value, index));
76862
+ return Promise.all(promises);
76863
+ });
76864
+ }
76865
+ }
76866
+ });
76867
+ return generator;
76868
+ }
76869
+ function validateConcurrency(concurrency) {
76870
+ if (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) {
76871
+ throw new TypeError("Expected `concurrency` to be a number from 1 and up");
76872
+ }
76873
+ }
76874
+
76875
+ // src/logic/storage.ts
76714
76876
  (0, import_dotenv.config)();
76715
76877
  if (!process.env.AWS_EXECUTION_ENV && !process.env.AWS_ACCESS_KEY_ID) {
76716
76878
  throw new Error("'AWS_ACCESS_KEY_ID' not set");
@@ -76741,110 +76903,147 @@ For more information please go to https://github.com/aws/aws-sdk-js-v3#functiona
76741
76903
  function isHttp(url2) {
76742
76904
  return url2.startsWith("http://") || url2.startsWith("https://");
76743
76905
  }
76906
+ var processRecord = (_0, _1, _2) => __async(null, [_0, _1, _2], function* ({
76907
+ filePath,
76908
+ key
76909
+ }, options, proxyAgent) {
76910
+ const start = import_perf_hooks.performance.now();
76911
+ if (options.logging) {
76912
+ console.info(`
76913
+ [Processing Start] key=${key}, filePath=${filePath}`);
76914
+ }
76915
+ try {
76916
+ const s3Key = `${options.savePath}/${key}`;
76917
+ if (options.logging) {
76918
+ console.info(`[S3 Key] ${s3Key}`);
76919
+ }
76920
+ let stream5 = void 0;
76921
+ let buffer = void 0;
76922
+ if (isHttp(filePath)) {
76923
+ if (options.logging) {
76924
+ console.info(`[Download Start] ${filePath}`);
76925
+ }
76926
+ const axiosResponse = yield axios_default.get(filePath, {
76927
+ responseType: "arraybuffer",
76928
+ headers: options.headers,
76929
+ httpsAgent: proxyAgent
76930
+ });
76931
+ if (options.logging) {
76932
+ console.info(`[Download Success] ${filePath}`);
76933
+ }
76934
+ buffer = Buffer.from(axiosResponse.data);
76935
+ } else {
76936
+ if (options.logging) {
76937
+ console.info(`[Read from FS] ${filePath}`);
76938
+ }
76939
+ stream5 = (0, import_fs8.createReadStream)(filePath);
76940
+ }
76941
+ const tagString = options.tags.map(
76942
+ (tag) => `${encodeURIComponent(tag.split(":")[0])}=${encodeURIComponent(tag.split(":")[1])}`
76943
+ ).join("&");
76944
+ if (!stream5 && !buffer) {
76945
+ if (options.logging) {
76946
+ console.warn(`[Error] Neither stream nor buffer is set for ${key}`);
76947
+ }
76948
+ throw new Error("buffer or stream not set");
76949
+ }
76950
+ if (options.logging) {
76951
+ console.info(`[Image Processing Start] ${key}`);
76952
+ }
76953
+ const image2 = buffer ? yield Jimp.fromBuffer(buffer) : yield Jimp.read(filePath);
76954
+ if (options.logging) {
76955
+ console.info(
76956
+ `[Image Loaded] key=${key}, width=${image2.width}, height=${image2.height}`
76957
+ );
76958
+ }
76959
+ const command = new PutObjectCommand({
76960
+ Body: buffer || stream5,
76961
+ Bucket: BUCKET_NAME,
76962
+ Key: s3Key,
76963
+ Tagging: tagString || void 0,
76964
+ ContentType: `image/${extractFileInfo(key).extension}`,
76965
+ ContentDisposition: "inline",
76966
+ Metadata: {
76967
+ "img-width": image2.width.toString(),
76968
+ "img-height": image2.height.toString()
76969
+ }
76970
+ });
76971
+ if (options.logging) {
76972
+ console.info(`[Uploading] ${key} to S3...`);
76973
+ }
76974
+ yield s32.send(command);
76975
+ if (options.logging) {
76976
+ console.info(`[Upload Success] ${key}`);
76977
+ }
76978
+ return {
76979
+ error: false,
76980
+ key,
76981
+ filePath,
76982
+ uploadUrl: `https://${BUCKET_NAME}.s3.${process.env.AWS_REGION}.amazonaws.com/${s3Key}`
76983
+ };
76984
+ } catch (e5) {
76985
+ const error = e5;
76986
+ if (options.logging) {
76987
+ console.error(`[Upload Error] key=${key}, error=${error.message}`);
76988
+ }
76989
+ return {
76990
+ error: true,
76991
+ key,
76992
+ filePath,
76993
+ message: error.message
76994
+ };
76995
+ } finally {
76996
+ const end = import_perf_hooks.performance.now();
76997
+ if (options.logging) {
76998
+ console.info(
76999
+ `[Processing End] key=${key}, duration=${(end - start).toFixed(0)}ms`
77000
+ );
77001
+ }
77002
+ }
77003
+ });
76744
77004
  var S3Storage = class {
76745
77005
  saveFiles(keys, options) {
76746
77006
  return __async(this, null, function* () {
77007
+ const parallelLimit = options.parallelLimit || 2;
77008
+ const limit = pLimit(parallelLimit);
76747
77009
  const result = [];
76748
77010
  const errored = [];
76749
77011
  const proxyAgent = (options == null ? void 0 : options.proxyUrl) && new import_https_proxy_agent.HttpsProxyAgent(options == null ? void 0 : options.proxyUrl);
76750
77012
  if (options.logging) {
76751
77013
  console.info(`[SaveFiles] Start saving ${keys.length} file(s)`);
76752
- console.time(`[SaveFiles] Total time`);
77014
+ console.time(`[SaveFiles] Total time ${parallelLimit}`);
76753
77015
  }
76754
- for (const { key, filePath } of keys) {
76755
- const start = import_perf_hooks.performance.now();
76756
- if (options.logging) {
76757
- console.info(`
76758
- [Processing Start] key=${key}, filePath=${filePath}`);
76759
- }
76760
- try {
76761
- const s3Key = `${options.savePath}/${key}`;
76762
- if (options.logging) {
76763
- console.info(`[S3 Key] ${s3Key}`);
76764
- }
76765
- let stream5 = void 0;
76766
- let buffer = void 0;
76767
- if (isHttp(filePath)) {
76768
- if (options.logging) {
76769
- console.info(`[Download Start] ${filePath}`);
76770
- }
76771
- const axiosResponse = yield axios_default.get(filePath, {
76772
- responseType: "arraybuffer",
76773
- headers: options.headers,
76774
- httpsAgent: proxyAgent
76775
- });
76776
- if (options.logging) {
76777
- console.info(`[Download Success] ${filePath}`);
76778
- }
76779
- buffer = Buffer.from(axiosResponse.data);
76780
- } else {
76781
- if (options.logging) {
76782
- console.info(`[Read from FS] ${filePath}`);
76783
- }
76784
- stream5 = (0, import_fs8.createReadStream)(filePath);
76785
- }
76786
- const tagString = options.tags.map(
76787
- (tag) => `${encodeURIComponent(tag.split(":")[0])}=${encodeURIComponent(tag.split(":")[1])}`
76788
- ).join("&");
76789
- if (!stream5 && !buffer) {
77016
+ yield Promise.all(
77017
+ keys.map(
77018
+ (record, index) => limit(() => __async(null, null, function* () {
76790
77019
  if (options.logging) {
76791
- console.warn(`[Error] Neither stream nor buffer is set for ${key}`);
77020
+ console.info(
77021
+ `Running p-limit task ${index}, limit: ${parallelLimit}`
77022
+ );
76792
77023
  }
76793
- throw new Error("buffer or stream not set");
76794
- }
76795
- if (options.logging) {
76796
- console.info(`[Image Processing Start] ${key}`);
76797
- }
76798
- const image2 = buffer ? yield Jimp.fromBuffer(buffer) : yield Jimp.read(filePath);
76799
- if (options.logging) {
76800
- console.info(
76801
- `[Image Loaded] key=${key}, width=${image2.width}, height=${image2.height}`
77024
+ const processResult = yield processRecord(
77025
+ record,
77026
+ options,
77027
+ proxyAgent || void 0
76802
77028
  );
76803
- }
76804
- const command = new PutObjectCommand({
76805
- Body: buffer || stream5,
76806
- Bucket: BUCKET_NAME,
76807
- Key: s3Key,
76808
- Tagging: tagString || void 0,
76809
- ContentType: `image/${extractFileInfo(key).extension}`,
76810
- ContentDisposition: "inline",
76811
- Metadata: {
76812
- "img-width": image2.width.toString(),
76813
- "img-height": image2.height.toString()
77029
+ if (processResult.message) {
77030
+ errored.push({
77031
+ key: processResult.key,
77032
+ filePath: processResult.filePath,
77033
+ message: processResult.message
77034
+ });
77035
+ } else if (processResult.uploadUrl) {
77036
+ result.push({
77037
+ key: processResult.key,
77038
+ filePath: processResult.filePath,
77039
+ uploadUrl: processResult.uploadUrl
77040
+ });
76814
77041
  }
76815
- });
76816
- result.push({
76817
- key,
76818
- filePath,
76819
- uploadUrl: `https://${BUCKET_NAME}.s3.${process.env.AWS_REGION}.amazonaws.com/${s3Key}`
76820
- });
76821
- if (options.logging) {
76822
- console.info(`[Uploading] ${key} to S3...`);
76823
- }
76824
- yield s32.send(command);
76825
- if (options.logging) {
76826
- console.info(`[Upload Success] ${key}`);
76827
- }
76828
- } catch (e5) {
76829
- const error = e5;
76830
- if (options.logging) {
76831
- console.error(`[Upload Error] key=${key}, error=${error.message}`);
76832
- }
76833
- errored.push({
76834
- key,
76835
- filePath,
76836
- message: error.message
76837
- });
76838
- }
76839
- const end = import_perf_hooks.performance.now();
76840
- if (options.logging) {
76841
- console.info(
76842
- `[Processing End] key=${key}, duration=${(end - start).toFixed(0)}ms`
76843
- );
76844
- }
76845
- }
77042
+ }))
77043
+ )
77044
+ );
76846
77045
  if (options.logging) {
76847
- console.timeEnd(`[SaveFiles] Total time`);
77046
+ console.timeEnd(`[SaveFiles] Total time ${parallelLimit}`);
76848
77047
  console.info(
76849
77048
  `[SaveFiles] Completed. Success: ${result.length}, Failed: ${errored.length}`
76850
77049
  );
package/dist/index.js CHANGED
@@ -33,6 +33,7 @@ import axios from "axios";
33
33
  import { Jimp } from "jimp";
34
34
  import { HttpsProxyAgent } from "https-proxy-agent";
35
35
  import { performance } from "perf_hooks";
36
+ import pLimit from "p-limit";
36
37
  config();
37
38
  if (!process.env.AWS_EXECUTION_ENV && !process.env.AWS_ACCESS_KEY_ID) {
38
39
  throw new Error("'AWS_ACCESS_KEY_ID' not set");
@@ -63,110 +64,147 @@ if (!BUCKET_NAME) {
63
64
  function isHttp(url) {
64
65
  return url.startsWith("http://") || url.startsWith("https://");
65
66
  }
67
+ var processRecord = (_0, _1, _2) => __async(null, [_0, _1, _2], function* ({
68
+ filePath,
69
+ key
70
+ }, options, proxyAgent) {
71
+ const start = performance.now();
72
+ if (options.logging) {
73
+ console.info(`
74
+ [Processing Start] key=${key}, filePath=${filePath}`);
75
+ }
76
+ try {
77
+ const s3Key = `${options.savePath}/${key}`;
78
+ if (options.logging) {
79
+ console.info(`[S3 Key] ${s3Key}`);
80
+ }
81
+ let stream = void 0;
82
+ let buffer = void 0;
83
+ if (isHttp(filePath)) {
84
+ if (options.logging) {
85
+ console.info(`[Download Start] ${filePath}`);
86
+ }
87
+ const axiosResponse = yield axios.get(filePath, {
88
+ responseType: "arraybuffer",
89
+ headers: options.headers,
90
+ httpsAgent: proxyAgent
91
+ });
92
+ if (options.logging) {
93
+ console.info(`[Download Success] ${filePath}`);
94
+ }
95
+ buffer = Buffer.from(axiosResponse.data);
96
+ } else {
97
+ if (options.logging) {
98
+ console.info(`[Read from FS] ${filePath}`);
99
+ }
100
+ stream = createReadStream(filePath);
101
+ }
102
+ const tagString = options.tags.map(
103
+ (tag) => `${encodeURIComponent(tag.split(":")[0])}=${encodeURIComponent(tag.split(":")[1])}`
104
+ ).join("&");
105
+ if (!stream && !buffer) {
106
+ if (options.logging) {
107
+ console.warn(`[Error] Neither stream nor buffer is set for ${key}`);
108
+ }
109
+ throw new Error("buffer or stream not set");
110
+ }
111
+ if (options.logging) {
112
+ console.info(`[Image Processing Start] ${key}`);
113
+ }
114
+ const image = buffer ? yield Jimp.fromBuffer(buffer) : yield Jimp.read(filePath);
115
+ if (options.logging) {
116
+ console.info(
117
+ `[Image Loaded] key=${key}, width=${image.width}, height=${image.height}`
118
+ );
119
+ }
120
+ const command = new PutObjectCommand({
121
+ Body: buffer || stream,
122
+ Bucket: BUCKET_NAME,
123
+ Key: s3Key,
124
+ Tagging: tagString || void 0,
125
+ ContentType: `image/${extractFileInfo(key).extension}`,
126
+ ContentDisposition: "inline",
127
+ Metadata: {
128
+ "img-width": image.width.toString(),
129
+ "img-height": image.height.toString()
130
+ }
131
+ });
132
+ if (options.logging) {
133
+ console.info(`[Uploading] ${key} to S3...`);
134
+ }
135
+ yield s3.send(command);
136
+ if (options.logging) {
137
+ console.info(`[Upload Success] ${key}`);
138
+ }
139
+ return {
140
+ error: false,
141
+ key,
142
+ filePath,
143
+ uploadUrl: `https://${BUCKET_NAME}.s3.${process.env.AWS_REGION}.amazonaws.com/${s3Key}`
144
+ };
145
+ } catch (e) {
146
+ const error = e;
147
+ if (options.logging) {
148
+ console.error(`[Upload Error] key=${key}, error=${error.message}`);
149
+ }
150
+ return {
151
+ error: true,
152
+ key,
153
+ filePath,
154
+ message: error.message
155
+ };
156
+ } finally {
157
+ const end = performance.now();
158
+ if (options.logging) {
159
+ console.info(
160
+ `[Processing End] key=${key}, duration=${(end - start).toFixed(0)}ms`
161
+ );
162
+ }
163
+ }
164
+ });
66
165
  var S3Storage = class {
67
166
  saveFiles(keys, options) {
68
167
  return __async(this, null, function* () {
168
+ const parallelLimit = options.parallelLimit || 2;
169
+ const limit = pLimit(parallelLimit);
69
170
  const result = [];
70
171
  const errored = [];
71
172
  const proxyAgent = (options == null ? void 0 : options.proxyUrl) && new HttpsProxyAgent(options == null ? void 0 : options.proxyUrl);
72
173
  if (options.logging) {
73
174
  console.info(`[SaveFiles] Start saving ${keys.length} file(s)`);
74
- console.time(`[SaveFiles] Total time`);
175
+ console.time(`[SaveFiles] Total time ${parallelLimit}`);
75
176
  }
76
- for (const { key, filePath } of keys) {
77
- const start = performance.now();
78
- if (options.logging) {
79
- console.info(`
80
- [Processing Start] key=${key}, filePath=${filePath}`);
81
- }
82
- try {
83
- const s3Key = `${options.savePath}/${key}`;
84
- if (options.logging) {
85
- console.info(`[S3 Key] ${s3Key}`);
86
- }
87
- let stream = void 0;
88
- let buffer = void 0;
89
- if (isHttp(filePath)) {
177
+ yield Promise.all(
178
+ keys.map(
179
+ (record, index) => limit(() => __async(null, null, function* () {
90
180
  if (options.logging) {
91
- console.info(`[Download Start] ${filePath}`);
181
+ console.info(
182
+ `Running p-limit task ${index}, limit: ${parallelLimit}`
183
+ );
92
184
  }
93
- const axiosResponse = yield axios.get(filePath, {
94
- responseType: "arraybuffer",
95
- headers: options.headers,
96
- httpsAgent: proxyAgent
97
- });
98
- if (options.logging) {
99
- console.info(`[Download Success] ${filePath}`);
100
- }
101
- buffer = Buffer.from(axiosResponse.data);
102
- } else {
103
- if (options.logging) {
104
- console.info(`[Read from FS] ${filePath}`);
105
- }
106
- stream = createReadStream(filePath);
107
- }
108
- const tagString = options.tags.map(
109
- (tag) => `${encodeURIComponent(tag.split(":")[0])}=${encodeURIComponent(tag.split(":")[1])}`
110
- ).join("&");
111
- if (!stream && !buffer) {
112
- if (options.logging) {
113
- console.warn(`[Error] Neither stream nor buffer is set for ${key}`);
114
- }
115
- throw new Error("buffer or stream not set");
116
- }
117
- if (options.logging) {
118
- console.info(`[Image Processing Start] ${key}`);
119
- }
120
- const image = buffer ? yield Jimp.fromBuffer(buffer) : yield Jimp.read(filePath);
121
- if (options.logging) {
122
- console.info(
123
- `[Image Loaded] key=${key}, width=${image.width}, height=${image.height}`
185
+ const processResult = yield processRecord(
186
+ record,
187
+ options,
188
+ proxyAgent || void 0
124
189
  );
125
- }
126
- const command = new PutObjectCommand({
127
- Body: buffer || stream,
128
- Bucket: BUCKET_NAME,
129
- Key: s3Key,
130
- Tagging: tagString || void 0,
131
- ContentType: `image/${extractFileInfo(key).extension}`,
132
- ContentDisposition: "inline",
133
- Metadata: {
134
- "img-width": image.width.toString(),
135
- "img-height": image.height.toString()
190
+ if (processResult.message) {
191
+ errored.push({
192
+ key: processResult.key,
193
+ filePath: processResult.filePath,
194
+ message: processResult.message
195
+ });
196
+ } else if (processResult.uploadUrl) {
197
+ result.push({
198
+ key: processResult.key,
199
+ filePath: processResult.filePath,
200
+ uploadUrl: processResult.uploadUrl
201
+ });
136
202
  }
137
- });
138
- result.push({
139
- key,
140
- filePath,
141
- uploadUrl: `https://${BUCKET_NAME}.s3.${process.env.AWS_REGION}.amazonaws.com/${s3Key}`
142
- });
143
- if (options.logging) {
144
- console.info(`[Uploading] ${key} to S3...`);
145
- }
146
- yield s3.send(command);
147
- if (options.logging) {
148
- console.info(`[Upload Success] ${key}`);
149
- }
150
- } catch (e) {
151
- const error = e;
152
- if (options.logging) {
153
- console.error(`[Upload Error] key=${key}, error=${error.message}`);
154
- }
155
- errored.push({
156
- key,
157
- filePath,
158
- message: error.message
159
- });
160
- }
161
- const end = performance.now();
162
- if (options.logging) {
163
- console.info(
164
- `[Processing End] key=${key}, duration=${(end - start).toFixed(0)}ms`
165
- );
166
- }
167
- }
203
+ }))
204
+ )
205
+ );
168
206
  if (options.logging) {
169
- console.timeEnd(`[SaveFiles] Total time`);
207
+ console.timeEnd(`[SaveFiles] Total time ${parallelLimit}`);
170
208
  console.info(
171
209
  `[SaveFiles] Completed. Success: ${result.length}, Failed: ${errored.length}`
172
210
  );
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "importer-storage",
3
3
  "private": false,
4
- "version": "1.0.16",
4
+ "version": "1.0.18",
5
5
  "main": "dist/index.js",
6
6
  "files": [
7
7
  "dist",
@@ -23,7 +23,8 @@
23
23
  "dotenv": "^16.5.0",
24
24
  "globals": "^16.2.0",
25
25
  "https-proxy-agent": "^7.0.6",
26
- "jimp": "^1.6.0"
26
+ "jimp": "^1.6.0",
27
+ "p-limit": "^7.2.0"
27
28
  },
28
29
  "devDependencies": {
29
30
  "@eslint/js": "^9.19.0",