forest-express-sequelize
Version:
Official Express/Sequelize Liana for Forest
358 lines (290 loc) • 9.95 kB
TypeScript
import { Application, NextFunction, Request, RequestHandler, Response } from 'express';
import * as Sequelize from 'sequelize';
// Everything related to Forest initialization
export interface LianaOptions {
objectMapping: typeof Sequelize;
envSecret: string;
authSecret: string;
connections: Record<string, Sequelize.Sequelize>;
includedModels?: string[];
excludedModels?: string[];
configDir?: string;
schemaDir?: string;
}
export function init(options: LianaOptions): Promise<Application>;
export interface DatabaseConfiguration {
name: string,
modelsDir: string,
connection: {
url: string,
options: Sequelize.Options,
}
}
// Everything related to Forest Authentication
export function ensureAuthenticated(request: Request, response: Response, next: NextFunction): void;
export interface UserTag {
key: string,
value: string,
}
export interface User {
email: string,
firstName: string,
lastName: string,
team: string,
role: string,
tags: UserTag[],
renderingId: number;
iat: number,
exp: number,
}
export interface ForestRequest extends Request {
user: User,
}
// Base attributes for actions requests (content of request.data.body.attributes)
interface ActionRequestAttributes {
collection_name: string,
ids: string[],
parent_collection_name: string,
parent_collection_id: string,
parent_association_name: string,
all_records: boolean,
all_records_subset_query: Query,
all_records_ids_excluded: string[],
smart_action_id: string,
action_intent_params: Record<string, unknown> | null,
}
// Base body from requests for action routes / hooks
interface ActionRequestBody {
data: {
attributes: ActionRequestAttributes,
type: 'action-requests',
},
}
// Base body from requests for classic smart action routes
interface SmartActionRequestBody<T extends Record<string, any> = Record<string, any>> {
data: {
attributes: ActionRequestAttributes & { values: T },
type: 'custom-action-requests',
},
}
// Base body from requests for smart action hooks
interface SmartActionHookRequestBody {
data: {
attributes: ActionRequestAttributes & {
fields: SmartActionChangeHookField[],
changedField: string,
},
type: 'custom-action-hook-requests',
},
}
// Concrete smart action request for classic smart action routes
export interface SmartActionRequest<T extends Record<string, any> = Record<string, any>> extends ForestRequest {
body: SmartActionRequestBody<T>,
}
// Request passed to smart action load hooks
export interface SmartActionLoadHookRequest extends ForestRequest {
body: ActionRequestBody,
}
// Request passed to smart action change hooks
export interface SmartActionChangeHookRequest extends ForestRequest {
body: SmartActionHookRequestBody,
}
// Everything related to Forest constants
export const PUBLIC_ROUTES: string[];
// Everything related to record manipulation
interface RecordsSerialized {
data: Record<string, unknown>[],
included: Record<string, unknown>[],
}
interface Meta {
count: number,
[k: string]: any,
}
export class AbstractRecordTool<M extends Sequelize.Model> {
constructor(model: Sequelize.ModelCtor<M>, user: User, query: Query)
serialize(records: M | M[], meta?: Meta): Promise<RecordsSerialized>;
}
export class RecordGetter<M extends Sequelize.Model> extends AbstractRecordTool<M> {
get(recordId: string): Promise<M>;
}
export class RecordsGetter<M extends Sequelize.Model> extends AbstractRecordTool<M> {
getAll(queryExtra?: Query): Promise<M[]>;
getIdsFromRequest(request: SmartActionRequest | SmartActionLoadHookRequest | SmartActionChangeHookRequest): Promise<string[]>;
}
export class RecordsCounter<M extends Sequelize.Model> extends AbstractRecordTool<M> {
count(): Promise<number>;
}
export class RecordsExporter<M extends Sequelize.Model> extends AbstractRecordTool<M> {
streamExport(response: Response): Promise<void>;
}
export class RecordUpdater<M extends Sequelize.Model> extends AbstractRecordTool<M> {
deserialize(body: Record<string, unknown>): Promise<Record<string, unknown>>;
update(record: Record<string, unknown>, recordId: string): Promise<M>;
}
export class RecordCreator<M extends Sequelize.Model> extends AbstractRecordTool<M> {
deserialize(body: Record<string, unknown>): Promise<Record<string, unknown>>;
create(record: Record<string, unknown>): Promise<M>;
}
export class RecordRemover<M extends Sequelize.Model> extends AbstractRecordTool<M> {
remove(recordId: string | number): Promise<void>;
}
export class RecordsRemover<M extends Sequelize.Model> extends AbstractRecordTool<M> {
remove(recordIds: string[] | number[]): Promise<void>;
}
export class RecordSerializer {
constructor(model: { name: string } | Sequelize.ModelCtor<any>, user?: User, query?: Query);
serialize(records: Record<string, any> | Record<string, any>[], meta?: Meta): Promise<RecordsSerialized>;
}
// Everything related to Forest permissions
export class PermissionMiddlewareCreator {
constructor(collectionName: string)
list(): RequestHandler;
export(): RequestHandler;
details(): RequestHandler;
create(): RequestHandler;
update(): RequestHandler;
delete(): RequestHandler;
smartAction(): RequestHandler;
}
// Optional middleware(s) related to the perf
export function deactivateCountMiddleware(request: Request, response: Response, next: NextFunction): void;
// Everything related to Forest Charts
export interface StatSerialized {
data: {
type: string,
id: string,
attributes: {
value: any[]
}
};
}
export class StatSerializer {
constructor(stats: { value: any[] })
perform(): StatSerialized;
}
// Everything related to Forest request params
export interface Page {
number: number;
size: number;
}
export type FilterOperator =
// Classic
| "not" | "greater_than" | "less_than" | "after" | "before" | "contains"
| "starts_with" | "ends_with" | "not_contains" | "present" | "blank"
| "not_equal" | "equal" | "includes_all" | "in"
// Date
| "today" | "yesterday" | "previous_week" | "previous_month" | "previous_quater"
| "previous_year" | "previous_week_to_date" | "previous_month_to_date"
| "previous_quarter_to_date" | "previous_year_to_date" | "previous_x_days"
| "previous_x_days_to_date" | "past" | "future" | "before_x_hours_ago" | "after_x_hours_ago" ;
export interface Filter {
field: string;
operator: FilterOperator;
value: string;
}
export interface Query {
timezone?: string;
search?: string;
fields?: {[key: string]: string};
sort?: string;
filters?: string
page?: Page;
searchExtended?: string;
}
// Everything related to Forest collection configuration
export interface SmartFieldValueGetter<M extends Sequelize.Model = any> {
(record: M): any;
}
export interface SmartFieldValueSetter<M extends Sequelize.Model = any> {
(record: M, fieldValue: any): any;
}
export interface SmartFieldSearchQuery {
include: Sequelize.Includeable | Sequelize.Includeable[],
where: Sequelize.WhereOptions,
}
export interface SmartFieldSearcher {
(query: SmartFieldSearchQuery, search: string): SmartFieldSearchQuery | Promise<SmartFieldSearchQuery>;
}
export interface SmartFieldFiltererFilter {
condition: Filter,
where: Record<symbol, Record<symbol, any> | any>,
}
export interface SmartFieldFilterer {
(filter: SmartFieldFiltererFilter): Sequelize.WhereOptions | Promise<Sequelize.WhereOptions>;
}
export interface SegmentAggregationCreator<M extends Sequelize.Model = any> {
(model: M): Sequelize.WhereOptions;
}
type FieldType = 'Boolean' | 'Date' | 'Dateonly' | 'Enum' | 'File' | 'Number' | 'String' | 'Json' | ['Enum'] | ['Number'] | ['String'];
type FieldEnumsType = string[] | number[] | Date[] | boolean[];
export interface SmartFieldOptions {
field: string;
description?: string;
type: FieldType;
isFilterable?: boolean;
isSortable?: boolean;
isReadOnly?: boolean;
isRequired?: boolean;
reference?: string;
enums?: FieldEnumsType;
defaultValue?: any;
get?: SmartFieldValueGetter;
set?: SmartFieldValueSetter;
search?: SmartFieldSearcher;
filter?: SmartFieldFilterer;
}
export interface SmartActionField {
field: string,
description?: string,
type: FieldType,
isRequired?: boolean,
isReadOnly?: boolean,
enums?: FieldEnumsType,
defaultValue?: any,
reference?: string,
hook?: string,
widget?: string;
}
export interface SmartActionHookField extends SmartActionField {
value: any,
}
export interface SmartActionLoadHookField extends SmartActionHookField {
position: number,
}
export interface SmartActionLoadHook {
(context: { fields: SmartActionLoadHookField[], request: SmartActionLoadHookRequest }): SmartActionLoadHookField[] | Promise<SmartActionLoadHookField[]>
}
export interface SmartActionChangeHookField extends SmartActionHookField {
previousValue: any,
}
export interface SmartActionChangeHook {
(context: { fields: SmartActionChangeHookField[], changedField: SmartActionChangeHookField, request: SmartActionChangeHookRequest }): SmartActionChangeHookField[] | Promise<SmartActionChangeHookField[]>
}
export interface SmartActionHooks {
load?: SmartActionLoadHook;
change?: Record<string, SmartActionChangeHook>;
}
export interface SmartActionOptions {
name: string;
type?: 'global' | 'bulk' | 'single';
fields?: SmartActionField[];
download?: boolean;
endpoint?: string;
httpMethod?: string;
hooks?: SmartActionHooks;
description?: string;
submitButtonLabel?: string;
}
export interface SmartSegmentOptions {
name: string;
where: SegmentAggregationCreator;
}
export interface CollectionOptions {
isSearchable?: boolean;
fields?: SmartFieldOptions[];
actions?: SmartActionOptions[];
segments?: SmartSegmentOptions[];
searchFields?: string[];
}
export function collection(name: string, options: CollectionOptions): void;
export function errorHandler(): RequestHandler;