UNPKG

@webda/core

Version:

Expose API with Lambda

552 lines (551 loc) 14.3 kB
import { Readable } from "stream"; import { Counter, WebdaError } from "../index.js"; import { CoreModel } from "../models/coremodel.js"; import { MappingService, Store } from "../stores/store.js"; import { OperationContext, WebContext } from "../utils/context.js"; import { Service, ServiceParameters } from "./service.js"; /** * Represent basic EventBinary */ export interface EventBinary { object: BinaryFileInfo; service: BinaryService; /** * In case the Context is known */ context?: OperationContext; } export interface EventBinaryUploadSuccess extends EventBinary { target: CoreModel; } /** * Sent before metadata are updated to allow alteration of the modification */ export interface EventBinaryMetadataUpdate extends EventBinaryUploadSuccess { target: CoreModel; metadata: BinaryMetadata; } /** * Emitted if binary does not exist */ export declare class BinaryNotFoundError extends WebdaError.CodeError { constructor(hash: string, storeName: string); } export interface BinaryFileInfo { /** * Hash of the binary */ hash?: string; /** * Will be computed by the service * * hash of the content prefixed by 'WEBDA' */ challenge?: string; /** * Size of the file */ size: number; /** * Name of the file */ name: string; /** * Mimetype */ mimetype: string; /** * Metadatas stored along with the binary */ metadata?: BinaryMetadata; } /** * Represent files attached to a model */ export type BinaryFiles = BinaryFileInfo[]; /** * Represent a file to store * @WebdaSchema */ export declare abstract class BinaryFile<T = any> implements BinaryFileInfo { /** * Current name */ name: string; /** * Original name */ originalname?: string; /** * Size of the binary */ size: number; /** * Mimetype of the binary */ mimetype: string; /** * Will be computed by the service * * hash of the content prefixed by 'WEBDA' */ challenge?: string; /** * Will be computed by the service * * hash of the content */ hash?: string; /** * Metadatas stored along with the binary */ metadata?: T; constructor(info: BinaryFileInfo); /** * Set the information * @param info */ set(info: BinaryFileInfo): void; /** * Retrieve a plain BinaryFileInfo object * @returns */ toBinaryFileInfo(): BinaryFileInfo; abstract get(): Promise<Readable>; /** * Create hashes * @param buffer * @returns */ getHashes(): Promise<{ hash: string; challenge: string; }>; } export declare class LocalBinaryFile extends BinaryFile { /** * Path on the hard drive */ path: string; constructor(filePath: string); /** * @override */ get(): Promise<Readable>; } export declare class MemoryBinaryFile extends BinaryFile { /** * Content */ buffer: Buffer; constructor(buffer: Buffer | string, info?: Partial<BinaryFileInfo>); /** * @override */ get(): Promise<Readable>; } /** * Define the metadata for a Binary */ export type BinaryMetadata = any; /** * This is a map used to retrieve binary * * @class BinaryMap */ export declare class BinaryMap<T = any> extends BinaryFile<T> { /** * Current context */ __ctx: OperationContext; /** * Link to the binary store */ __store: BinaryService; constructor(service: BinaryService, obj: BinaryFileInfo); /** * Get the binary data * * @returns */ get(): Promise<Readable>; /** * Get into a buffer */ getAsBuffer(): Promise<Buffer>; /** * Download the binary to a path * * Shortcut to call {@link Binary.downloadTo} with current object * * @param filename */ downloadTo(filename: string): Promise<void>; /** * Set the http context * @param ctx */ setContext(ctx: OperationContext): void; } /** * One Binary instance */ export declare class Binary<T = any> extends BinaryMap<T> { protected model: CoreModel; protected attribute: string; protected empty: boolean; constructor(attribute: string, model: CoreModel); /** * isEmpty * @returns */ isEmpty(): boolean; /** * Ensure empty is set correctly * @param info */ set(info: BinaryFileInfo): void; /** * Replace the binary * @param id * @param ctx * @returns */ upload(file: BinaryFile): Promise<void>; /** * Delete the binary, if you need to replace just use upload */ delete(): Promise<void>; /** * Return undefined if no hash * @returns */ toJSON(): this; } /** * Define a Binary map stored in a Binaries collection */ export declare class BinariesItem<T = any> extends BinaryMap<T> { protected parent: BinariesImpl; constructor(parent: BinariesImpl, info: BinaryFileInfo); /** * Replace the binary * @param id * @param ctx * @returns */ upload(file: BinaryFile): Promise<void>; /** * Delete the binary, if you need to replace just use upload */ delete(): Promise<void>; } /** * Define a collection of Binary */ export declare class BinariesImpl<T = any> extends Array<BinariesItem<T>> { __service: BinaryService; protected model: CoreModel; protected attribute: string; assign(model: CoreModel, attribute: string): this; pop(): BinariesItem<T>; slice(): BinariesItem<T>[]; unshift(): number; shift(): BinariesItem<T>; push(...args: any[]): number; /** * Upload a file to this model * @param file */ upload(file: BinaryFile, replace?: BinariesItem): Promise<void>; /** * Delete an item * @param item */ delete(item: BinariesItem): Promise<void>; } /** * Define a collection of Binary with a Readonly and the upload method */ export type Binaries<T = any> = Readonly<Array<BinariesItem<T>>> & { upload: (file: BinaryFile) => Promise<void>; }; export declare class BinaryParameters extends ServiceParameters { /** * Define the map to Object collection * * key is a Store name * the string[] represent all valids attributes to store files in * @deprecated */ map: { [key: string]: string[]; }; /** * Define the map of models * * indicates all models * * key is a Store name * the string[] represent all valids attributes to store files in * indicates all attributes */ models: { [key: string]: string[]; }; /** * Expose the service to http * @deprecated will be removed in 4.0 */ expose?: { /** * URL to expose the service to */ url: string; /** * Restrict some APIs */ restrict?: { /** * Restrict GET */ get?: boolean; /** * Restrict POST */ create?: boolean; /** * Restrict DELETE */ delete?: boolean; /** * Restrict update of metadata */ metadata?: boolean; }; }; constructor(params: any, _service: Service); } export type BinaryEvents = { /** * Emitted when someone download a binary */ "Binary.Get": EventBinary; "Binary.UploadSuccess": EventBinaryUploadSuccess; "Binary.MetadataUpdate": EventBinaryMetadataUpdate; "Binary.MetadataUpdated": EventBinaryUploadSuccess; "Binary.Create": EventBinaryUploadSuccess; "Binary.Delete": EventBinary; }; /** * Define a BinaryModel with infinite field for binary map */ export type BinaryModel<T = { [key: string]: BinaryMap[]; }> = CoreModel & T; /** * This is an abstract service to represent a storage of files * The binary allow you to expose this service as HTTP * * It supports two modes: * - attached to a CoreModel (attach, detach, reattach) * - pure storage with no managed id (read, write, delete) * * As we have deduplication builtin you can get some stats * - getUsageCount(hash) * - getUsageCountForRaw() * - getUsageCountForMap() * * The Binary storage should store only once a binary and reference every object that are used by this binary, so it can be cleaned. * * * @see FileBinary * @see S3Binary * * @exports * @abstract * @WebdaModda Binary */ export declare abstract class BinaryService<T extends BinaryParameters = BinaryParameters, E extends BinaryEvents = BinaryEvents> extends Service<T, E> implements MappingService<BinaryMap> { _lowercaseMaps: any; metrics: { upload: Counter; download: Counter; delete: Counter; metadataUpdate: Counter; }; /** * @override */ initMetrics(): void; /** * Redirect to the temporary link to S3 object * or return it if returnInfo=true * * @param ctx of the request * @param returnInfo */ httpGet(context: WebContext): Promise<void>; /** * Get a UrlFromObject * */ getRedirectUrlFromObject(binaryMap: BinaryMap, _context: OperationContext, _expires?: number): Promise<null | string>; /** * Define if binary is managed by the store * @param modelName * @param attribute * @returns -1 if not managed, 0 if managed but by default, 1 if managed and in the map, 2 if explicit with attribute and model */ handleBinary(modelName: string, attribute: string): -1 | 0 | 1 | 2; /** * When you store a binary to be able to retrieve it you need to store the information into another object * * If you have a User object define like this : User = {'name': 'Remi', 'uuid': 'Loopingz'} * You will call the `store(userStore, 'Loopingz', 'images', filedata, {'type':'profile'})` * After a successful call the object will look like * ``` * User = { * 'name': 'Remi', * 'uuid': 'Loopingz', * 'images': [ * {'type':'profile','hash':'a12545...','size':1245,'mime':'application/octet'} * ] * } * ``` * * * @param {CoreModel} object The object uuid to get from the store * @param {String} property The object property to add the file to * @param {Object} file The file by itself * @param {Object} metadata to add to the binary object * @emits 'binaryCreate' */ abstract store(object: CoreModel, property: string, file: BinaryFile, metadata?: BinaryMetadata): Promise<void>; /** * The store can retrieve how many time a binary has been used */ abstract getUsageCount(hash: string): Promise<number>; /** * Delete a binary * * @param {CoreModel} object The object uuid to get from the store * @param {String} property The object property to add the file to * @param {Number} index The index of the file to change in the property * @emits 'binaryDelete' */ abstract delete(object: CoreModel, property: string, index?: number): Promise<void>; /** * Get a binary * * @param {Object} info The reference stored in your target object * @emits 'binaryGet' */ get(info: BinaryMap): Promise<Readable>; /** * Download a binary to a file * * @param {Object} info The reference stored in your target object * @param {String} filepath to save the binary to */ downloadTo(info: BinaryMap, filename: any): Promise<void>; /** * @override */ resolve(): this; abstract _get(info: BinaryMap): Promise<Readable>; /** * Init the declared maps, adding reverse maps * * @param map */ initMap(map: any): void; /** * Based on the raw Map init a BinaryMap * @param obj * @returns */ newModel(obj: any): BinaryMap; /** * Read a stream to a buffer * * @param stream * @returns */ static streamToBuffer(stream: Readable): Promise<Buffer>; /** * Check if a map is defined * * @param name * @param property */ protected checkMap(object: CoreModel, property: string): void; /** * Ensure events are sent correctly after an upload and update the BinaryFileInfo in targetted object */ uploadSuccess(object: BinaryModel, property: string, fileInfo: BinaryFileInfo | { toBinaryFileInfo: () => BinaryFileInfo; }): Promise<void>; /** * Cascade delete the object * * @param info of the map * @param uuid of the object */ abstract cascadeDelete(info: BinaryMap, uuid: string): Promise<void>; /** * * @param targetStore * @param object * @param property * @param index * @returns */ deleteSuccess(object: BinaryModel, property: string, index?: number): Promise<any>; /** * Get file either from multipart post or raw * @param req * @returns */ _getFile(req: WebContext): Promise<BinaryFile>; /** * @override */ initRoutes(): void; /** * Init the Binary system routes * * Making sure parameters.expose exists prior */ _initRoutes(): void; /** * Return the name of the service for OpenAPI * @returns */ protected getOperationName(): string; /** * Based on the request parameter verify it match a known mapping * @param ctx * @returns */ _verifyMapAndStore(ctx: WebContext): Store<CoreModel>; /** * By default no challenge is managed so throws 404 * * @param ctx */ putRedirectUrl(_ctx: WebContext): Promise<{ url: string; method?: string; headers?: { [key: string]: string; }; }>; /** * Mechanism to add a data based on challenge */ httpChallenge(ctx: WebContext<BinaryFile>): Promise<void>; /** * Manage the different routes * @param ctx */ httpRoute(ctx: WebContext): Promise<void>; }