@webda/core
Version:
Expose API with Lambda
552 lines (551 loc) • 14.3 kB
TypeScript
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>;
}