@kiyasov/platform-hono 1.6.1 → 2.0.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/.claude/settings.local.json +7 -1
- package/dist/cjs/src/adapters/hono-adapter.d.ts +1 -0
- package/dist/cjs/src/adapters/hono-adapter.js +14 -3
- package/dist/cjs/src/adapters/hono-adapter.js.map +1 -1
- package/dist/cjs/src/drivers/graphQLUpload/Upload.d.ts +5 -7
- package/dist/cjs/src/drivers/graphQLUpload/Upload.js.map +1 -1
- package/dist/cjs/src/drivers/graphQLUpload/fs-capacitor.d.ts +20 -8
- package/dist/cjs/src/drivers/graphQLUpload/fs-capacitor.js +111 -58
- package/dist/cjs/src/drivers/graphQLUpload/fs-capacitor.js.map +1 -1
- package/dist/cjs/src/drivers/graphQLUpload/index.d.ts +9 -3
- package/dist/cjs/src/drivers/graphQLUpload/index.js +21 -3
- package/dist/cjs/src/drivers/graphQLUpload/index.js.map +1 -1
- package/dist/cjs/src/drivers/graphQLUpload/processRequest.d.ts +8 -1
- package/dist/cjs/src/drivers/graphQLUpload/processRequest.js +43 -37
- package/dist/cjs/src/drivers/graphQLUpload/processRequest.js.map +1 -1
- package/dist/cjs/src/drivers/graphQLUpload/storage/capacitor-storage.d.ts +15 -0
- package/dist/cjs/src/drivers/graphQLUpload/storage/capacitor-storage.js +47 -0
- package/dist/cjs/src/drivers/graphQLUpload/storage/capacitor-storage.js.map +1 -0
- package/dist/cjs/src/drivers/graphQLUpload/storage/index.d.ts +3 -0
- package/dist/cjs/src/drivers/graphQLUpload/storage/index.js +20 -0
- package/dist/cjs/src/drivers/graphQLUpload/storage/index.js.map +1 -0
- package/dist/cjs/src/drivers/graphQLUpload/storage/memory-storage.d.ts +13 -0
- package/dist/cjs/src/drivers/graphQLUpload/storage/memory-storage.js +31 -0
- package/dist/cjs/src/drivers/graphQLUpload/storage/memory-storage.js.map +1 -0
- package/dist/cjs/src/drivers/graphQLUpload/storage/storage.d.ts +17 -0
- package/dist/cjs/src/drivers/graphQLUpload/storage/storage.js +3 -0
- package/dist/cjs/src/drivers/graphQLUpload/storage/storage.js.map +1 -0
- package/dist/cjs/src/drivers/graphQLUpload/utils/file.d.ts +6 -0
- package/dist/cjs/src/drivers/graphQLUpload/utils/file.js +62 -0
- package/dist/cjs/src/drivers/graphQLUpload/utils/file.js.map +1 -0
- package/dist/cjs/src/drivers/graphQLUpload/utils/index.d.ts +2 -0
- package/dist/cjs/src/drivers/graphQLUpload/utils/index.js +19 -0
- package/dist/cjs/src/drivers/graphQLUpload/utils/index.js.map +1 -0
- package/dist/cjs/src/drivers/graphQLUpload/utils/validators.d.ts +18 -0
- package/dist/cjs/src/drivers/graphQLUpload/utils/validators.js +171 -0
- package/dist/cjs/src/drivers/graphQLUpload/utils/validators.js.map +1 -0
- package/dist/cjs/src/multer/index.d.ts +1 -0
- package/dist/cjs/src/multer/index.js +1 -0
- package/dist/cjs/src/multer/index.js.map +1 -1
- package/dist/cjs/src/multer/interceptors/any-files-interceptor.d.ts +2 -2
- package/dist/cjs/src/multer/interceptors/any-files-interceptor.js +6 -23
- package/dist/cjs/src/multer/interceptors/any-files-interceptor.js.map +1 -1
- package/dist/cjs/src/multer/interceptors/base-interceptor.d.ts +6 -0
- package/dist/cjs/src/multer/interceptors/base-interceptor.js +26 -0
- package/dist/cjs/src/multer/interceptors/base-interceptor.js.map +1 -0
- package/dist/cjs/src/multer/interceptors/file-fields-interceptor.d.ts +2 -2
- package/dist/cjs/src/multer/interceptors/file-fields-interceptor.js +7 -24
- package/dist/cjs/src/multer/interceptors/file-fields-interceptor.js.map +1 -1
- package/dist/cjs/src/multer/interceptors/file-interceptor.d.ts +2 -2
- package/dist/cjs/src/multer/interceptors/file-interceptor.js +6 -23
- package/dist/cjs/src/multer/interceptors/file-interceptor.js.map +1 -1
- package/dist/cjs/src/multer/interceptors/files-interceptor.d.ts +2 -2
- package/dist/cjs/src/multer/interceptors/files-interceptor.js +6 -23
- package/dist/cjs/src/multer/interceptors/files-interceptor.js.map +1 -1
- package/dist/cjs/src/multer/interceptors/index.d.ts +1 -0
- package/dist/cjs/src/multer/interceptors/index.js +1 -0
- package/dist/cjs/src/multer/interceptors/index.js.map +1 -1
- package/dist/cjs/src/multer/multipart/handlers/any-files.d.ts +2 -8
- package/dist/cjs/src/multer/multipart/handlers/any-files.js +12 -25
- package/dist/cjs/src/multer/multipart/handlers/any-files.js.map +1 -1
- package/dist/cjs/src/multer/multipart/handlers/base-handler.d.ts +42 -0
- package/dist/cjs/src/multer/multipart/handlers/base-handler.js +106 -0
- package/dist/cjs/src/multer/multipart/handlers/base-handler.js.map +1 -0
- package/dist/cjs/src/multer/multipart/handlers/file-fields.d.ts +3 -10
- package/dist/cjs/src/multer/multipart/handlers/file-fields.js +19 -33
- package/dist/cjs/src/multer/multipart/handlers/file-fields.js.map +1 -1
- package/dist/cjs/src/multer/multipart/handlers/index.d.ts +6 -1
- package/dist/cjs/src/multer/multipart/handlers/index.js +13 -0
- package/dist/cjs/src/multer/multipart/handlers/index.js.map +1 -1
- package/dist/cjs/src/multer/multipart/handlers/multiple-files.d.ts +2 -8
- package/dist/cjs/src/multer/multipart/handlers/multiple-files.js +18 -36
- package/dist/cjs/src/multer/multipart/handlers/multiple-files.js.map +1 -1
- package/dist/cjs/src/multer/multipart/handlers/single-file.d.ts +2 -8
- package/dist/cjs/src/multer/multipart/handlers/single-file.js +11 -33
- package/dist/cjs/src/multer/multipart/handlers/single-file.js.map +1 -1
- package/dist/cjs/src/multer/multipart/index.d.ts +1 -1
- package/dist/cjs/src/multer/multipart/options.d.ts +10 -16
- package/dist/cjs/src/multer/multipart/options.js.map +1 -1
- package/dist/cjs/src/multer/multipart/request.js +14 -3
- package/dist/cjs/src/multer/multipart/request.js.map +1 -1
- package/dist/cjs/src/multer/storage/disk-storage.d.ts +2 -1
- package/dist/cjs/src/multer/storage/disk-storage.js +2 -1
- package/dist/cjs/src/multer/storage/disk-storage.js.map +1 -1
- package/dist/cjs/src/multer/storage/memory-storage.d.ts +2 -11
- package/dist/cjs/src/multer/storage/memory-storage.js +6 -4
- package/dist/cjs/src/multer/storage/memory-storage.js.map +1 -1
- package/dist/cjs/src/multer/storage/storage.d.ts +6 -5
- package/dist/cjs/src/multer/utils/file.d.ts +6 -0
- package/dist/cjs/src/multer/utils/file.js +62 -0
- package/dist/cjs/src/multer/utils/file.js.map +1 -0
- package/dist/cjs/src/multer/utils/index.d.ts +2 -0
- package/dist/cjs/src/multer/utils/index.js +19 -0
- package/dist/cjs/src/multer/utils/index.js.map +1 -0
- package/dist/cjs/src/multer/utils/validators.d.ts +18 -0
- package/dist/cjs/src/multer/utils/validators.js +171 -0
- package/dist/cjs/src/multer/utils/validators.js.map +1 -0
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/adapters/hono-adapter.d.ts +1 -0
- package/dist/esm/src/adapters/hono-adapter.js +14 -3
- package/dist/esm/src/adapters/hono-adapter.js.map +1 -1
- package/dist/esm/src/drivers/graphQLUpload/Upload.d.ts +5 -7
- package/dist/esm/src/drivers/graphQLUpload/Upload.js.map +1 -1
- package/dist/esm/src/drivers/graphQLUpload/fs-capacitor.d.ts +20 -8
- package/dist/esm/src/drivers/graphQLUpload/fs-capacitor.js +112 -59
- package/dist/esm/src/drivers/graphQLUpload/fs-capacitor.js.map +1 -1
- package/dist/esm/src/drivers/graphQLUpload/index.d.ts +9 -3
- package/dist/esm/src/drivers/graphQLUpload/index.js +7 -3
- package/dist/esm/src/drivers/graphQLUpload/index.js.map +1 -1
- package/dist/esm/src/drivers/graphQLUpload/processRequest.d.ts +8 -1
- package/dist/esm/src/drivers/graphQLUpload/processRequest.js +42 -36
- package/dist/esm/src/drivers/graphQLUpload/processRequest.js.map +1 -1
- package/dist/esm/src/drivers/graphQLUpload/storage/capacitor-storage.d.ts +15 -0
- package/dist/esm/src/drivers/graphQLUpload/storage/capacitor-storage.js +43 -0
- package/dist/esm/src/drivers/graphQLUpload/storage/capacitor-storage.js.map +1 -0
- package/dist/esm/src/drivers/graphQLUpload/storage/index.d.ts +3 -0
- package/dist/esm/src/drivers/graphQLUpload/storage/index.js +4 -0
- package/dist/esm/src/drivers/graphQLUpload/storage/index.js.map +1 -0
- package/dist/esm/src/drivers/graphQLUpload/storage/memory-storage.d.ts +13 -0
- package/dist/esm/src/drivers/graphQLUpload/storage/memory-storage.js +27 -0
- package/dist/esm/src/drivers/graphQLUpload/storage/memory-storage.js.map +1 -0
- package/dist/esm/src/drivers/graphQLUpload/storage/storage.d.ts +17 -0
- package/dist/esm/src/drivers/graphQLUpload/storage/storage.js +2 -0
- package/dist/esm/src/drivers/graphQLUpload/storage/storage.js.map +1 -0
- package/dist/esm/src/drivers/graphQLUpload/utils/file.d.ts +6 -0
- package/dist/esm/src/drivers/graphQLUpload/utils/file.js +54 -0
- package/dist/esm/src/drivers/graphQLUpload/utils/file.js.map +1 -0
- package/dist/esm/src/drivers/graphQLUpload/utils/index.d.ts +2 -0
- package/dist/esm/src/drivers/graphQLUpload/utils/index.js +3 -0
- package/dist/esm/src/drivers/graphQLUpload/utils/index.js.map +1 -0
- package/dist/esm/src/drivers/graphQLUpload/utils/validators.d.ts +18 -0
- package/dist/esm/src/drivers/graphQLUpload/utils/validators.js +167 -0
- package/dist/esm/src/drivers/graphQLUpload/utils/validators.js.map +1 -0
- package/dist/esm/src/multer/index.d.ts +1 -0
- package/dist/esm/src/multer/index.js +1 -0
- package/dist/esm/src/multer/index.js.map +1 -1
- package/dist/esm/src/multer/interceptors/any-files-interceptor.d.ts +2 -2
- package/dist/esm/src/multer/interceptors/any-files-interceptor.js +6 -23
- package/dist/esm/src/multer/interceptors/any-files-interceptor.js.map +1 -1
- package/dist/esm/src/multer/interceptors/base-interceptor.d.ts +6 -0
- package/dist/esm/src/multer/interceptors/base-interceptor.js +23 -0
- package/dist/esm/src/multer/interceptors/base-interceptor.js.map +1 -0
- package/dist/esm/src/multer/interceptors/file-fields-interceptor.d.ts +2 -2
- package/dist/esm/src/multer/interceptors/file-fields-interceptor.js +7 -24
- package/dist/esm/src/multer/interceptors/file-fields-interceptor.js.map +1 -1
- package/dist/esm/src/multer/interceptors/file-interceptor.d.ts +2 -2
- package/dist/esm/src/multer/interceptors/file-interceptor.js +6 -23
- package/dist/esm/src/multer/interceptors/file-interceptor.js.map +1 -1
- package/dist/esm/src/multer/interceptors/files-interceptor.d.ts +2 -2
- package/dist/esm/src/multer/interceptors/files-interceptor.js +6 -23
- package/dist/esm/src/multer/interceptors/files-interceptor.js.map +1 -1
- package/dist/esm/src/multer/interceptors/index.d.ts +1 -0
- package/dist/esm/src/multer/interceptors/index.js +1 -0
- package/dist/esm/src/multer/interceptors/index.js.map +1 -1
- package/dist/esm/src/multer/multipart/handlers/any-files.d.ts +2 -8
- package/dist/esm/src/multer/multipart/handlers/any-files.js +12 -25
- package/dist/esm/src/multer/multipart/handlers/any-files.js.map +1 -1
- package/dist/esm/src/multer/multipart/handlers/base-handler.d.ts +42 -0
- package/dist/esm/src/multer/multipart/handlers/base-handler.js +102 -0
- package/dist/esm/src/multer/multipart/handlers/base-handler.js.map +1 -0
- package/dist/esm/src/multer/multipart/handlers/file-fields.d.ts +3 -10
- package/dist/esm/src/multer/multipart/handlers/file-fields.js +19 -33
- package/dist/esm/src/multer/multipart/handlers/file-fields.js.map +1 -1
- package/dist/esm/src/multer/multipart/handlers/index.d.ts +6 -1
- package/dist/esm/src/multer/multipart/handlers/index.js +6 -1
- package/dist/esm/src/multer/multipart/handlers/index.js.map +1 -1
- package/dist/esm/src/multer/multipart/handlers/multiple-files.d.ts +2 -8
- package/dist/esm/src/multer/multipart/handlers/multiple-files.js +18 -36
- package/dist/esm/src/multer/multipart/handlers/multiple-files.js.map +1 -1
- package/dist/esm/src/multer/multipart/handlers/single-file.d.ts +2 -8
- package/dist/esm/src/multer/multipart/handlers/single-file.js +11 -33
- package/dist/esm/src/multer/multipart/handlers/single-file.js.map +1 -1
- package/dist/esm/src/multer/multipart/index.d.ts +1 -1
- package/dist/esm/src/multer/multipart/options.d.ts +10 -16
- package/dist/esm/src/multer/multipart/options.js.map +1 -1
- package/dist/esm/src/multer/multipart/request.js +14 -3
- package/dist/esm/src/multer/multipart/request.js.map +1 -1
- package/dist/esm/src/multer/storage/disk-storage.d.ts +2 -1
- package/dist/esm/src/multer/storage/disk-storage.js +2 -1
- package/dist/esm/src/multer/storage/disk-storage.js.map +1 -1
- package/dist/esm/src/multer/storage/memory-storage.d.ts +2 -11
- package/dist/esm/src/multer/storage/memory-storage.js +6 -4
- package/dist/esm/src/multer/storage/memory-storage.js.map +1 -1
- package/dist/esm/src/multer/storage/storage.d.ts +6 -5
- package/dist/esm/src/multer/utils/file.d.ts +6 -0
- package/dist/esm/src/multer/utils/file.js +54 -0
- package/dist/esm/src/multer/utils/file.js.map +1 -0
- package/dist/esm/src/multer/utils/index.d.ts +2 -0
- package/dist/esm/src/multer/utils/index.js +3 -0
- package/dist/esm/src/multer/utils/index.js.map +1 -0
- package/dist/esm/src/multer/utils/validators.d.ts +18 -0
- package/dist/esm/src/multer/utils/validators.js +167 -0
- package/dist/esm/src/multer/utils/validators.js.map +1 -0
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/package.json +6 -4
- package/src/adapters/hono-adapter.ts +18 -3
- package/src/drivers/graphQLUpload/Upload.ts +21 -14
- package/src/drivers/graphQLUpload/fs-capacitor.ts +240 -116
- package/src/drivers/graphQLUpload/index.ts +37 -3
- package/src/drivers/graphQLUpload/processRequest.ts +92 -38
- package/src/drivers/graphQLUpload/storage/capacitor-storage.ts +86 -0
- package/src/drivers/graphQLUpload/storage/index.ts +3 -0
- package/src/drivers/graphQLUpload/storage/memory-storage.ts +62 -0
- package/src/drivers/graphQLUpload/storage/storage.ts +52 -0
- package/src/drivers/graphQLUpload/utils/file.ts +109 -0
- package/src/drivers/graphQLUpload/utils/index.ts +2 -0
- package/src/drivers/graphQLUpload/utils/validators.ts +219 -0
- package/src/multer/index.ts +1 -0
- package/src/multer/interceptors/any-files-interceptor.ts +12 -43
- package/src/multer/interceptors/base-interceptor.ts +54 -0
- package/src/multer/interceptors/file-fields-interceptor.ts +14 -48
- package/src/multer/interceptors/file-interceptor.ts +12 -44
- package/src/multer/interceptors/files-interceptor.ts +13 -45
- package/src/multer/interceptors/index.ts +1 -0
- package/src/multer/multipart/handlers/any-files.ts +14 -32
- package/src/multer/multipart/handlers/base-handler.ts +204 -0
- package/src/multer/multipart/handlers/file-fields.ts +29 -57
- package/src/multer/multipart/handlers/index.ts +11 -1
- package/src/multer/multipart/handlers/multiple-files.ts +23 -54
- package/src/multer/multipart/handlers/single-file.ts +14 -47
- package/src/multer/multipart/index.ts +1 -1
- package/src/multer/multipart/options.ts +26 -8
- package/src/multer/multipart/request.ts +19 -3
- package/src/multer/storage/disk-storage.ts +2 -1
- package/src/multer/storage/memory-storage.ts +13 -6
- package/src/multer/storage/storage.ts +12 -5
- package/src/multer/utils/file.ts +109 -0
- package/src/multer/utils/index.ts +2 -0
- package/src/multer/utils/validators.ts +219 -0
- package/test/README.md +247 -0
- package/test/graphql-upload.test.ts +509 -0
- package/test/helpers.ts +70 -0
- package/test/integration.test.ts +197 -0
- package/test/interceptors-e2e.test.ts +362 -0
- package/test/multipart-upload.test.ts +354 -0
- package/test/smoke.test.ts +227 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kiyasov/platform-hono",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Nest adapter for Hono",
|
|
5
5
|
"author": "Islam Kiiasov",
|
|
6
6
|
"repository": {
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
"server",
|
|
21
21
|
"rest",
|
|
22
22
|
"api",
|
|
23
|
-
"typescript"
|
|
23
|
+
"typescript",
|
|
24
|
+
"graphql"
|
|
24
25
|
],
|
|
25
26
|
"main": "./dist/cjs/index.js",
|
|
26
27
|
"module": "./dist/esm/index.js",
|
|
@@ -58,7 +59,6 @@
|
|
|
58
59
|
"@swc/core": "^1.15.8",
|
|
59
60
|
"@types/autocannon": "^7.12.7",
|
|
60
61
|
"@types/bun": "^1.3.5",
|
|
61
|
-
"@types/busboy": "^1.5.4",
|
|
62
62
|
"autocannon": "^8.0.0",
|
|
63
63
|
"bun": "^1.3.5",
|
|
64
64
|
"class-transformer": "^0.5.1",
|
|
@@ -86,7 +86,9 @@
|
|
|
86
86
|
"build": "bun run build:esm && bun run build:cjs",
|
|
87
87
|
"dev": "cd example && nest start -w --copy-files --exec \"bun run --inspect\"",
|
|
88
88
|
"benchmark": "bun dev:bun & ( sleep 5 && autocannon -c 200 -d 5 -p 10 http://localhost:3000 )",
|
|
89
|
-
"benchmark:file": "bun run dev:bun & ( sleep 5 && bun run ./benchmarks/benchmark.mjs)"
|
|
89
|
+
"benchmark:file": "bun run dev:bun & ( sleep 5 && bun run ./benchmarks/benchmark.mjs)",
|
|
90
|
+
"test": "bun test",
|
|
91
|
+
"test:watch": "bun test --watch"
|
|
90
92
|
},
|
|
91
93
|
"trustedDependencies": [
|
|
92
94
|
"@apollo/protobufjs",
|
|
@@ -221,7 +221,8 @@ export class HonoAdapter extends AbstractHttpAdapter<
|
|
|
221
221
|
|
|
222
222
|
public setErrorHandler(handler: ErrorHandler) {
|
|
223
223
|
this.instance.onError(async (err: Error, ctx: Context) => {
|
|
224
|
-
|
|
224
|
+
const argumentsHost = this.createArgumentsHost(ctx);
|
|
225
|
+
await handler(err, ctx.req, argumentsHost);
|
|
225
226
|
|
|
226
227
|
return this.getBody(ctx);
|
|
227
228
|
});
|
|
@@ -229,7 +230,8 @@ export class HonoAdapter extends AbstractHttpAdapter<
|
|
|
229
230
|
|
|
230
231
|
public setNotFoundHandler(handler: RequestHandler) {
|
|
231
232
|
this.instance.notFound(async (ctx: Context) => {
|
|
232
|
-
|
|
233
|
+
const argumentsHost = this.createArgumentsHost(ctx);
|
|
234
|
+
await handler(ctx.req, argumentsHost);
|
|
233
235
|
await this.status(ctx, HttpStatus.NOT_FOUND);
|
|
234
236
|
|
|
235
237
|
return this.getBody(ctx, 'Not Found');
|
|
@@ -411,7 +413,8 @@ export class HonoAdapter extends AbstractHttpAdapter<
|
|
|
411
413
|
).bind(this.instance);
|
|
412
414
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
413
415
|
routeMethod(path, async (ctx: Context, next: Function) => {
|
|
414
|
-
|
|
416
|
+
const argumentsHost = this.createArgumentsHost(ctx);
|
|
417
|
+
await callback(ctx.req, argumentsHost, next);
|
|
415
418
|
});
|
|
416
419
|
};
|
|
417
420
|
}
|
|
@@ -434,4 +437,16 @@ export class HonoAdapter extends AbstractHttpAdapter<
|
|
|
434
437
|
},
|
|
435
438
|
});
|
|
436
439
|
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Creates a NestJS-compatible ArgumentsHost wrapper around Hono Context
|
|
443
|
+
*/
|
|
444
|
+
private createArgumentsHost(ctx: Context) {
|
|
445
|
+
const argumentsHost = {
|
|
446
|
+
getRequest: () => ctx.req,
|
|
447
|
+
getResponse: () => ctx,
|
|
448
|
+
switchToHttp: () => argumentsHost,
|
|
449
|
+
};
|
|
450
|
+
return argumentsHost;
|
|
451
|
+
}
|
|
437
452
|
}
|
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
import { ReadStream, ReadStreamOptions, WriteStream } from './fs-capacitor';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
capacitor
|
|
2
|
+
import { StorageFile } from './storage';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Represents a file upload with metadata and stream access.
|
|
6
|
+
* Compatible with capacitor storage for streaming file content.
|
|
7
|
+
*
|
|
8
|
+
* Extends StorageFile with optional stream support for capacitor storage.
|
|
9
|
+
*/
|
|
10
|
+
export interface FileUpload extends StorageFile {
|
|
11
|
+
/** Creates a readable stream for the file content (capacitor storage only) */
|
|
12
|
+
createReadStream?(options?: ReadStreamOptions): ReadStream;
|
|
13
|
+
/** The write stream capacitor (capacitor storage only) */
|
|
14
|
+
capacitor?: WriteStream;
|
|
15
|
+
/** Original File object if available */
|
|
16
|
+
file?: File;
|
|
12
17
|
}
|
|
13
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Upload promise wrapper for GraphQL file uploads.
|
|
21
|
+
* Manages the asynchronous file upload process with proper error handling.
|
|
22
|
+
*/
|
|
14
23
|
export class Upload {
|
|
15
24
|
promise: Promise<FileUpload>;
|
|
16
25
|
resolve: (file?: FileUpload) => void;
|
|
@@ -21,15 +30,13 @@ export class Upload {
|
|
|
21
30
|
this.promise = new Promise((resolve, reject) => {
|
|
22
31
|
this.resolve = (file) => {
|
|
23
32
|
this.file = file;
|
|
24
|
-
|
|
25
33
|
resolve(file);
|
|
26
34
|
};
|
|
27
|
-
|
|
28
35
|
this.reject = reject;
|
|
29
36
|
});
|
|
30
37
|
|
|
31
|
-
// Prevent
|
|
32
|
-
// https://github.com/nodejs/node/issues/20392
|
|
38
|
+
// Prevent unhandled promise rejection errors
|
|
39
|
+
// See: https://github.com/nodejs/node/issues/20392
|
|
33
40
|
this.promise.catch(() => {});
|
|
34
41
|
}
|
|
35
42
|
}
|
|
@@ -1,30 +1,65 @@
|
|
|
1
1
|
import { randomBytes } from 'crypto';
|
|
2
2
|
import { EventEmitter } from 'events';
|
|
3
|
-
import {
|
|
3
|
+
import { close, closeSync, open, read, unlink, unlinkSync, write } from 'fs';
|
|
4
4
|
import { tmpdir } from 'os';
|
|
5
5
|
import { join } from 'path';
|
|
6
6
|
import { Readable, ReadableOptions, Writable, WritableOptions } from 'stream';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Error thrown when attempting to create a ReadStream from a destroyed WriteStream.
|
|
10
|
+
*/
|
|
11
|
+
export class ReadAfterDestroyedError extends Error {
|
|
12
|
+
constructor() {
|
|
13
|
+
super('A ReadStream cannot be created from a destroyed WriteStream.');
|
|
14
|
+
this.name = 'ReadAfterDestroyedError';
|
|
15
|
+
}
|
|
16
|
+
}
|
|
10
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Error thrown when attempting to create a ReadStream from a released WriteStream.
|
|
20
|
+
*/
|
|
21
|
+
export class ReadAfterReleasedError extends Error {
|
|
22
|
+
constructor() {
|
|
23
|
+
super('A ReadStream cannot be created from a released WriteStream.');
|
|
24
|
+
this.name = 'ReadAfterReleasedError';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Options for creating a ReadStream.
|
|
30
|
+
*/
|
|
11
31
|
export interface ReadStreamOptions {
|
|
32
|
+
/** Maximum number of bytes to store in the internal buffer before ceasing to read from the underlying resource. */
|
|
12
33
|
highWaterMark?: ReadableOptions['highWaterMark'];
|
|
34
|
+
/** Encoding to use for the readable stream. */
|
|
13
35
|
encoding?: ReadableOptions['encoding'];
|
|
14
36
|
}
|
|
15
37
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
process.once('exit', () => processExitProxy.emit('exit'));
|
|
38
|
+
/**
|
|
39
|
+
* Proxy event emitter to handle process exit events without triggering max listeners warnings.
|
|
40
|
+
*/
|
|
41
|
+
const PROCESS_EXIT_PROXY = new EventEmitter();
|
|
42
|
+
PROCESS_EXIT_PROXY.setMaxListeners(Infinity);
|
|
43
|
+
process.once('exit', () => PROCESS_EXIT_PROXY.emit('exit'));
|
|
23
44
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
45
|
+
interface WritableState {
|
|
46
|
+
finished: boolean;
|
|
47
|
+
}
|
|
27
48
|
|
|
49
|
+
/**
|
|
50
|
+
* A readable stream that reads from a WriteStream's temporary file.
|
|
51
|
+
* Allows multiple concurrent reads from the same WriteStream.
|
|
52
|
+
*/
|
|
53
|
+
export class ReadStream extends Readable {
|
|
54
|
+
private _pos = 0;
|
|
55
|
+
private readonly _writeStream: WriteStream;
|
|
56
|
+
private _retryListenersAttached = false;
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Creates a new ReadStream attached to a WriteStream.
|
|
60
|
+
* @param writeStream - The WriteStream to read from.
|
|
61
|
+
* @param options - Stream options.
|
|
62
|
+
*/
|
|
28
63
|
constructor(writeStream: WriteStream, options?: ReadStreamOptions) {
|
|
29
64
|
super({
|
|
30
65
|
highWaterMark: options?.highWaterMark,
|
|
@@ -34,79 +69,135 @@ export class ReadStream extends Readable {
|
|
|
34
69
|
this._writeStream = writeStream;
|
|
35
70
|
}
|
|
36
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Retries reading from the write stream after data is available.
|
|
74
|
+
*/
|
|
75
|
+
private _retry = (): void => {
|
|
76
|
+
this._detachRetryListeners();
|
|
77
|
+
this._read(this.readableHighWaterMark || 65536);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Attaches retry listeners to wait for more data or stream completion.
|
|
82
|
+
*/
|
|
83
|
+
private _attachRetryListeners(): void {
|
|
84
|
+
if (this._retryListenersAttached) return;
|
|
85
|
+
this._writeStream.on('finish', this._retry);
|
|
86
|
+
this._writeStream.on('write', this._retry);
|
|
87
|
+
this._retryListenersAttached = true;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Detaches retry listeners when they are no longer needed.
|
|
92
|
+
*/
|
|
93
|
+
private _detachRetryListeners(): void {
|
|
94
|
+
if (!this._retryListenersAttached) return;
|
|
95
|
+
this._writeStream.off('finish', this._retry);
|
|
96
|
+
this._writeStream.off('write', this._retry);
|
|
97
|
+
this._retryListenersAttached = false;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Internal read implementation that fetches data from the temporary file.
|
|
102
|
+
* @param n - Number of bytes to read.
|
|
103
|
+
*/
|
|
37
104
|
_read(n: number): void {
|
|
38
|
-
if (this.destroyed)
|
|
105
|
+
if (this.destroyed) {
|
|
106
|
+
this._detachRetryListeners();
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
39
109
|
|
|
40
|
-
|
|
110
|
+
const fd = this._writeStream.getFd();
|
|
111
|
+
if (fd === null) {
|
|
41
112
|
this._writeStream.once('ready', () => this._read(n));
|
|
42
113
|
return;
|
|
43
114
|
}
|
|
44
115
|
|
|
45
|
-
// Using `allocUnsafe` here is OK because we return a slice the length of
|
|
46
|
-
// `bytesRead`, and discard the rest. This prevents node from having to zero
|
|
47
|
-
// out the entire allocation first.
|
|
48
116
|
const buf = new Uint8Array(Buffer.allocUnsafe(n).buffer);
|
|
49
|
-
read(
|
|
50
|
-
if (error)
|
|
117
|
+
read(fd, buf, 0, n, this._pos, (error, bytesRead) => {
|
|
118
|
+
if (error) {
|
|
119
|
+
this.destroy(error);
|
|
120
|
+
this._detachRetryListeners();
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
51
123
|
|
|
52
|
-
// Push any read bytes into the local stream buffer.
|
|
53
124
|
if (bytesRead) {
|
|
54
125
|
this._pos += bytesRead;
|
|
55
126
|
this.push(buf.slice(0, bytesRead));
|
|
56
127
|
return;
|
|
57
128
|
}
|
|
58
129
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
(
|
|
63
|
-
this._writeStream as unknown as {
|
|
64
|
-
_writableState: { finished: boolean };
|
|
65
|
-
}
|
|
66
|
-
)._writableState.finished
|
|
67
|
-
) {
|
|
68
|
-
// Check if we have consumed the whole file up to where
|
|
69
|
-
// the write stream has written before ending the stream
|
|
70
|
-
if (this._pos < (this._writeStream as unknown as { _pos: number })._pos)
|
|
130
|
+
if (this._writeStream.isWritableFinished()) {
|
|
131
|
+
const writePos = this._writeStream.getWritePosition();
|
|
132
|
+
if (this._pos < writePos) {
|
|
71
133
|
this._read(n);
|
|
72
|
-
else
|
|
134
|
+
} else {
|
|
135
|
+
this.push(null);
|
|
136
|
+
this._detachRetryListeners();
|
|
137
|
+
}
|
|
73
138
|
return;
|
|
74
139
|
}
|
|
75
140
|
|
|
76
|
-
|
|
77
|
-
const retry = (): void => {
|
|
78
|
-
this._writeStream.off('finish', retry);
|
|
79
|
-
this._writeStream.off('write', retry);
|
|
80
|
-
this._read(n);
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
this._writeStream.on('finish', retry);
|
|
84
|
-
this._writeStream.on('write', retry);
|
|
141
|
+
this._attachRetryListeners();
|
|
85
142
|
});
|
|
86
143
|
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Cleanup when the stream is destroyed.
|
|
147
|
+
*/
|
|
148
|
+
_destroy(
|
|
149
|
+
error: Error | null,
|
|
150
|
+
callback: (error?: Error | null) => void,
|
|
151
|
+
): void {
|
|
152
|
+
this._detachRetryListeners();
|
|
153
|
+
super._destroy(error, callback);
|
|
154
|
+
}
|
|
87
155
|
}
|
|
88
156
|
|
|
157
|
+
/**
|
|
158
|
+
* Options for creating a WriteStream.
|
|
159
|
+
*/
|
|
89
160
|
export interface WriteStreamOptions {
|
|
161
|
+
/** Maximum number of bytes to store in the internal buffer before ceasing to write to the underlying resource. */
|
|
90
162
|
highWaterMark?: WritableOptions['highWaterMark'];
|
|
163
|
+
/** Default encoding to use for the writable stream. */
|
|
91
164
|
defaultEncoding?: WritableOptions['defaultEncoding'];
|
|
165
|
+
/** Function that returns the temporary directory path. */
|
|
92
166
|
tmpdir?: () => string;
|
|
93
167
|
}
|
|
94
168
|
|
|
169
|
+
/**
|
|
170
|
+
* A writable stream that stores data in a temporary file.
|
|
171
|
+
* Supports multiple concurrent ReadStream instances reading from the same file.
|
|
172
|
+
* Automatically cleans up the temporary file when all streams are closed.
|
|
173
|
+
*/
|
|
95
174
|
export class WriteStream extends Writable {
|
|
96
|
-
private _fd:
|
|
97
|
-
private _path:
|
|
98
|
-
private _pos
|
|
99
|
-
private _readStreams
|
|
100
|
-
private _released
|
|
101
|
-
|
|
102
|
-
|
|
175
|
+
private _fd: number | null = null;
|
|
176
|
+
private _path: string | null = null;
|
|
177
|
+
private _pos = 0;
|
|
178
|
+
private readonly _readStreams = new Set<ReadStream>();
|
|
179
|
+
private _released = false;
|
|
180
|
+
private _tmpdir: () => string;
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Creates a new WriteStream with a temporary file.
|
|
184
|
+
* @param options - Stream options.
|
|
185
|
+
*/
|
|
186
|
+
constructor(options: WriteStreamOptions = {}) {
|
|
103
187
|
super({
|
|
104
|
-
highWaterMark: options
|
|
105
|
-
defaultEncoding: options
|
|
188
|
+
highWaterMark: options.highWaterMark,
|
|
189
|
+
defaultEncoding: options.defaultEncoding,
|
|
106
190
|
autoDestroy: false,
|
|
107
191
|
});
|
|
192
|
+
this._tmpdir = options.tmpdir ?? tmpdir;
|
|
193
|
+
this._initFile();
|
|
194
|
+
}
|
|
108
195
|
|
|
109
|
-
|
|
196
|
+
/**
|
|
197
|
+
* Initializes the temporary file with a random name.
|
|
198
|
+
* Emits 'ready' when the file is ready for writing.
|
|
199
|
+
*/
|
|
200
|
+
private _initFile(): void {
|
|
110
201
|
randomBytes(16, (error, buffer) => {
|
|
111
202
|
if (error) {
|
|
112
203
|
this.destroy(error);
|
|
@@ -114,27 +205,53 @@ export class WriteStream extends Writable {
|
|
|
114
205
|
}
|
|
115
206
|
|
|
116
207
|
this._path = join(
|
|
117
|
-
(
|
|
208
|
+
this._tmpdir(),
|
|
118
209
|
`capacitor-${buffer.toString('hex')}.tmp`,
|
|
119
210
|
);
|
|
120
211
|
|
|
121
|
-
// Create a file in the OS's temporary files directory.
|
|
122
212
|
open(this._path, 'wx+', 0o600, (error, fd) => {
|
|
123
213
|
if (error) {
|
|
124
214
|
this.destroy(error);
|
|
125
215
|
return;
|
|
126
216
|
}
|
|
127
217
|
|
|
128
|
-
|
|
129
|
-
processExitProxy.once('exit', this._cleanupSync);
|
|
130
|
-
|
|
218
|
+
PROCESS_EXIT_PROXY.once('exit', this._cleanupSync);
|
|
131
219
|
this._fd = fd;
|
|
132
220
|
this.emit('ready');
|
|
133
221
|
});
|
|
134
222
|
});
|
|
135
223
|
}
|
|
136
224
|
|
|
137
|
-
|
|
225
|
+
/**
|
|
226
|
+
* Returns the file descriptor for the temporary file.
|
|
227
|
+
* @returns The file descriptor or null if not yet initialized.
|
|
228
|
+
*/
|
|
229
|
+
getFd(): number | null {
|
|
230
|
+
return this._fd;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Returns the current write position in the file.
|
|
235
|
+
* @returns The number of bytes written so far.
|
|
236
|
+
*/
|
|
237
|
+
getWritePosition(): number {
|
|
238
|
+
return this._pos;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Checks if the writable stream has finished.
|
|
243
|
+
* @returns True if the stream is finished, false otherwise.
|
|
244
|
+
*/
|
|
245
|
+
isWritableFinished(): boolean {
|
|
246
|
+
return (this as unknown as { _writableState: WritableState })._writableState
|
|
247
|
+
.finished;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Asynchronously cleans up the temporary file.
|
|
252
|
+
* Closes the file descriptor and deletes the file.
|
|
253
|
+
*/
|
|
254
|
+
private _cleanup(callback: (error: Error | null) => void): void {
|
|
138
255
|
const fd = this._fd;
|
|
139
256
|
const path = this._path;
|
|
140
257
|
|
|
@@ -143,59 +260,61 @@ export class WriteStream extends Writable {
|
|
|
143
260
|
return;
|
|
144
261
|
}
|
|
145
262
|
|
|
146
|
-
// Close the file descriptor.
|
|
147
263
|
close(fd, (closeError) => {
|
|
148
|
-
|
|
149
|
-
|
|
264
|
+
this._fd = null;
|
|
265
|
+
PROCESS_EXIT_PROXY.off('exit', this._cleanupSync);
|
|
266
|
+
|
|
150
267
|
unlink(path, (unlinkError) => {
|
|
151
|
-
|
|
152
|
-
// clean up on next restart, since we use store thes in `os.tmpdir()`
|
|
153
|
-
this._fd = null;
|
|
154
|
-
|
|
155
|
-
// We avoid removing this until now in case an exit occurs while
|
|
156
|
-
// asyncronously cleaning up.
|
|
157
|
-
processExitProxy.off('exit', this._cleanupSync);
|
|
158
|
-
callback(unlinkError ?? closeError);
|
|
268
|
+
callback(unlinkError ?? closeError ?? null);
|
|
159
269
|
});
|
|
160
270
|
});
|
|
161
|
-
}
|
|
271
|
+
}
|
|
162
272
|
|
|
163
|
-
|
|
164
|
-
|
|
273
|
+
/**
|
|
274
|
+
* Synchronously cleans up the temporary file.
|
|
275
|
+
* Called on process exit to ensure cleanup even if async operations are interrupted.
|
|
276
|
+
*/
|
|
277
|
+
private _cleanupSync = (): void => {
|
|
278
|
+
PROCESS_EXIT_PROXY.off('exit', this._cleanupSync);
|
|
165
279
|
|
|
166
|
-
if (typeof this._fd === 'number')
|
|
280
|
+
if (typeof this._fd === 'number') {
|
|
167
281
|
try {
|
|
168
282
|
closeSync(this._fd);
|
|
169
283
|
} catch {
|
|
170
|
-
//
|
|
171
|
-
// still try to unlink the file.
|
|
284
|
+
// File descriptor already closed
|
|
172
285
|
}
|
|
286
|
+
}
|
|
173
287
|
|
|
174
|
-
|
|
175
|
-
|
|
288
|
+
if (this._path !== null) {
|
|
289
|
+
try {
|
|
176
290
|
unlinkSync(this._path);
|
|
291
|
+
} catch {
|
|
292
|
+
// File already deleted
|
|
177
293
|
}
|
|
178
|
-
} catch {
|
|
179
|
-
// If we are unable to unlink the file, the operating system will clean
|
|
180
|
-
// up on next restart, since we use store thes in `os.tmpdir()`
|
|
181
294
|
}
|
|
182
295
|
};
|
|
183
296
|
|
|
184
|
-
|
|
185
|
-
|
|
297
|
+
/**
|
|
298
|
+
* Called when the stream is finished writing.
|
|
299
|
+
*/
|
|
300
|
+
_final(callback: (error?: Error | null) => void): void {
|
|
301
|
+
if (this._fd === null) {
|
|
186
302
|
this.once('ready', () => this._final(callback));
|
|
187
303
|
return;
|
|
188
304
|
}
|
|
189
305
|
callback();
|
|
190
306
|
}
|
|
191
307
|
|
|
308
|
+
/**
|
|
309
|
+
* Internal write implementation that writes data to the temporary file.
|
|
310
|
+
*/
|
|
192
311
|
_write(
|
|
193
312
|
chunk: Buffer,
|
|
194
|
-
|
|
195
|
-
callback: (error?:
|
|
313
|
+
_encoding: string,
|
|
314
|
+
callback: (error?: Error | null) => void,
|
|
196
315
|
): void {
|
|
197
|
-
if (
|
|
198
|
-
this.once('ready', () => this._write(chunk,
|
|
316
|
+
if (this._fd === null) {
|
|
317
|
+
this.once('ready', () => this._write(chunk, _encoding, callback));
|
|
199
318
|
return;
|
|
200
319
|
}
|
|
201
320
|
|
|
@@ -211,41 +330,29 @@ export class WriteStream extends Writable {
|
|
|
211
330
|
return;
|
|
212
331
|
}
|
|
213
332
|
|
|
214
|
-
// It's safe to increment `this._pos` after flushing to the filesystem
|
|
215
|
-
// because node streams ensure that only one `_write()` is active at a
|
|
216
|
-
// time. If this assumption is broken, the behavior of this library is
|
|
217
|
-
// undefined, regardless of where this is incremented. Relocating this
|
|
218
|
-
// to increment syncronously would result in correct file contents, but
|
|
219
|
-
// the out-of-order writes would still open the potential for read streams
|
|
220
|
-
// to scan positions that have not yet been written.
|
|
221
333
|
this._pos += chunk.length;
|
|
222
334
|
this.emit('write');
|
|
223
335
|
callback();
|
|
224
336
|
});
|
|
225
337
|
}
|
|
226
338
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
339
|
+
/**
|
|
340
|
+
* Cleanup when the stream is destroyed.
|
|
341
|
+
* Destroys all associated ReadStreams and cleans up the temporary file.
|
|
342
|
+
*/
|
|
232
343
|
_destroy(
|
|
233
|
-
error:
|
|
234
|
-
callback: (error?:
|
|
344
|
+
error: Error | null,
|
|
345
|
+
callback: (error?: Error | null) => void,
|
|
235
346
|
): void {
|
|
236
|
-
// Destroy all attached read streams.
|
|
237
347
|
for (const readStream of this._readStreams) {
|
|
238
|
-
readStream.destroy(error
|
|
348
|
+
readStream.destroy(error ?? undefined);
|
|
239
349
|
}
|
|
240
350
|
|
|
241
|
-
|
|
242
|
-
if (typeof this._fd === 'number' && typeof this._path === 'string') {
|
|
351
|
+
if (this._fd !== null && this._path !== null) {
|
|
243
352
|
this._cleanup((cleanupError) => callback(cleanupError ?? error));
|
|
244
353
|
return;
|
|
245
354
|
}
|
|
246
355
|
|
|
247
|
-
// This capacitor has not yet finished initialization; if initialization
|
|
248
|
-
// does complete, immediately clean up after.
|
|
249
356
|
this.once('ready', () => {
|
|
250
357
|
this._cleanup((cleanupError) => {
|
|
251
358
|
if (cleanupError) {
|
|
@@ -257,21 +364,27 @@ export class WriteStream extends Writable {
|
|
|
257
364
|
callback(error);
|
|
258
365
|
}
|
|
259
366
|
|
|
367
|
+
/**
|
|
368
|
+
* Creates a new ReadStream that reads from this WriteStream.
|
|
369
|
+
* Multiple ReadStreams can be created and will read independently.
|
|
370
|
+
* @param options - Stream options for the ReadStream.
|
|
371
|
+
* @returns A new ReadStream instance.
|
|
372
|
+
* @throws {ReadAfterDestroyedError} If the WriteStream has been destroyed.
|
|
373
|
+
* @throws {ReadAfterReleasedError} If the WriteStream has been released.
|
|
374
|
+
*/
|
|
260
375
|
createReadStream(options?: ReadStreamOptions): ReadStream {
|
|
261
|
-
if (this.destroyed)
|
|
262
|
-
throw new ReadAfterDestroyedError(
|
|
263
|
-
|
|
264
|
-
);
|
|
376
|
+
if (this.destroyed) {
|
|
377
|
+
throw new ReadAfterDestroyedError();
|
|
378
|
+
}
|
|
265
379
|
|
|
266
|
-
if (this._released)
|
|
267
|
-
throw new ReadAfterReleasedError(
|
|
268
|
-
|
|
269
|
-
);
|
|
380
|
+
if (this._released) {
|
|
381
|
+
throw new ReadAfterReleasedError();
|
|
382
|
+
}
|
|
270
383
|
|
|
271
384
|
const readStream = new ReadStream(this, options);
|
|
272
385
|
this._readStreams.add(readStream);
|
|
273
386
|
|
|
274
|
-
readStream.once('close', ()
|
|
387
|
+
readStream.once('close', () => {
|
|
275
388
|
this._readStreams.delete(readStream);
|
|
276
389
|
|
|
277
390
|
if (this._released && this._readStreams.size === 0) {
|
|
@@ -281,6 +394,17 @@ export class WriteStream extends Writable {
|
|
|
281
394
|
|
|
282
395
|
return readStream;
|
|
283
396
|
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Releases the WriteStream, marking it for cleanup.
|
|
400
|
+
* The stream will be destroyed once all ReadStreams are closed.
|
|
401
|
+
*/
|
|
402
|
+
release(): void {
|
|
403
|
+
this._released = true;
|
|
404
|
+
if (this._readStreams.size === 0) {
|
|
405
|
+
this.destroy();
|
|
406
|
+
}
|
|
407
|
+
}
|
|
284
408
|
}
|
|
285
409
|
|
|
286
410
|
export default {
|
|
@@ -1,4 +1,38 @@
|
|
|
1
|
+
// Core
|
|
2
|
+
export { Upload, FileUpload } from './Upload';
|
|
3
|
+
export { GraphQLUpload } from './GraphQLUpload';
|
|
4
|
+
export { processRequest, ProcessRequestOptions } from './processRequest';
|
|
5
|
+
|
|
6
|
+
// Streams
|
|
1
7
|
export * from './fs-capacitor';
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
export
|
|
8
|
+
|
|
9
|
+
// Storage - re-export with GQL prefix to avoid conflicts
|
|
10
|
+
export type {
|
|
11
|
+
StorageFile as GQLStorageFile,
|
|
12
|
+
StorageOptions as GQLStorageOptions,
|
|
13
|
+
} from './storage';
|
|
14
|
+
export { Storage as GQLStorage } from './storage/storage';
|
|
15
|
+
export {
|
|
16
|
+
CapacitorStorage as GQLCapacitorStorage,
|
|
17
|
+
CapacitorStorageFile as GQLCapacitorStorageFile,
|
|
18
|
+
} from './storage/capacitor-storage';
|
|
19
|
+
export {
|
|
20
|
+
MemoryStorage as GQLMemoryStorage,
|
|
21
|
+
MemoryStorageFile as GQLMemoryStorageFile,
|
|
22
|
+
} from './storage/memory-storage';
|
|
23
|
+
|
|
24
|
+
// Utils - prefix to avoid conflicts with multer
|
|
25
|
+
export {
|
|
26
|
+
formatBytes as gqlFormatBytes,
|
|
27
|
+
validateFileSize as gqlValidateFileSize,
|
|
28
|
+
getFileExtension as gqlGetFileExtension,
|
|
29
|
+
isAllowedFileType as gqlIsAllowedFileType,
|
|
30
|
+
sanitizeFilename as gqlSanitizeFilename,
|
|
31
|
+
getUniqueFilename as gqlGetUniqueFilename,
|
|
32
|
+
} from './utils/file';
|
|
33
|
+
|
|
34
|
+
export {
|
|
35
|
+
FileTypes as GQLFileTypes,
|
|
36
|
+
FileValidatorOptions as GQLFileValidatorOptions,
|
|
37
|
+
validateFile as gqlValidateFile,
|
|
38
|
+
} from './utils/validators';
|