UNPKG

superflare

Version:

A full-stack framework for Cloudflare Workers.

421 lines (400 loc) 16.1 kB
interface StorageDiskConfig { binding: R2Bucket; /** * Optional. The public URL to the disk. If you have made your R2 bucket public, you can * set this to the URL of the bucket. If your R2 bucket is private but you want to allow * access to objects, you can set this to a local route like `/storage/<diskname>` where you are * proxying the R2 bucket. * * If you do not set this, `storage()->url(key)` for objects in this disk will return `null`. */ publicPath?: string; } type ChannelAuthorizeFunction = (user: any, ...args: any) => boolean | Promise<boolean>; type ChannelPresenceFunction = (user: any, ...args: any) => any | Promise<any>; type ChannelConfig = { binding?: DurableObjectNamespace; authorize?: ChannelAuthorizeFunction; presence?: ChannelPresenceFunction; }; interface ChannelsConfig { default: { binding: DurableObjectNamespace; }; [name: string]: ChannelConfig; } interface SuperflareUserConfig { /** * A secret key used to sign cookies and other sensitive data. */ appKey?: string; database?: { default: D1Database; } & Record<string, D1Database>; storage?: { default: StorageDiskConfig; } & Record<string, StorageDiskConfig>; queues?: { default: Queue; } & Record<string, Queue>; listeners?: { [name: string]: any[]; }; channels?: ChannelsConfig; } declare function setConfig(userConfig: SuperflareUserConfig): SuperflareUserConfig; /** * Accept a general set of request attributes in order to work * with both Cloudflare Workers and Pages. */ type DefineConfigContext<Env = Record<string, any>> = { /** * Request will not always be present, e.g. if the context is a queue worker. */ request?: Request; env: Env; ctx: ExecutionContext; }; /** * Return both the userConfig and the ctx so we can re-use that in the request * handlers without asking the user to pass them again. */ type DefineConfigResult = SuperflareUserConfig; declare function defineConfig<Env = Record<string, any>>(callback: (ctx: DefineConfigContext<Env>) => SuperflareUserConfig): (ctx: DefineConfigContext<Env>) => DefineConfigResult; declare class DatabaseException extends Error { } declare function seed(callback: () => void): (database: D1Database) => void; type R2Input = Parameters<R2Bucket["put"]>[1]; declare function storage(disk?: string): Storage; declare class Storage { diskName: string; disk: StorageDiskConfig; constructor(diskName: string, disk: StorageDiskConfig); url(key: string): string | null; get(key: string): Promise<R2ObjectBody | null>; delete(key: string): Promise<void>; put(...args: Parameters<R2Bucket["put"]>): Promise<R2Object>; /** * Takes an input without a key and generates a random filename for you. * Optionally pass an `{ extension: string }` option to add an extension to the filename. */ putRandom(input: R2Input, options?: R2PutOptions & { extension?: string; prefix?: string; }): Promise<R2Object>; } declare function servePublicPathFromStorage(path: string): Promise<Response>; declare class Factory { #private; model: typeof Model; constructor(model: typeof Model); static for(model: typeof Model): Factory; create(attributes?: Record<string, any>): Promise<ModelInstance<any>>; definition(definition: () => Record<string, any>): this; } /** * Superflare accepts external implementations of Session which match the following signature: */ interface Session$1 { id: string; data: any; has(key: string): boolean; get(key: string): any; set(key: string, value: any): void; unset(key: string): void; flash(key: string, value: any): void; } /** * Superflare exposes its own Session implementation which includes a dirty tracker to allow * it to automatically commit changes to the session as a Cookie header on the outgoing response. */ declare class SuperflareSession implements Session$1 { private session; private dirty; constructor(session: Session$1); get id(): string; get data(): any; has(key: string): boolean; get(key: string): any; /** * Get a flashed value from the session, and indicate that the session has been modified. */ getFlash(key: string): any; set(key: string, value: any): void; unset(key: string): void; /** * Flash a value to the session. To read the flashed value on a future request, use `getFlash`. */ flash(key: string, value: any): void; isDirty(): boolean; getSession(): Session$1; } declare function handleFetch<Env>({ request, env, ctx, config, session, getSessionCookie, }: { request: Request; env: Env; ctx: ExecutionContext; config: ReturnType<typeof defineConfig<Env>>; session: SuperflareSession; /** * Superflare will commit changes to the session as a Cookie header on the outgoing response. * You must provide a way to get that cookie. This likely comes from your session storage. */ getSessionCookie: () => Promise<string>; }, getResponse: () => Promise<Response>): Promise<Response>; declare function handleQueue<Env>(batch: MessageBatch, env: Env, ctx: ExecutionContext, config: ReturnType<typeof defineConfig<Env>>): Promise<void[]>; declare abstract class Job { /** * The name of the queue on which to dispatch this job. */ queue: string; constructor(); abstract handle(): Promise<void>; /** * The private instance method we use to dispatch a job onto the queue. */ private dispatch; /** * Dispatch the job with the given arguments. */ static dispatch<T extends Job>(this: new (...arg: any[]) => T, ...args: any[]): Promise<void>; /** * Convert the constructor arguments to a payload that can be sent to the queue. */ private toQueuePayload; static register(job: any): void; } declare class SuperflareAuth { session: Session$1; constructor(session: Session$1); attempt<M extends BaseModel>(model: M, credentials: { email: string; password: string; }): Promise<boolean>; check<M extends new (args: any) => InstanceType<M>>(model: M): Promise<boolean>; id(): any; login(user: any): void; user<M extends new (args: any) => InstanceType<M>>(model: M): Promise<InstanceType<M> | null>; logout(): void; } declare function hash(): { make(input: string): Promise<string>; check(input: string, hash: string): Promise<boolean>; }; declare class Event { static shouldQueue: boolean; static queue: string; static dispatch<T extends Event>(this: { new (...arg: any[]): T; shouldQueue: boolean; queue: string; }, ...args: any[]): Promise<void>; broadcastTo?(): string; static register(event: any): void; } declare abstract class Listener { abstract handle(event: any): void; } declare function handleWebSockets(request: Request, { auth, session, userModel, channelName: specifiedChannelName, }?: { auth?: SuperflareAuth; session?: SuperflareSession; userModel?: any; channelName?: string; }): Promise<Response>; interface Session { webSocket: WebSocket; id: string; quit?: boolean; user?: UserPayload; } interface UserPayload { sessionId?: string; presenceData?: any; } type Env = unknown; declare class Channel implements DurableObject { storage: DurableObjectStorage; sessions: Session[]; env: Env; constructor(controller: any, env: Env); fetch(request: Request): Promise<Response>; handleSession(webSocket: WebSocket, user?: UserPayload): Promise<void>; broadcast(message: any): void; } type SchemaMode = "create" | "update" | "delete"; declare class Schema { protected tableName: String; protected builder: SchemaBuilder; protected mode: SchemaMode; constructor(tableName: String, builder: SchemaBuilder, mode?: SchemaMode); addCommand(command: string): void; static create(tableName: string, callback: (builder: SchemaBuilder) => void): Schema; static update(tableName: string, callback: (builder: SchemaBuilder) => void): Schema; static rename(oldTableName: string, newTableName: string): Schema; static drop(tableName: string): Schema; toSql(): string; } declare class SchemaBuilder { protected tableName: String; columns: ColumnDefinition[]; commands: string[]; constructor(tableName: String); blob(columnName: string): ColumnDefinition; boolean(columnName: string): ColumnDefinition; date(columnName: string): ColumnDefinition; dropColumn(columnName: string): this; dateTime(columnName: string): ColumnDefinition; increments(columnName: string): ColumnDefinition; float(columnName: string): ColumnDefinition; integer(columnName: string, primaryKey?: boolean): ColumnDefinition; renameColumn(from: string, to: string): this; string(columnName: string): ColumnDefinition; text(columnName: string): ColumnDefinition; timestamps(): void; protected addCommand(command: string): this; protected addColumn(columnName: string, columnType: string, options?: ColumnDefinitionOptions): ColumnDefinition; } interface ColumnDefinitionOptions { primaryKey?: boolean; } declare class ColumnDefinition { #private; columnName: string; columnType: string; options?: ColumnDefinitionOptions | undefined; constructor(columnName: string, columnType: string, options?: ColumnDefinitionOptions | undefined); toString(): string; nullable(): this; unique(): this; } /** * Copied from Remix: * @see https://github.com/remix-run/remix/blob/72c22b3deb9e84e97359b481f7f2af6cdc355877/packages/remix-server-runtime/formData.ts * Copyright 2021 Remix Software Inc. * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ type UploadHandlerPart = { name: string; filename?: string; contentType: string; data: AsyncIterable<Uint8Array>; stream: ReadableStream<Uint8Array>; }; type UploadHandler = (part: UploadHandlerPart) => Promise<File | string | null | undefined>; /** * Allows you to handle multipart forms (file uploads) for your app. */ declare function parseMultipartFormData(request: Request, uploadHandler: UploadHandler): Promise<FormData>; declare function handleScheduled<Env>(event: ScheduledEvent, env: Env, ctx: ExecutionContext, config: ReturnType<typeof defineConfig<Env>>, scheduleDefinition: (scheduler: Scheduler) => void | Promise<void>): Promise<void>; declare class Scheduler { tasks: any[]; run(fn: () => Promise<any> | any): Task; job(job: any): Task; } declare class Task { fn: any; constraints: any[]; constructor(fn: any, constraints?: any[]); /** * Run every minute. */ everyMinute(): this; /** * Run hourly at the top. */ hourly(): this; /** * Run daily at midnight UTC. */ daily(): this; /** * Run daily at a specific time UTC. */ dailyAt(time: string): this; /** * Run weekly on Sunday at midnight UTC. */ weekly(): this; /** * Run weekly on a specific day of the week at a specific time UTC. */ weeklyOn(day: string, time: string): this; /** * Run monthly on the first day of the month at midnight UTC. */ monthly(): this; /** * Run monthly on a specific date of the month at a specific time UTC. */ monthlyOn(date: string, time: string): this; yearly(): this; } /** * Export everything from `index.ts` *except* Model, because we have to manually * compose and export types for Model/QueryBuilder. **/ /** * Shape of the model instance. */ interface ModelInstance<M> { id: number; hidden: string[]; save(): Promise<boolean>; delete(): Promise<boolean>; update(attributes: any): Promise<boolean>; toJSON(): any; belongsTo<M extends BaseModel>(model: M): BelongsTo<M>; hasOne<M extends BaseModel>(model: M): HasOne<M>; hasMany<M extends BaseModel>(model: M): HasMany<M>; } interface BelongsTo<M extends BaseModel, R = InstanceType<M>> extends QueryBuilder<M, R> { associate(model: any): R; dissociate(): R; } interface HasOne<M extends BaseModel, R = InstanceType<M>> extends QueryBuilder<M, R> { save(model: any): Promise<R>; create(attributes: any): Promise<R>; } interface HasMany<M extends BaseModel, R = InstanceType<M>[]> extends QueryBuilder<M, R> { save(model: any): Promise<R>; create(attributes: any): Promise<R>; } /** * Shape of the model constructor (static properties). */ interface BaseModel<M = any> { find<T extends BaseModel>(this: T, ids: number[]): Promise<InstanceType<T>[]>; find<T extends BaseModel>(this: T, id: number): Promise<null | InstanceType<T>>; first<T extends BaseModel>(this: T): Promise<null | InstanceType<T>>; orderBy<T extends BaseModel>(this: T, field: string, direction?: "asc" | "desc"): QueryBuilder<T>; all<T extends BaseModel>(this: T): Promise<InstanceType<T>[]>; where<T extends BaseModel>(this: T, field: string, value: string | number): QueryBuilder<T>; where<T extends BaseModel>(this: T, field: string, operator: string, value?: string | number): QueryBuilder<T>; whereIn<T extends BaseModel>(this: T, field: string, values: (string | number)[]): QueryBuilder<T>; with<T extends BaseModel>(this: T, relationName: string | string[]): QueryBuilder<T>; create<T extends BaseModel>(this: T, attributes: any): Promise<InstanceType<T>>; count<T extends BaseModel>(this: T): Promise<number>; query<T extends BaseModel>(this: T): QueryBuilder<T>; register(model: any): void; tableName: string; connection: string; new (attributes?: any): ModelInstance<M>; } interface QueryBuilder<T extends BaseModel, R = InstanceType<T>> { count<T>(this: T): Promise<number>; find<T>(this: T, id: number): Promise<null | R>; find<T>(this: T, ids: number[]): Promise<R[]>; where<T>(this: T, field: string, value: any): this; where<T>(this: T, field: string, operator: string, value?: any): this; whereIn<T>(this: T, field: string, values: (string | number)[]): this; with<T>(this: T, relationName: string | string[]): this; limit<T>(this: T, limit: number): this; get(): Promise<R[]>; first(): Promise<null | R>; orderBy<T>(this: T, field: string, direction?: "asc" | "desc"): this; then(onfulfilled?: (value: R[]) => R[] | PromiseLike<R[]>): Promise<R[]>; catch(onrejected?: (reason: any) => any): Promise<R[]>; } declare const Model: BaseModel; export { BaseModel, BelongsTo, Channel, DatabaseException, DefineConfigResult, Event, Factory, HasMany, HasOne, Job, Listener, Model, ModelInstance, R2Input, Schema, Session$1 as Session, SuperflareAuth, SuperflareSession, SuperflareUserConfig, defineConfig, handleFetch, handleQueue, handleScheduled, handleWebSockets, hash, parseMultipartFormData, seed, servePublicPathFromStorage, setConfig, storage };