@eik/core 2.2.3 → 2.4.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/CHANGELOG.md +14 -0
- package/lib/handlers/alias.post.js +9 -4
- package/lib/handlers/alias.put.js +10 -5
- package/lib/handlers/map.put.js +10 -6
- package/lib/handlers/pkg.put.js +31 -10
- package/lib/multipart/parser.js +76 -45
- package/lib/sinks/test.js +57 -0
- package/lib/utils/utils.js +10 -53
- package/package.json +4 -4
- package/types/handlers/alias.post.d.ts +30 -1
- package/types/handlers/alias.put.d.ts +30 -1
- package/types/handlers/auth.post.d.ts +30 -1
- package/types/handlers/pkg.put.d.ts +30 -1
- package/types/multipart/parser.d.ts +30 -1
- package/types/utils/utils.d.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# [2.4.0](https://github.com/eik-lib/core/compare/v2.3.0...v2.4.0) (2026-08-25)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* replace pipeline-based reads and writes with buffer operations ([#649](https://github.com/eik-lib/core/issues/649)) ([ace642f](https://github.com/eik-lib/core/commit/ace642f66ac08abcbda86c51b181bf107df68c5c))
|
|
7
|
+
|
|
8
|
+
# [2.3.0](https://github.com/eik-lib/core/compare/v2.2.3...v2.3.0) (2026-08-24)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* add traceId to upload logs and improve observability ([#647](https://github.com/eik-lib/core/issues/647)) ([32f8d38](https://github.com/eik-lib/core/commit/32f8d38290fab142cad9febc8379cd12f791cd70))
|
|
14
|
+
|
|
1
15
|
## [2.2.3](https://github.com/eik-lib/core/compare/v2.2.2...v2.2.3) (2026-08-22)
|
|
2
16
|
|
|
3
17
|
|
|
@@ -153,6 +153,7 @@ const AliasPost = class AliasPost {
|
|
|
153
153
|
*/
|
|
154
154
|
async handler(req, user, type, name, alias) {
|
|
155
155
|
const end = this._histogram.timer();
|
|
156
|
+
const traceId = req.traceId;
|
|
156
157
|
|
|
157
158
|
const pAlias = decodeUriComponent(alias);
|
|
158
159
|
const pName = decodeUriComponent(name);
|
|
@@ -163,7 +164,7 @@ const AliasPost = class AliasPost {
|
|
|
163
164
|
validators.type(type);
|
|
164
165
|
} catch (error) {
|
|
165
166
|
this._log.info(
|
|
166
|
-
`alias:post - Validation failed - ${error instanceof Error ? error.message : String(error)}`,
|
|
167
|
+
`alias:post - Validation failed - ${error instanceof Error ? error.message : String(error)} - TraceId: ${traceId}`,
|
|
167
168
|
);
|
|
168
169
|
const e = new HttpError.NotFound();
|
|
169
170
|
end({ labels: { success: false, status: e.status } });
|
|
@@ -175,7 +176,7 @@ const AliasPost = class AliasPost {
|
|
|
175
176
|
|
|
176
177
|
if (!org) {
|
|
177
178
|
this._log.debug(
|
|
178
|
-
`alias:post - Hostname does not match a configured organization - ${url.hostname}`,
|
|
179
|
+
`alias:post - Hostname does not match a configured organization - ${url.hostname} - TraceId: ${traceId}`,
|
|
179
180
|
);
|
|
180
181
|
const e = new HttpError.BadRequest();
|
|
181
182
|
end({ labels: { success: false, status: e.status, type } });
|
|
@@ -195,14 +196,18 @@ const AliasPost = class AliasPost {
|
|
|
195
196
|
const exist = await this._exist(incoming);
|
|
196
197
|
if (!exist) {
|
|
197
198
|
this._log.info(
|
|
198
|
-
`alias:post - Alias does not exists - Org: ${org} - Type: ${type} - Name: ${pName} - Alias: ${pAlias}`,
|
|
199
|
+
`alias:post - Alias does not exists - Org: ${org} - Type: ${type} - Name: ${pName} - Alias: ${pAlias} - TraceId: ${traceId}`,
|
|
199
200
|
);
|
|
200
201
|
const e = new HttpError.NotFound();
|
|
201
202
|
end({ labels: { success: false, status: e.status, type } });
|
|
202
203
|
throw e;
|
|
203
204
|
}
|
|
204
205
|
|
|
205
|
-
await this._parser(incoming);
|
|
206
|
+
const resolvedAlias = await this._parser(incoming);
|
|
207
|
+
|
|
208
|
+
this._log.info(
|
|
209
|
+
`alias:post - Alias created - Org: ${org} - Type: ${type} - Name: ${pName} - Alias: ${pAlias} - Version: ${resolvedAlias.version} - TraceId: ${traceId}`,
|
|
210
|
+
);
|
|
206
211
|
|
|
207
212
|
const outgoing = new HttpOutgoing();
|
|
208
213
|
outgoing.cacheControl = this._cacheControl || "";
|
|
@@ -94,7 +94,7 @@ const AliasPut = class AliasPut {
|
|
|
94
94
|
if (this._sink) await this._sink.read(path);
|
|
95
95
|
} catch (error) {
|
|
96
96
|
this._log.error(
|
|
97
|
-
`alias:
|
|
97
|
+
`alias:put - Unable to locate requested published package version - Version ${alias.name}@${alias.version}`,
|
|
98
98
|
);
|
|
99
99
|
this._log.trace(error);
|
|
100
100
|
throw new HttpError.NotFound();
|
|
@@ -153,6 +153,7 @@ const AliasPut = class AliasPut {
|
|
|
153
153
|
*/
|
|
154
154
|
async handler(req, user, type, name, alias) {
|
|
155
155
|
const end = this._histogram.timer();
|
|
156
|
+
const traceId = req.traceId;
|
|
156
157
|
|
|
157
158
|
const pAlias = decodeUriComponent(alias);
|
|
158
159
|
const pName = decodeUriComponent(name);
|
|
@@ -163,7 +164,7 @@ const AliasPut = class AliasPut {
|
|
|
163
164
|
validators.type(type);
|
|
164
165
|
} catch (error) {
|
|
165
166
|
this._log.info(
|
|
166
|
-
`alias:put - Validation failed - ${error instanceof Error ? error.message : String(error)}`,
|
|
167
|
+
`alias:put - Validation failed - ${error instanceof Error ? error.message : String(error)} - TraceId: ${traceId}`,
|
|
167
168
|
);
|
|
168
169
|
const e = new HttpError.BadRequest();
|
|
169
170
|
end({ labels: { success: false, status: e.status } });
|
|
@@ -175,7 +176,7 @@ const AliasPut = class AliasPut {
|
|
|
175
176
|
|
|
176
177
|
if (!org) {
|
|
177
178
|
this._log.debug(
|
|
178
|
-
`alias:put - Hostname does not match a configured organization - ${url.hostname}`,
|
|
179
|
+
`alias:put - Hostname does not match a configured organization - ${url.hostname} - TraceId: ${traceId}`,
|
|
179
180
|
);
|
|
180
181
|
const e = new HttpError.BadRequest();
|
|
181
182
|
end({ labels: { success: false, status: e.status, type } });
|
|
@@ -195,14 +196,18 @@ const AliasPut = class AliasPut {
|
|
|
195
196
|
const exist = await this._exist(incoming);
|
|
196
197
|
if (exist) {
|
|
197
198
|
this._log.info(
|
|
198
|
-
`alias:put - Alias exists - Org: ${org} - Type: ${type} - Name: ${pName} - Alias: ${pAlias}`,
|
|
199
|
+
`alias:put - Alias exists - Org: ${org} - Type: ${type} - Name: ${pName} - Alias: ${pAlias} - TraceId: ${traceId}`,
|
|
199
200
|
);
|
|
200
201
|
const e = new HttpError.Conflict();
|
|
201
202
|
end({ labels: { success: false, status: e.status, type } });
|
|
202
203
|
throw e;
|
|
203
204
|
}
|
|
204
205
|
|
|
205
|
-
await this._parser(incoming);
|
|
206
|
+
const resolvedAlias = await this._parser(incoming);
|
|
207
|
+
|
|
208
|
+
this._log.info(
|
|
209
|
+
`alias:put - Alias updated - Org: ${org} - Type: ${type} - Name: ${pName} - Alias: ${pAlias} - Version: ${resolvedAlias.version} - TraceId: ${traceId}`,
|
|
210
|
+
);
|
|
206
211
|
|
|
207
212
|
const outgoing = new HttpOutgoing();
|
|
208
213
|
outgoing.cacheControl = this._cacheControl || "";
|
package/lib/handlers/map.put.js
CHANGED
|
@@ -179,12 +179,14 @@ const MapPut = class MapPut {
|
|
|
179
179
|
|
|
180
180
|
if (!this._sink) throw new Error("No sink configured");
|
|
181
181
|
|
|
182
|
+
const traceId = incoming.request?.traceId;
|
|
183
|
+
|
|
182
184
|
try {
|
|
183
185
|
await this._sink.exist(path);
|
|
184
186
|
} catch {
|
|
185
187
|
// File does not exist — this is a new import map.
|
|
186
188
|
this._log.info(
|
|
187
|
-
`map:put - Version meta file did not exist in sink - Create new - Pathname: ${path}`,
|
|
189
|
+
`map:put - Version meta file did not exist in sink - Create new - Pathname: ${path} - TraceId: ${traceId}`,
|
|
188
190
|
);
|
|
189
191
|
return new Versions(incoming);
|
|
190
192
|
}
|
|
@@ -195,7 +197,7 @@ const MapPut = class MapPut {
|
|
|
195
197
|
// entire version history.
|
|
196
198
|
const obj = await readJSON(this._sink, path);
|
|
197
199
|
this._log.info(
|
|
198
|
-
`map:put - Successfully read version meta file from sink - Pathname: ${path}`,
|
|
200
|
+
`map:put - Successfully read version meta file from sink - Pathname: ${path} - TraceId: ${traceId}`,
|
|
199
201
|
);
|
|
200
202
|
return new Versions(obj);
|
|
201
203
|
}
|
|
@@ -206,9 +208,10 @@ const MapPut = class MapPut {
|
|
|
206
208
|
*/
|
|
207
209
|
async _writeVersions(incoming, versions) {
|
|
208
210
|
const path = createFilePathToVersion(incoming);
|
|
211
|
+
const traceId = incoming.request?.traceId;
|
|
209
212
|
await writeJSON(this._sink, path, versions, "application/json");
|
|
210
213
|
this._log.info(
|
|
211
|
-
`map:put - Successfully wrote version meta file to sink - Pathname: ${path}`,
|
|
214
|
+
`map:put - Successfully wrote version meta file to sink - Pathname: ${path} - TraceId: ${traceId}`,
|
|
212
215
|
);
|
|
213
216
|
}
|
|
214
217
|
|
|
@@ -220,6 +223,7 @@ const MapPut = class MapPut {
|
|
|
220
223
|
*/
|
|
221
224
|
async handler(req, user, name, version) {
|
|
222
225
|
const end = this._histogram.timer();
|
|
226
|
+
const traceId = req.traceId;
|
|
223
227
|
|
|
224
228
|
const pVersion = decodeUriComponent(version);
|
|
225
229
|
const pName = decodeUriComponent(name);
|
|
@@ -229,7 +233,7 @@ const MapPut = class MapPut {
|
|
|
229
233
|
validators.name(pName);
|
|
230
234
|
} catch (error) {
|
|
231
235
|
this._log.info(
|
|
232
|
-
`map:put - Validation failed - ${error instanceof Error ? error.message : String(error)}`,
|
|
236
|
+
`map:put - Validation failed - ${error instanceof Error ? error.message : String(error)} - TraceId: ${traceId}`,
|
|
233
237
|
);
|
|
234
238
|
const e = new HttpError.BadRequest();
|
|
235
239
|
end({ labels: { success: false, status: e.status } });
|
|
@@ -241,7 +245,7 @@ const MapPut = class MapPut {
|
|
|
241
245
|
|
|
242
246
|
if (!org) {
|
|
243
247
|
this._log.debug(
|
|
244
|
-
`map:put - Hostname does not match a configured organization - ${url.hostname}`,
|
|
248
|
+
`map:put - Hostname does not match a configured organization - ${url.hostname} - TraceId: ${traceId}`,
|
|
245
249
|
);
|
|
246
250
|
const e = new HttpError.BadRequest();
|
|
247
251
|
end({ labels: { success: false, status: e.status, type: "map" } });
|
|
@@ -266,7 +270,7 @@ const MapPut = class MapPut {
|
|
|
266
270
|
|
|
267
271
|
if (!versions.check(pVersion)) {
|
|
268
272
|
this._log.info(
|
|
269
|
-
`map:put - Semver version is lower than previous version of the package - Org: ${org} - Name: ${pName} - Version: ${pVersion}`,
|
|
273
|
+
`map:put - Semver version is lower than previous version of the package - Org: ${org} - Name: ${pName} - Version: ${pVersion} - TraceId: ${traceId}`,
|
|
270
274
|
);
|
|
271
275
|
const e = new HttpError.Conflict();
|
|
272
276
|
end({ labels: { success: false, status: e.status, type: "map" } });
|
package/lib/handlers/pkg.put.js
CHANGED
|
@@ -136,7 +136,7 @@ const PkgPut = class PkgPut {
|
|
|
136
136
|
"application/json",
|
|
137
137
|
);
|
|
138
138
|
this._log.info(
|
|
139
|
-
`pkg:put - Successfully wrote eik.json to sink - Pathname: ${eikJsonPath}`,
|
|
139
|
+
`pkg:put - Successfully wrote eik.json to sink - Pathname: ${eikJsonPath} - TraceId: ${incoming.request?.traceId}`,
|
|
140
140
|
);
|
|
141
141
|
|
|
142
142
|
const asset = new Asset({
|
|
@@ -167,7 +167,7 @@ const PkgPut = class PkgPut {
|
|
|
167
167
|
} catch {
|
|
168
168
|
// File does not exist — this is a new package.
|
|
169
169
|
this._log.info(
|
|
170
|
-
`pkg:put - Version meta file did not exist in sink - Create new - Pathname: ${path}`,
|
|
170
|
+
`pkg:put - Version meta file did not exist in sink - Create new - Pathname: ${path} - TraceId: ${incoming.request?.traceId}`,
|
|
171
171
|
);
|
|
172
172
|
return new Versions(incoming);
|
|
173
173
|
}
|
|
@@ -178,7 +178,7 @@ const PkgPut = class PkgPut {
|
|
|
178
178
|
// overwrite the index and erase the entire version history.
|
|
179
179
|
const obj = await readJSON(this._sink, path);
|
|
180
180
|
this._log.info(
|
|
181
|
-
`pkg:put - Successfully read version meta file from sink - Pathname: ${path}`,
|
|
181
|
+
`pkg:put - Successfully read version meta file from sink - Pathname: ${path} - TraceId: ${incoming.request?.traceId}`,
|
|
182
182
|
);
|
|
183
183
|
return new Versions(obj);
|
|
184
184
|
}
|
|
@@ -191,14 +191,14 @@ const PkgPut = class PkgPut {
|
|
|
191
191
|
try {
|
|
192
192
|
await readEikJson(this._sink, path);
|
|
193
193
|
this._log.info(
|
|
194
|
-
`pkg:put - Found version meta file from sink - Pathname: ${path}`,
|
|
194
|
+
`pkg:put - Found version meta file from sink - Pathname: ${path} - TraceId: ${incoming.request?.traceId}`,
|
|
195
195
|
);
|
|
196
196
|
return true;
|
|
197
197
|
// eslint-disable-next-line no-unused-vars
|
|
198
198
|
} catch (error) {
|
|
199
199
|
// File does not exist, its probably a new package
|
|
200
200
|
this._log.info(
|
|
201
|
-
`pkg:put - Did not find meta file in sink - Create new - Pathname: ${path}`,
|
|
201
|
+
`pkg:put - Did not find meta file in sink - Create new - Pathname: ${path} - TraceId: ${incoming.request?.traceId}`,
|
|
202
202
|
);
|
|
203
203
|
return false;
|
|
204
204
|
}
|
|
@@ -212,7 +212,7 @@ const PkgPut = class PkgPut {
|
|
|
212
212
|
const path = createFilePathToVersion(incoming);
|
|
213
213
|
await writeJSON(this._sink, path, versions, "application/json");
|
|
214
214
|
this._log.info(
|
|
215
|
-
`pkg:put - Successfully wrote version meta file to sink - Pathname: ${path}`,
|
|
215
|
+
`pkg:put - Successfully wrote version meta file to sink - Pathname: ${path} - TraceId: ${incoming.request?.traceId}`,
|
|
216
216
|
);
|
|
217
217
|
}
|
|
218
218
|
|
|
@@ -225,6 +225,7 @@ const PkgPut = class PkgPut {
|
|
|
225
225
|
*/
|
|
226
226
|
async handler(req, user, type, name, version) {
|
|
227
227
|
const end = this._histogram.timer();
|
|
228
|
+
const traceId = req.traceId;
|
|
228
229
|
|
|
229
230
|
const pVersion = decodeUriComponent(version);
|
|
230
231
|
const pName = decodeUriComponent(name);
|
|
@@ -235,7 +236,7 @@ const PkgPut = class PkgPut {
|
|
|
235
236
|
validators.type(type);
|
|
236
237
|
} catch (error) {
|
|
237
238
|
this._log.info(
|
|
238
|
-
`pkg:put - Validation failed - ${error instanceof Error ? error.message : String(error)}`,
|
|
239
|
+
`pkg:put - Validation failed - ${error instanceof Error ? error.message : String(error)} - TraceId: ${traceId}`,
|
|
239
240
|
);
|
|
240
241
|
const e = new HttpError.BadRequest();
|
|
241
242
|
end({ labels: { success: false, status: e.status } });
|
|
@@ -247,7 +248,7 @@ const PkgPut = class PkgPut {
|
|
|
247
248
|
|
|
248
249
|
if (!org) {
|
|
249
250
|
this._log.debug(
|
|
250
|
-
`pkg:put - Hostname does not match a configured organization - ${url.hostname}`,
|
|
251
|
+
`pkg:put - Hostname does not match a configured organization - ${url.hostname} - TraceId: ${traceId}`,
|
|
251
252
|
);
|
|
252
253
|
const e = new HttpError.BadRequest();
|
|
253
254
|
end({ labels: { success: false, status: e.status, type } });
|
|
@@ -264,11 +265,15 @@ const PkgPut = class PkgPut {
|
|
|
264
265
|
org,
|
|
265
266
|
});
|
|
266
267
|
|
|
268
|
+
this._log.info(
|
|
269
|
+
`pkg:put - Received upload - Name: ${pName} - Version: ${pVersion} - TraceId: ${traceId}`,
|
|
270
|
+
);
|
|
271
|
+
|
|
267
272
|
const versionExists = await this._readVersion(incoming);
|
|
268
273
|
|
|
269
274
|
if (versionExists) {
|
|
270
275
|
this._log.info(
|
|
271
|
-
`pkg:put - Semver version already exists for the package - Org: ${org} - Name: ${pName} - Version: ${pVersion}`,
|
|
276
|
+
`pkg:put - Semver version already exists for the package - Org: ${org} - Name: ${pName} - Version: ${pVersion} - TraceId: ${traceId}`,
|
|
272
277
|
);
|
|
273
278
|
const e = new HttpError.Conflict();
|
|
274
279
|
end({ labels: { success: false, status: e.status, type } });
|
|
@@ -276,6 +281,9 @@ const PkgPut = class PkgPut {
|
|
|
276
281
|
}
|
|
277
282
|
|
|
278
283
|
const versions = await this._readVersions(incoming).catch(() => {
|
|
284
|
+
this._log.error(
|
|
285
|
+
`pkg:put - Failed to read version meta from sink - Name: ${pName} - Version: ${pVersion} - TraceId: ${traceId}`,
|
|
286
|
+
);
|
|
279
287
|
const e = new HttpError.BadGateway();
|
|
280
288
|
end({ labels: { success: false, status: e.status, type } });
|
|
281
289
|
throw e;
|
|
@@ -290,6 +298,9 @@ const PkgPut = class PkgPut {
|
|
|
290
298
|
eikJsonAsset = await this._writeEikJson(incoming, eikJson);
|
|
291
299
|
// eslint-disable-next-line no-unused-vars
|
|
292
300
|
} catch (error) {
|
|
301
|
+
this._log.error(
|
|
302
|
+
`pkg:put - Failed to write eik.json to sink - Name: ${pName} - Version: ${pVersion} - TraceId: ${traceId}`,
|
|
303
|
+
);
|
|
293
304
|
const e = new HttpError.BadGateway();
|
|
294
305
|
end({ labels: { success: false, status: e.status, type } });
|
|
295
306
|
throw e;
|
|
@@ -300,10 +311,13 @@ const PkgPut = class PkgPut {
|
|
|
300
311
|
const pkgMetaPath = createFilePathToPackage(pkg);
|
|
301
312
|
await writeJSON(this._sink, pkgMetaPath, pkg, "application/json");
|
|
302
313
|
this._log.info(
|
|
303
|
-
`pkg:put - Successfully wrote package meta file to sink - Pathname: ${pkgMetaPath}`,
|
|
314
|
+
`pkg:put - Successfully wrote package meta file to sink - Pathname: ${pkgMetaPath} - TraceId: ${traceId}`,
|
|
304
315
|
);
|
|
305
316
|
// eslint-disable-next-line no-unused-vars
|
|
306
317
|
} catch (error) {
|
|
318
|
+
this._log.error(
|
|
319
|
+
`pkg:put - Failed to write package meta to sink - Name: ${pName} - Version: ${pVersion} - TraceId: ${traceId}`,
|
|
320
|
+
);
|
|
307
321
|
const e = new HttpError.BadGateway();
|
|
308
322
|
end({ labels: { success: false, status: e.status, type } });
|
|
309
323
|
throw e;
|
|
@@ -315,6 +329,9 @@ const PkgPut = class PkgPut {
|
|
|
315
329
|
await this._writeVersions(incoming, versions);
|
|
316
330
|
// eslint-disable-next-line no-unused-vars
|
|
317
331
|
} catch (error) {
|
|
332
|
+
this._log.error(
|
|
333
|
+
`pkg:put - Failed to write version meta to sink - Name: ${pName} - Version: ${pVersion} - TraceId: ${traceId}`,
|
|
334
|
+
);
|
|
318
335
|
const e = new HttpError.BadGateway();
|
|
319
336
|
end({ labels: { success: false, status: e.status, type } });
|
|
320
337
|
throw e;
|
|
@@ -325,6 +342,10 @@ const PkgPut = class PkgPut {
|
|
|
325
342
|
outgoing.statusCode = 303;
|
|
326
343
|
outgoing.location = createURIPathToPkgLog(pkg);
|
|
327
344
|
|
|
345
|
+
this._log.info(
|
|
346
|
+
`pkg:put - Upload completed - Name: ${pName} - Version: ${pVersion} - TraceId: ${traceId}`,
|
|
347
|
+
);
|
|
348
|
+
|
|
328
349
|
end({ labels: { status: outgoing.statusCode, type } });
|
|
329
350
|
|
|
330
351
|
return outgoing;
|
package/lib/multipart/parser.js
CHANGED
|
@@ -148,8 +148,10 @@ const MultipartParser = class MultipartParser {
|
|
|
148
148
|
*/
|
|
149
149
|
_handleFile({ fieldname, file, filename, incoming }) {
|
|
150
150
|
return new Promise((resolve, reject) => {
|
|
151
|
+
const traceId = incoming.request?.traceId;
|
|
152
|
+
|
|
151
153
|
this._log.info(
|
|
152
|
-
`multipart - Start extracting package - Field: ${fieldname} - Filename: ${filename}`,
|
|
154
|
+
`multipart - Start extracting package - Field: ${fieldname} - Filename: ${filename} - Name: ${incoming.name} - Version: ${incoming.version} - TraceId: ${traceId}`,
|
|
153
155
|
);
|
|
154
156
|
|
|
155
157
|
const ac = new AbortController();
|
|
@@ -167,6 +169,10 @@ const MultipartParser = class MultipartParser {
|
|
|
167
169
|
/** @type {import("tar").ReadEntry[]} */
|
|
168
170
|
const pendingEntries = [];
|
|
169
171
|
|
|
172
|
+
let totalFiles = 0;
|
|
173
|
+
let writtenFiles = 0;
|
|
174
|
+
let failedFiles = 0;
|
|
175
|
+
|
|
170
176
|
const drainPending = () => {
|
|
171
177
|
while (
|
|
172
178
|
runningWrites < MAX_CONCURRENT_WRITES &&
|
|
@@ -180,20 +186,34 @@ const MultipartParser = class MultipartParser {
|
|
|
180
186
|
incoming,
|
|
181
187
|
entry,
|
|
182
188
|
signal: ac.signal,
|
|
183
|
-
})
|
|
189
|
+
});
|
|
190
|
+
// Track counts on the raw promise without altering its
|
|
191
|
+
// resolve/reject value so the queue still propagates
|
|
192
|
+
// errors to Promise.all and resolves with Asset objects.
|
|
193
|
+
persist
|
|
194
|
+
.then(() => {
|
|
195
|
+
writtenFiles++;
|
|
196
|
+
})
|
|
197
|
+
.catch(() => {
|
|
198
|
+
failedFiles++;
|
|
199
|
+
});
|
|
200
|
+
const tracked = persist.finally(() => {
|
|
184
201
|
runningWrites--;
|
|
185
202
|
drainPending();
|
|
186
203
|
});
|
|
187
|
-
|
|
188
|
-
queue.push(
|
|
204
|
+
tracked.catch(() => {});
|
|
205
|
+
queue.push(tracked);
|
|
189
206
|
}
|
|
190
207
|
};
|
|
191
208
|
|
|
192
209
|
file.once("limit", () => {
|
|
193
210
|
this._log.warn(
|
|
194
|
-
`multipart - Uploaded package exceeds the max allowed file size - Field: ${fieldname} - Filename: ${filename} - Name: ${incoming.name} - Version: ${incoming.version} - Type: ${incoming.type} - Limit: ${this._pkgMaxFileSize} bytes`,
|
|
211
|
+
`multipart - Uploaded package exceeds the max allowed file size - Field: ${fieldname} - Filename: ${filename} - Name: ${incoming.name} - Version: ${incoming.version} - Type: ${incoming.type} - Limit: ${this._pkgMaxFileSize} bytes - TraceId: ${traceId}`,
|
|
195
212
|
);
|
|
196
213
|
ac.abort();
|
|
214
|
+
this._log.info(
|
|
215
|
+
`multipart - Upload aborted - Field: ${fieldname} - Running: ${runningWrites} - Pending: ${pendingEntries.length} - TraceId: ${traceId}`,
|
|
216
|
+
);
|
|
197
217
|
file.emit("error", new HttpError.PayloadTooLarge());
|
|
198
218
|
});
|
|
199
219
|
|
|
@@ -222,6 +242,9 @@ const MultipartParser = class MultipartParser {
|
|
|
222
242
|
capturedEikJson = JSON.parse(
|
|
223
243
|
Buffer.concat(chunks).toString("utf8"),
|
|
224
244
|
);
|
|
245
|
+
this._log.debug(
|
|
246
|
+
`multipart - Found eik.json in tar - Field: ${fieldname} - TraceId: ${traceId}`,
|
|
247
|
+
);
|
|
225
248
|
} catch {
|
|
226
249
|
// Malformed eik.json in tar — proceed without it.
|
|
227
250
|
}
|
|
@@ -235,6 +258,7 @@ const MultipartParser = class MultipartParser {
|
|
|
235
258
|
// Holding an entry without piping it blocks the tar parser
|
|
236
259
|
// at that position in the archive, creating natural
|
|
237
260
|
// backpressure on the upstream upload stream.
|
|
261
|
+
totalFiles++;
|
|
238
262
|
pendingEntries.push(entry);
|
|
239
263
|
drainPending();
|
|
240
264
|
},
|
|
@@ -243,7 +267,7 @@ const MultipartParser = class MultipartParser {
|
|
|
243
267
|
pipeline(file, extract, (error) => {
|
|
244
268
|
if (error) {
|
|
245
269
|
this._log.info(
|
|
246
|
-
`multipart - Uploaded package could not be extracted properly - Field: ${fieldname} - Filename: ${filename}`,
|
|
270
|
+
`multipart - Uploaded package could not be extracted properly - Field: ${fieldname} - Filename: ${filename} - Name: ${incoming.name} - Version: ${incoming.version} - Total: ${totalFiles} - Written: ${writtenFiles} - Failed: ${failedFiles} - TraceId: ${traceId}`,
|
|
247
271
|
);
|
|
248
272
|
this._log.trace(error);
|
|
249
273
|
|
|
@@ -272,8 +296,17 @@ const MultipartParser = class MultipartParser {
|
|
|
272
296
|
return;
|
|
273
297
|
}
|
|
274
298
|
|
|
299
|
+
if (!capturedEikJson) {
|
|
300
|
+
this._log.debug(
|
|
301
|
+
`multipart - No eik.json in tar, server will generate it - Field: ${fieldname} - TraceId: ${traceId}`,
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
|
|
275
305
|
Promise.all(queue)
|
|
276
306
|
.then((result) => {
|
|
307
|
+
this._log.info(
|
|
308
|
+
`multipart - Tar successfully unpacked - Field: ${fieldname} - Filename: ${filename} - Name: ${incoming.name} - Version: ${incoming.version} - Total: ${totalFiles} - Written: ${writtenFiles} - Failed: ${failedFiles} - TraceId: ${traceId}`,
|
|
309
|
+
);
|
|
277
310
|
const formFile = new FormFile({
|
|
278
311
|
name: fieldname,
|
|
279
312
|
value: result,
|
|
@@ -292,6 +325,8 @@ const MultipartParser = class MultipartParser {
|
|
|
292
325
|
* @param {{ incoming: any, entry: any, signal: AbortSignal }} options
|
|
293
326
|
*/
|
|
294
327
|
async _persistFile({ incoming, entry, signal }) {
|
|
328
|
+
const traceId = incoming.request?.traceId;
|
|
329
|
+
|
|
295
330
|
const asset = new Asset({
|
|
296
331
|
pathname: entry.path,
|
|
297
332
|
version: incoming.version,
|
|
@@ -301,60 +336,56 @@ const MultipartParser = class MultipartParser {
|
|
|
301
336
|
});
|
|
302
337
|
asset.size = entry.size;
|
|
303
338
|
|
|
304
|
-
const
|
|
339
|
+
const assetPath = createFilePathToAsset(asset);
|
|
305
340
|
|
|
306
|
-
this._log.
|
|
307
|
-
`multipart - Start writing asset to sink - Pathname: ${
|
|
341
|
+
this._log.debug(
|
|
342
|
+
`multipart - Start writing asset to sink - Pathname: ${assetPath} - TraceId: ${traceId}`,
|
|
308
343
|
);
|
|
309
344
|
|
|
310
345
|
if (!this._sink) {
|
|
311
346
|
throw new Error("No sink configured");
|
|
312
347
|
}
|
|
313
|
-
const writer = await this._sink.write(path, asset.mimeType);
|
|
314
|
-
|
|
315
|
-
const integrityStream = ssri.integrityStream({ single: true });
|
|
316
|
-
let hash = "";
|
|
317
|
-
integrityStream.once("integrity", (/** @type {any} */ integrity) => {
|
|
318
|
-
hash = integrity;
|
|
319
|
-
});
|
|
320
348
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
writer.destroy();
|
|
326
|
-
};
|
|
349
|
+
if (signal.aborted) {
|
|
350
|
+
entry.resume();
|
|
351
|
+
throw new Error("Aborted");
|
|
352
|
+
}
|
|
327
353
|
|
|
354
|
+
// Buffer all chunks from the tar entry — no pipeline or stream Transform needed
|
|
355
|
+
const chunks = [];
|
|
356
|
+
for await (const chunk of entry) {
|
|
328
357
|
if (signal.aborted) {
|
|
329
|
-
|
|
330
|
-
reject(new Error("Aborted"));
|
|
331
|
-
return;
|
|
358
|
+
throw new Error("Aborted");
|
|
332
359
|
}
|
|
360
|
+
chunks.push(chunk);
|
|
361
|
+
}
|
|
362
|
+
const buffer = Buffer.concat(chunks);
|
|
333
363
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
signal.removeEventListener("abort", onAbort);
|
|
338
|
-
|
|
339
|
-
if (error) {
|
|
340
|
-
this._log.error(
|
|
341
|
-
`multipart - Failed writing asset to sink - Pathname: ${path}`,
|
|
342
|
-
);
|
|
343
|
-
this._log.trace(error);
|
|
364
|
+
if (signal.aborted) {
|
|
365
|
+
throw new Error("Aborted");
|
|
366
|
+
}
|
|
344
367
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
368
|
+
// Compute integrity hash directly from the buffer
|
|
369
|
+
const integrity = ssri.fromData(buffer, { single: true });
|
|
370
|
+
asset.integrity = integrity.toString();
|
|
348
371
|
|
|
349
|
-
|
|
372
|
+
try {
|
|
373
|
+
await this._sink.writeBuffer(assetPath, asset.mimeType, buffer, {
|
|
374
|
+
traceId,
|
|
375
|
+
});
|
|
376
|
+
} catch (error) {
|
|
377
|
+
this._log.error(
|
|
378
|
+
`multipart - Failed writing asset to sink - Pathname: ${assetPath} - TraceId: ${traceId}`,
|
|
379
|
+
);
|
|
380
|
+
this._log.trace(error);
|
|
381
|
+
throw error;
|
|
382
|
+
}
|
|
350
383
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
384
|
+
this._log.debug(
|
|
385
|
+
`multipart - Successfully wrote asset to sink - Pathname: ${assetPath} - TraceId: ${traceId}`,
|
|
386
|
+
);
|
|
354
387
|
|
|
355
|
-
|
|
356
|
-
});
|
|
357
|
-
});
|
|
388
|
+
return asset;
|
|
358
389
|
}
|
|
359
390
|
};
|
|
360
391
|
export default MultipartParser;
|
package/lib/sinks/test.js
CHANGED
|
@@ -109,6 +109,63 @@ export default class SinkTest extends Sink {
|
|
|
109
109
|
|
|
110
110
|
// Common SINK API
|
|
111
111
|
|
|
112
|
+
/**
|
|
113
|
+
* @param {string} filePath
|
|
114
|
+
* @param {string} contentType
|
|
115
|
+
* @param {Buffer} buffer
|
|
116
|
+
* @param {{ traceId?: string }} [options]
|
|
117
|
+
* @returns {Promise<void>}
|
|
118
|
+
*/
|
|
119
|
+
// eslint-disable-next-line no-unused-vars
|
|
120
|
+
async writeBuffer(filePath, contentType, buffer, options = {}) {
|
|
121
|
+
const operation = "write";
|
|
122
|
+
try {
|
|
123
|
+
Sink.validateFilePath(filePath);
|
|
124
|
+
Sink.validateContentType(contentType);
|
|
125
|
+
} catch (error) {
|
|
126
|
+
this._counter.inc({ labels: { operation } });
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
const pathname = toUrlPathname(path.join(this._rootPath, filePath));
|
|
130
|
+
if (pathname.indexOf(this._rootPath) !== 0) {
|
|
131
|
+
this._counter.inc({ labels: { operation } });
|
|
132
|
+
throw new Error(`Directory traversal - ${filePath}`);
|
|
133
|
+
}
|
|
134
|
+
const entry = new Entry({ mimeType: contentType, payload: [buffer] });
|
|
135
|
+
this._state.set(pathname, entry);
|
|
136
|
+
this._counter.inc({ labels: { success: true, access: true, operation } });
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* @param {string} filePath
|
|
141
|
+
* @returns {Promise<Buffer>}
|
|
142
|
+
*/
|
|
143
|
+
async readBuffer(filePath) {
|
|
144
|
+
const operation = "read";
|
|
145
|
+
try {
|
|
146
|
+
Sink.validateFilePath(filePath);
|
|
147
|
+
} catch (error) {
|
|
148
|
+
this._counter.inc({ labels: { operation } });
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
const pathname = toUrlPathname(path.join(this._rootPath, filePath));
|
|
152
|
+
if (pathname.indexOf(this._rootPath) !== 0) {
|
|
153
|
+
this._counter.inc({ labels: { operation } });
|
|
154
|
+
throw new Error(`Directory traversal - ${filePath}`);
|
|
155
|
+
}
|
|
156
|
+
const entry = this._state.get(pathname);
|
|
157
|
+
if (!entry) {
|
|
158
|
+
this._counter.inc({ labels: { access: true, operation } });
|
|
159
|
+
throw new Error(`${filePath} does not exist`);
|
|
160
|
+
}
|
|
161
|
+
this._counter.inc({ labels: { success: true, access: true, operation } });
|
|
162
|
+
return Buffer.concat(
|
|
163
|
+
(entry.payload || []).map((/** @type {any} */ item) =>
|
|
164
|
+
Buffer.isBuffer(item) ? item : Buffer.from(item),
|
|
165
|
+
),
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
112
169
|
/**
|
|
113
170
|
* @param {string} filePath
|
|
114
171
|
* @param {string} contentType
|
package/lib/utils/utils.js
CHANGED
|
@@ -1,39 +1,14 @@
|
|
|
1
|
-
import { Writable,
|
|
1
|
+
import { Writable, pipeline } from "node:stream";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @param {any} sink
|
|
5
5
|
* @param {string} path
|
|
6
6
|
*/
|
|
7
|
-
const readJSON = (sink, path) =>
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
/** @type {any[]} */
|
|
12
|
-
const buffer = [];
|
|
13
|
-
const from = await sink.read(path);
|
|
14
|
-
|
|
15
|
-
const to = new Writable({
|
|
16
|
-
objectMode: false,
|
|
17
|
-
write(chunk, encoding, callback) {
|
|
18
|
-
buffer.push(chunk);
|
|
19
|
-
callback();
|
|
20
|
-
},
|
|
21
|
-
});
|
|
7
|
+
const readJSON = async (sink, path) => {
|
|
8
|
+
const buffer = await sink.readBuffer(path);
|
|
9
|
+
return JSON.parse(buffer.toString("utf8"));
|
|
10
|
+
};
|
|
22
11
|
|
|
23
|
-
pipeline(from.stream, to, (error) => {
|
|
24
|
-
if (error) return reject(error);
|
|
25
|
-
const str = Buffer.concat(buffer).toString("utf8");
|
|
26
|
-
try {
|
|
27
|
-
const obj = JSON.parse(str);
|
|
28
|
-
return resolve(obj);
|
|
29
|
-
} catch (err) {
|
|
30
|
-
return reject(err);
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
} catch (error) {
|
|
34
|
-
reject(error);
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
12
|
/**
|
|
38
13
|
* @param {any} sink
|
|
39
14
|
* @param {string} path
|
|
@@ -46,30 +21,12 @@ const readEikJson = (sink, path) => sink.exist(path);
|
|
|
46
21
|
* @param {any} obj
|
|
47
22
|
* @param {string} contentType
|
|
48
23
|
*/
|
|
49
|
-
const writeJSON = (sink, path, obj, contentType) =>
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const from = new Readable({
|
|
56
|
-
objectMode: false,
|
|
57
|
-
read() {
|
|
58
|
-
this.push(buffer);
|
|
59
|
-
this.push(null);
|
|
60
|
-
},
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
const to = await sink.write(path, contentType);
|
|
24
|
+
const writeJSON = async (sink, path, obj, contentType) => {
|
|
25
|
+
const buffer = Buffer.from(JSON.stringify(obj));
|
|
26
|
+
await sink.writeBuffer(path, contentType, buffer);
|
|
27
|
+
return buffer;
|
|
28
|
+
};
|
|
64
29
|
|
|
65
|
-
pipeline(from, to, (error) => {
|
|
66
|
-
if (error) return reject(error);
|
|
67
|
-
return resolve(buffer);
|
|
68
|
-
});
|
|
69
|
-
} catch (error) {
|
|
70
|
-
reject(error);
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
30
|
/**
|
|
74
31
|
* @param {any} from
|
|
75
32
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eik/core",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "Core server package",
|
|
5
5
|
"main": "lib/main.js",
|
|
6
6
|
"types": "./types/main.d.ts",
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
"author": "",
|
|
30
30
|
"license": "MIT",
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@eik/sink": "1.
|
|
33
|
-
"@eik/sink-file-system": "2.
|
|
34
|
-
"@eik/sink-memory": "2.
|
|
32
|
+
"@eik/sink": "1.4.0",
|
|
33
|
+
"@eik/sink-file-system": "2.4.0",
|
|
34
|
+
"@eik/sink-memory": "2.4.0",
|
|
35
35
|
"@metrics/client": "2.5.5",
|
|
36
36
|
"abslog": "2.4.4",
|
|
37
37
|
"busboy": "1.6.0",
|
|
@@ -55,7 +55,36 @@ declare const AliasPost: {
|
|
|
55
55
|
incoming: any;
|
|
56
56
|
entry: any;
|
|
57
57
|
signal: AbortSignal;
|
|
58
|
-
}): Promise<
|
|
58
|
+
}): Promise<{
|
|
59
|
+
_mimeType: string;
|
|
60
|
+
_type: string;
|
|
61
|
+
_size: number;
|
|
62
|
+
_integrity: string;
|
|
63
|
+
_pathname: string;
|
|
64
|
+
_version: string;
|
|
65
|
+
_name: string;
|
|
66
|
+
_org: string;
|
|
67
|
+
get integrity(): string;
|
|
68
|
+
set integrity(value: string);
|
|
69
|
+
get pathname(): string;
|
|
70
|
+
get mimeType(): string;
|
|
71
|
+
get version(): string;
|
|
72
|
+
get asset(): string;
|
|
73
|
+
get name(): string;
|
|
74
|
+
get type(): string;
|
|
75
|
+
set type(value: string);
|
|
76
|
+
get size(): number;
|
|
77
|
+
set size(value: number);
|
|
78
|
+
get org(): string;
|
|
79
|
+
toJSON(): {
|
|
80
|
+
integrity: string;
|
|
81
|
+
pathname: string;
|
|
82
|
+
mimeType: string;
|
|
83
|
+
type: string;
|
|
84
|
+
size: number;
|
|
85
|
+
};
|
|
86
|
+
get [Symbol.toStringTag](): string;
|
|
87
|
+
}>;
|
|
59
88
|
get [Symbol.toStringTag](): string;
|
|
60
89
|
};
|
|
61
90
|
get metrics(): Metrics;
|
|
@@ -55,7 +55,36 @@ declare const AliasPut: {
|
|
|
55
55
|
incoming: any;
|
|
56
56
|
entry: any;
|
|
57
57
|
signal: AbortSignal;
|
|
58
|
-
}): Promise<
|
|
58
|
+
}): Promise<{
|
|
59
|
+
_mimeType: string;
|
|
60
|
+
_type: string;
|
|
61
|
+
_size: number;
|
|
62
|
+
_integrity: string;
|
|
63
|
+
_pathname: string;
|
|
64
|
+
_version: string;
|
|
65
|
+
_name: string;
|
|
66
|
+
_org: string;
|
|
67
|
+
get integrity(): string;
|
|
68
|
+
set integrity(value: string);
|
|
69
|
+
get pathname(): string;
|
|
70
|
+
get mimeType(): string;
|
|
71
|
+
get version(): string;
|
|
72
|
+
get asset(): string;
|
|
73
|
+
get name(): string;
|
|
74
|
+
get type(): string;
|
|
75
|
+
set type(value: string);
|
|
76
|
+
get size(): number;
|
|
77
|
+
set size(value: number);
|
|
78
|
+
get org(): string;
|
|
79
|
+
toJSON(): {
|
|
80
|
+
integrity: string;
|
|
81
|
+
pathname: string;
|
|
82
|
+
mimeType: string;
|
|
83
|
+
type: string;
|
|
84
|
+
size: number;
|
|
85
|
+
};
|
|
86
|
+
get [Symbol.toStringTag](): string;
|
|
87
|
+
}>;
|
|
59
88
|
get [Symbol.toStringTag](): string;
|
|
60
89
|
};
|
|
61
90
|
get metrics(): Metrics;
|
|
@@ -55,7 +55,36 @@ declare const AuthPost: {
|
|
|
55
55
|
incoming: any;
|
|
56
56
|
entry: any;
|
|
57
57
|
signal: AbortSignal;
|
|
58
|
-
}): Promise<
|
|
58
|
+
}): Promise<{
|
|
59
|
+
_mimeType: string;
|
|
60
|
+
_type: string;
|
|
61
|
+
_size: number;
|
|
62
|
+
_integrity: string;
|
|
63
|
+
_pathname: string;
|
|
64
|
+
_version: string;
|
|
65
|
+
_name: string;
|
|
66
|
+
_org: string;
|
|
67
|
+
get integrity(): string;
|
|
68
|
+
set integrity(value: string);
|
|
69
|
+
get pathname(): string;
|
|
70
|
+
get mimeType(): string;
|
|
71
|
+
get version(): string;
|
|
72
|
+
get asset(): string;
|
|
73
|
+
get name(): string;
|
|
74
|
+
get type(): string;
|
|
75
|
+
set type(value: string);
|
|
76
|
+
get size(): number;
|
|
77
|
+
set size(value: number);
|
|
78
|
+
get org(): string;
|
|
79
|
+
toJSON(): {
|
|
80
|
+
integrity: string;
|
|
81
|
+
pathname: string;
|
|
82
|
+
mimeType: string;
|
|
83
|
+
type: string;
|
|
84
|
+
size: number;
|
|
85
|
+
};
|
|
86
|
+
get [Symbol.toStringTag](): string;
|
|
87
|
+
}>;
|
|
59
88
|
get [Symbol.toStringTag](): string;
|
|
60
89
|
};
|
|
61
90
|
get metrics(): Metrics;
|
|
@@ -58,7 +58,36 @@ declare const PkgPut: {
|
|
|
58
58
|
incoming: any;
|
|
59
59
|
entry: any;
|
|
60
60
|
signal: AbortSignal;
|
|
61
|
-
}): Promise<
|
|
61
|
+
}): Promise<{
|
|
62
|
+
_mimeType: string;
|
|
63
|
+
_type: string;
|
|
64
|
+
_size: number;
|
|
65
|
+
_integrity: string;
|
|
66
|
+
_pathname: string;
|
|
67
|
+
_version: string;
|
|
68
|
+
_name: string;
|
|
69
|
+
_org: string;
|
|
70
|
+
get integrity(): string;
|
|
71
|
+
set integrity(value: string);
|
|
72
|
+
get pathname(): string;
|
|
73
|
+
get mimeType(): string;
|
|
74
|
+
get version(): string;
|
|
75
|
+
get asset(): string;
|
|
76
|
+
get name(): string;
|
|
77
|
+
get type(): string;
|
|
78
|
+
set type(value: string);
|
|
79
|
+
get size(): number;
|
|
80
|
+
set size(value: number);
|
|
81
|
+
get org(): string;
|
|
82
|
+
toJSON(): {
|
|
83
|
+
integrity: string;
|
|
84
|
+
pathname: string;
|
|
85
|
+
mimeType: string;
|
|
86
|
+
type: string;
|
|
87
|
+
size: number;
|
|
88
|
+
};
|
|
89
|
+
get [Symbol.toStringTag](): string;
|
|
90
|
+
}>;
|
|
62
91
|
get [Symbol.toStringTag](): string;
|
|
63
92
|
};
|
|
64
93
|
get metrics(): Metrics;
|
|
@@ -58,7 +58,36 @@ declare const MultipartParser: {
|
|
|
58
58
|
incoming: any;
|
|
59
59
|
entry: any;
|
|
60
60
|
signal: AbortSignal;
|
|
61
|
-
}): Promise<
|
|
61
|
+
}): Promise<{
|
|
62
|
+
_mimeType: string;
|
|
63
|
+
_type: string;
|
|
64
|
+
_size: number;
|
|
65
|
+
_integrity: string;
|
|
66
|
+
_pathname: string;
|
|
67
|
+
_version: string;
|
|
68
|
+
_name: string;
|
|
69
|
+
_org: string;
|
|
70
|
+
get integrity(): string;
|
|
71
|
+
set integrity(value: string);
|
|
72
|
+
get pathname(): string;
|
|
73
|
+
get mimeType(): string;
|
|
74
|
+
get version(): string;
|
|
75
|
+
get asset(): string;
|
|
76
|
+
get name(): string;
|
|
77
|
+
get type(): string;
|
|
78
|
+
set type(value: string);
|
|
79
|
+
get size(): number;
|
|
80
|
+
set size(value: number);
|
|
81
|
+
get org(): string;
|
|
82
|
+
toJSON(): {
|
|
83
|
+
integrity: string;
|
|
84
|
+
pathname: string;
|
|
85
|
+
mimeType: string;
|
|
86
|
+
type: string;
|
|
87
|
+
size: number;
|
|
88
|
+
};
|
|
89
|
+
get [Symbol.toStringTag](): string;
|
|
90
|
+
}>;
|
|
62
91
|
get [Symbol.toStringTag](): string;
|
|
63
92
|
};
|
|
64
93
|
};
|
package/types/utils/utils.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export function readJSON(sink: any, path: string): Promise<any>;
|
|
|
9
9
|
* @param {any} obj
|
|
10
10
|
* @param {string} contentType
|
|
11
11
|
*/
|
|
12
|
-
export function writeJSON(sink: any, path: string, obj: any, contentType: string): Promise<
|
|
12
|
+
export function writeJSON(sink: any, path: string, obj: any, contentType: string): Promise<Buffer<ArrayBuffer>>;
|
|
13
13
|
/**
|
|
14
14
|
* @param {any} from
|
|
15
15
|
*/
|