@samitouri / QOSami-HFS / commits / 47aa9fc2

event.uploadStart can be stopped

Massimo Melina committed May 30, 2024 at 00:49 UTC 47aa9fc2be739bf7bffc611fb325d8489f2114ab
2 files changed +17 -5
dev-plugins.md
+8 -4
@@ -170,7 +170,7 @@ The `api` object you get as parameter of the `init` contains the following:
170
171 - `Const: object` all constants of the `const.ts` file are exposed here. E.g. BUILD_TIMESTAMP, API_VERSION, etc.
172
173 -- `getConnections: Connections[]` retrieve current list of active connections.
173 +- `getConnections(): Connections[]` retrieve current list of active connections.
174
175 - `storageDir: string` folder where a plugin is supposed to store run-time data. This folder is preserved during
176 an update of the plugin, while the rest could be deleted.
@@ -188,7 +188,7 @@ The `api` object you get as parameter of the `init` contains the following:
188
189 when the event is emitted, your (optional) listener is called, and the returned promise is resolved.
190
191 -- `require: function` use this instead of standard `require` function to access modules already loaded by HFS. Example:
191 +- `require(module: string)` use this instead of standard `require` function to access modules already loaded by HFS. Example:
192 ```js
193 const { watchLoad } = api.require('./watchLoad')
194 ```
@@ -197,10 +197,10 @@ The `api` object you get as parameter of the `init` contains the following:
197 If you need something for your plugin that's not covered by `api`, you can test it with this method, but you should
198 then discuss it on the forum because an addition to `api` is your best option for making a future-proof plugin.
199
200 -- `customApiCall: (method: string, ...params) => any[]` this will invoke other plugins if they define `method`
200 +- `customApiCall(method: string, ...params): any[]` this will invoke other plugins if they define `method`
201 exported inside `customApi: object`
202
203 -- `openDb: (filename, options) => Promise<{ get, put, del, close, unlink, sublevel }>` LevelDB-like class for storage.
203 +- `openDb(filename, options): Promise<{ get, put, del, close, unlink, sublevel }>` LevelDB-like class for storage.
204 Refer to [dedicated documentation](https://www.npmjs.com/package/@rejetto/kvstorage) for details.
205
206 ## Front-end specific
@@ -390,6 +390,7 @@ This section is still partially documented, and you may need to have a look at t
390
391 - `deleting`
392 - parameters: { node, ctx }
393 + - called just before trying to delete a file or folder (which still may not exist and fail)
394 - async supported
395 - stoppable
396 - `logout`
@@ -413,6 +414,9 @@ This section is still partially documented, and you may need to have a look at t
414 - `pluginStopped`
415 - `pluginStarted`
416 - `uploadStart`
417 + - parameters: { ctx, writeStream }
418 + - stoppable
419 + - return: callback to call when upload is finished
420 - `uploadFinished`
421
422 ## Other files
src/upload.ts
+9 -1
@@ -116,7 +116,12 @@ export function uploadWriter(base: VfsNode, path: string, ctx: Koa.Context) {
116 trackProgress()
117 // allow plugins to mess with the write-stream, because the read-stream can be complicated in case of multipart
118 const obj = { ctx, writeStream }
119 - events.emit('uploadStart', obj)
119 + const resEvent = events.emit('uploadStart', obj)
120 + if (resEvent?.preventDefault())
121 + return writeStream.close(() => {
122 + try { fs.unlinkSync(writeStream.path) }
123 + catch {}
124 + })
125
126 const lockMiddleware = pendingPromise() // outside we need to know when all operations stopped
127 writeStream.once('close', async () => {
@@ -144,6 +149,9 @@ export function uploadWriter(base: VfsNode, path: string, ctx: Koa.Context) {
149 if (resumable)
150 delayedDelete(resumable, 0)
151 events.emit('uploadFinished', obj)
152 + if (resEvent) for (const cb of resEvent)
153 + if (_.isFunction(cb))
154 + cb(obj)
155 }
156 catch (err: any) {
157 setUploadMeta(tempName, ctx)