Quik Framework :: Storage Express
- Codename: Berlin
- Version: 0.2.0-beta.76
- License: Check license here
Express helpers for handling local file uploads via Multer-backed middleware.
Installation
npm install @quik/storage-express
Configuration
This package relies on the local storage settings from @quik/storage:
STORAGE_LOCAL_ENABLEDSTORAGE_LOCAL_UPLOAD(temporary upload folder)STORAGE_LOCAL_DESTINATION(final storage folder)STORAGE_LOCAL_SIGNED_SECRET(required to serve/accept signed local storage URLs)STORAGE_LOCAL_HTTP_BASE_PATH(default:/storage/local; base path for the signed download/upload routes)
Usage
Enable the module in your bootstrap setup and attach upload decorators:
import { LocalStorage } from '@quik/storage-express';
import { Decorators, QRoute } from '@quik/http';
@Decorators.Route.Route('/uploads')
export class UploadRoute extends QRoute {
@LocalStorage.Decorators.SingleFile('file')
@Decorators.Endpoint.POST('/')
async upload(event) {
return { file: event.context.files?.file };
}
}
The middleware converts Multer files into LocalStorageFile entities and
exposes them on the Express context (context.files).
Persisting uploads
Use the persist decorators to move files into the configured destination via the storage engine:
import { LocalStorage } from '@quik/storage-express';
import { Decorators, QRoute } from '@quik/http';
@Decorators.Route.Route('/uploads')
export class UploadRoute extends QRoute {
@LocalStorage.Decorators.SingleFilePersist('file')
@Decorators.Endpoint.POST('/persist')
async uploadAndPersist(event) {
return { file: event.context.files?.file };
}
}
SingleFilePersist and ArrayFilePersist accept an optional destination path
to override the configured STORAGE_LOCAL_DESTINATION.
Notes:
LocalStorageFile.moveToDestinationis async.LocalStorageFile.extensionincludes the leading dot (e.g..txt).
Middleware Options & Limits
SingleFile(fieldName)accepts exactly one file for the given field.ArrayFile(fieldName, maxCount)accepts multiple files for one field and forwardsmaxCountto Multer.SingleFilePersistandArrayFilePersistmove uploads intoSTORAGE_LOCAL_DESTINATION, or an explicit destination.
Multer is configured with the STORAGE_LOCAL_UPLOAD temp folder. Size limits and file filters should be
applied by composing additional Express middleware when needed.
Signed download/upload endpoints
This package does not register GET/POST routes for signed local storage URLs itself — the consuming
application defines those routes (path, method, request/response shape are application-specific). What this
package provides is the building block for verifying the token:
@quik/storage'sQLocalStorageEngine.getSignedDownloadURL/getSignedUploadURL(orPresignedLocalURLEntity) produce a URL of the form{STORAGE_LOCAL_HTTP_BASE_PATH}/{download|upload}?token=....STORAGE_LOCAL_HTTP_BASE_PATHis only used to build that URL string — mount your route at a matching path if you want the two to line up.LocalStorage.Decorators.RequireSignedToken(purpose)(alias forRequireLocalStorageToken, also exported directly) is an endpoint middleware decorator that verifies thetokenquery parameter and throws before the handler runs if it's missing, malformed, expired, or issued for the wrong purpose — the same shape as@quik/authorization'sAuthDecorators.CanAccess. On success it stores the verified storage path on the event viaevent.getObject(LOCAL_STORAGE_TOKEN_PATH_KEY).
import { Decorators, QQueryParameters, QRoute, Responses } from '@quik/http';
import { Fields } from '@quik/entity';
import { LOCAL_STORAGE_TOKEN_PATH_KEY, LocalStorage, RequireLocalStorageToken } from '@quik/storage-express';
import { QStorageEngineType, StorageStore } from '@quik/storage';
import type { QLocalStorageEngine } from '@quik/storage';
@Decorators.Parameters.Query()
class TokenQuery extends QQueryParameters {
@Fields.String()
public token: string;
}
@Decorators.Route.API('/storage/local')
export class LocalStorageRoute extends QRoute {
@Decorators.Endpoint.GET('/download', { query: TokenQuery })
@RequireLocalStorageToken('download')
async download(event) {
const path = event.getObject<string>(LOCAL_STORAGE_TOKEN_PATH_KEY);
const engine = StorageStore.get(QStorageEngineType.LOCAL) as QLocalStorageEngine;
const file = await engine.get(path);
return Responses.OKFile(file.path, file.mimeType);
}
}
RequireLocalStorageToken throws StorageInvalidSignedURLError (missing/malformed token, 401),
StorageSignedURLExpiredError (410), or StorageSignedURLPurposeMismatchError (401) — all from @quik/storage.
There is no Bearer authentication involved; the signed token itself is the authorization.
API Highlights
LocalStorage.init()wires Multer if local storage is enabled.LocalStorage.Decoratorsprovides upload decorators, plusRequireSignedTokenfor verifying signed local storage tokens.RequireLocalStorageToken/LOCAL_STORAGE_TOKEN_PATH_KEY— also exported directly for use outside theLocalStoragenamespace.LocalStorageFileentity represents uploaded files.- Persist decorators move uploads into storage using the local engine.
Testing & Coverage
See the root instructions for details on running pnpm run test:coverage and accessing coverage artifacts.
API Reference
Generated API documentation is available in the storage-express API section.