blade-client
Version:
Access your RONIN database via TypeScript.
246 lines (245 loc) • 12.9 kB
TypeScript
import { AddQuery, AlterQuery, CombinedInstructions, CountQuery, CreateQuery, DatabaseResult, DropQuery, GetQuery, ListQuery, Model, ModelField, ModelIndex, ModelPreset, Query, QueryType, RemoveQuery, ResultRecord, SetQuery, Statement, StoredObject } from "blade-compiler";
import { DeepCallable } from "blade-syntax/queries";
import { Model as Model$1 } from "blade-syntax/schema";
//#region src/triggers/index.d.ts
type ParentTrigger = {
model: string;
type: TriggerType;
};
interface TriggerOptions<TType extends QueryType = QueryType, TSchema = unknown, TQuery = FilteredTriggerQuery<TType>> {
/** The instructions of the query that is being executed. */
query: TQuery;
/** Whether multiple records are being accessed by the query. */
multipleRecords: boolean;
/** An instance of the current client, which can be used for nested queries. */
client: ReturnType<typeof createSyntaxFactory>;
/** Can be used for sharing values between the triggers of a model. */
context: Map<string, any>;
/**
* If the query was generated by another trigger, this property will contain
* information about that trigger.
*/
parentTrigger?: ParentTrigger;
/** The model for which the query is being executed. */
model?: string;
/** The database for which the query is being executed. */
database?: string;
/** A function for keeping the worker alive as long as a promise is not resolved. */
waitUntil?: QueryHandlerOptions['waitUntil'];
/** The list of records, before the query was executed. */
previousRecords: Array<TSchema>;
/** The list of records, after the query was executed. */
records: Array<TSchema>;
}
type ReturnedQueries = () => Array<Promise<any>>;
type FilteredTriggerQuery<TType extends QueryType, TQuery extends CombinedInstructions = CombinedInstructions> = RecursivePartial<TQuery> & Pick<TQuery, TType extends 'count' ? never : TType extends 'add' ? 'to' : TType extends 'get' ? never : TType extends 'set' ? 'to' : TType extends 'remove' ? never : never>;
type BeforeTriggerHandler<TOptions extends object> = (options: TOptions) => Array<Query> | Promise<Array<Query>> | ReturnedQueries | Promise<ReturnedQueries>;
type DuringTriggerHandler<TOptions extends object, TType extends QueryType, TQuery extends FilteredTriggerQuery<TType> = FilteredTriggerQuery<TType>> = (options: TOptions) => TQuery | Promise<TQuery> | Query | Promise<Query>;
type AfterTriggerHandler<TOptions extends object> = (options: TOptions) => Array<Query> | Promise<Array<Query>> | ReturnedQueries | Promise<ReturnedQueries>;
type ResolvingTriggerHandler<TOptions extends object, TSchema = unknown> = (options: TOptions) => TSchema | Promise<TSchema>;
type FollowingTriggerHandler<TOptions extends object> = (options: TOptions) => void | Promise<void>;
declare const TRIGGER_TYPES: readonly ["before", "during", "after", "resolving", "following"];
type TriggerType = (typeof TRIGGER_TYPES)[number];
type TriggerName = ({ [K in QueryType]: `before${Capitalize<K>}` } | { [K in QueryType]: K } | { [K in QueryType]: `after${Capitalize<K>}` } | { [K in QueryType]: `resolving${Capitalize<K>}` } | { [K in QueryType]: `following${Capitalize<K>}` })[QueryType];
type Trigger<TStage extends TriggerType, TType extends QueryType, TSchema extends (TStage extends 'before' | 'during' | 'after' ? never : unknown) = never, TOptions extends object = TriggerOptions<TType, TSchema>> = TStage extends 'before' ? BeforeTriggerHandler<TOptions> : TStage extends 'during' ? DuringTriggerHandler<TOptions, TType> : TStage extends 'after' ? AfterTriggerHandler<TOptions> : TStage extends 'resolving' ? ResolvingTriggerHandler<TOptions, TSchema> : TStage extends 'following' ? FollowingTriggerHandler<TOptions> : never;
type Triggers<TType extends QueryType, TSchema = unknown, TOptions extends object = TriggerOptions<TType, TSchema>> = { [K in TriggerName]?: K extends 'before' | `before${string}` ? Trigger<'before', TType, never, TOptions> : K extends 'after' | `after${string}` ? Trigger<'after', TType, never, TOptions> : K extends 'resolving' | `resolving${string}` ? Trigger<'resolving', TType, TSchema, TOptions> : K extends 'following' | `following${string}` ? Trigger<'following', TType, TSchema, TOptions> : Trigger<'during', TType, never, TOptions> };
type TriggersPerModel<TSchema = unknown> = Record<string, Triggers<QueryType, TSchema>>;
/**
* Constructs the method name used for a particular type of trigger and query.
* For example, if `triggerType` is "following" and `queryType` is "add", the
* resulting method name would be `followingAdd`.
*
* @param triggerType - The type of trigger.
* @param queryType - The type of query.
*
* @returns The method name constructed from the trigger and query types.
*/
declare const getTriggerName: (triggerType: TriggerType, queryType: QueryType) => TriggerName;
//#endregion
//#region src/types/storage.d.ts
type StorableObject = {
query: {
index: number;
type: 'set' | 'add';
};
name?: string;
schema: string;
field: string;
value?: any;
contentType: string;
reference: StoredObject | null;
};
type StorableObjectValue = File | ReadableStream | Buffer | ArrayBuffer | Blob;
//#endregion
//#region src/types/utils.d.ts
interface QueryHandlerOptions {
/**
* Object containing triggers for defined schemas.
*/
triggers?: TriggersPerModel;
/**
* Token used to authenticate against RONIN. By default,
* `process.env.RONIN_TOKEN` will be used.
*/
token?: string;
/**
* Allows for executing SQL statements generated by the client.
*
* @param statements - An array of SQL statements to execute.
* @param options - Additional configuration for the database call.
*
* @returns A promise that resolves with the result of the SQL statements.
*/
databaseCaller?: (statements: Array<Statement>, options: {
database: string;
token?: string;
stream?: string;
}) => Promise<DatabaseResult> | DatabaseResult;
/**
* Allows for uploading storage objects provided to the client.
*
* @param object - The object to upload.
* @param options - Additional configuration for the storage call.
*
* @returns A promise that resolves with a reference to the uploaded object.
*/
storageCaller?: (object: StorableObject, options: {
token: string;
}) => Promise<StoredObject> | StoredObject;
/**
* Invoked by the query syntax when queries are to be executed.
*
* @param queries - A list of queries that should be executed.
* @param options - Configuration options that were provided for the queries.
*
* @returns Formatted results for the provided queries.
*/
syntaxCallback?: (queries: Array<Query>, options: QueryHandlerOptions) => Promise<FormattedResults<ResultRecord>>;
/**
* A particular connection identifier to re-use for the provided queries.
*
* Useful for ensuring that multiple transactions are sent through the same connection,
* which guarantees their order during transport.
*/
stream?: string;
/**
* Allows for extending the lifetime of the edge worker invocation until the
* provided promise has been resolved. If the `triggers` option is provided on
* an edge runtime, this option is required.
*/
waitUntil?: (promise: Promise<unknown>) => void;
/**
* If the query should be run for a specific database within your space, you may
* provide the desired database name here.
*/
database?: string;
/**
* Allows for indicating whether the client is being invoked from inside of a trigger,
* which lets the client ensure that the trigger is not invoked recursively.
*
* It is highly recommended to rely on `options.client` for running queries in triggers
* instead of initializing a custom client, as that resumes the configuration.
*/
parentTrigger?: ParentTrigger;
/** A list of models used for compiling Blade queries to SQL. */
models?: Array<Model>;
/**
* Applies a default `limitedTo` instruction to queries obtaining multiple records.
* Useful for environments in which memory is tightly constrained.
*/
defaultRecordLimit?: number;
/** Log helpful debugging information. */
debug?: boolean;
}
/**
* Utility type to make all properties of an object optional.
*/
type RecursivePartial<T$1> = { [K in keyof T$1]?: T$1[K] extends Array<infer U> ? Array<RecursivePartial<U>> : T$1[K] extends object ? RecursivePartial<T$1[K]> : T$1[K] };
/**
* Utility type to convert a tuple of promises into a tuple of their resolved types.
*/
type PromiseTuple<T$1 extends [Promise<any>, ...Array<Promise<any>>] | Array<Promise<any>>> = { [P in keyof T$1]: Awaited<T$1[P]> };
type RegularFormattedResult<T$1> = number | (T$1 & ResultRecord) | (Array<T$1 & ResultRecord> & {
moreBefore?: string;
moreAfter?: string;
}) | null;
type ExpandedFormattedResult<T$1> = Record<Model['slug'], RegularFormattedResult<T$1>>;
type FormattedResult<T$1> = RegularFormattedResult<T$1> | ExpandedFormattedResult<T$1>;
type FormattedResults<T$1> = Array<FormattedResult<T$1>>;
//#endregion
//#region src/queries.d.ts
declare function runQueriesWithStorageAndTriggers<T$1 extends ResultRecord>(queries: Array<Query>, options: QueryHandlerOptions): Promise<FormattedResults<T$1>>;
declare function runQueriesWithStorageAndTriggers<T$1 extends ResultRecord>(queries: Record<string, Array<Query>>, options: QueryHandlerOptions): Promise<Record<string, FormattedResults<T$1>>>;
//#endregion
//#region src/index.d.ts
/**
* Creates a syntax factory for generating and executing queries.
*
* @param options - An optional object of options for the query execution.
*
* Alternatively, a function that returns the object may be provided instead, which is
* useful for cases in which the config must be generated dynamically whenever a query
* is executed.
*
* @returns An object with methods for generating and executing different types
* of queries.
*
* ### Usage
* ```typescript
* const { get, set, add, remove, count } = createSyntaxFactory({
* token: '...'
* });
*
* await get.accounts();
*
* await set.account({
* with: {
* email: 'mike@gmail.com',
* },
* to: {
* status: 'active',
* },
* });
*
* await add.account({ with: { email: 'mike@gmail.com' } });
*
* await remove.accounts.with.emailVerified.notBeing(true);
*
* await count.accounts();
*
* // Execute a batch of operations
* const batchResult = await batch(() => [
* get.accounts(),
* get.account.with.email('mike@gmail.com')
* ]);
* ```
*/
declare const createSyntaxFactory: (options: QueryHandlerOptions | (() => QueryHandlerOptions)) => {
get: DeepCallable<GetQuery>;
set: DeepCallable<SetQuery>;
add: DeepCallable<AddQuery>;
remove: DeepCallable<RemoveQuery>;
count: DeepCallable<CountQuery, number>;
list: DeepCallable<ListQuery>;
create: DeepCallable<CreateQuery, Model$1>;
alter: DeepCallable<AlterQuery, Model$1 | ModelField | ModelIndex | ModelPreset>;
drop: DeepCallable<DropQuery, Model$1>;
batch: <T extends [Promise<any>, ...Array<Promise<any>>] | Array<Promise<any>>>(operations: () => T, queryOptions?: Record<string, unknown>) => Promise<PromiseTuple<T>>;
sql: (strings: TemplateStringsArray, ...values: Array<unknown>) => Promise<any>;
sqlBatch: <T extends [Promise<any>, ...Array<Promise<any>>] | Array<Promise<any>>>(operations: () => T, queryOptions?: Record<string, unknown>) => Promise<PromiseTuple<T>>;
};
declare const get: DeepCallable<GetQuery>;
declare const set: DeepCallable<SetQuery>;
declare const add: DeepCallable<AddQuery>;
declare const remove: DeepCallable<RemoveQuery>;
declare const count: DeepCallable<CountQuery, number>;
declare const list: DeepCallable<ListQuery>;
declare const create: DeepCallable<CreateQuery, Model$1>;
declare const alter: DeepCallable<AlterQuery, Model$1 | ModelField | ModelIndex | ModelPreset>;
declare const drop: DeepCallable<DropQuery, Model$1>;
declare const batch: <T extends [Promise<any>, ...Array<Promise<any>>] | Array<Promise<any>>>(operations: () => T, queryOptions?: Record<string, unknown>) => Promise<PromiseTuple<T>>;
declare const sql: (strings: TemplateStringsArray, ...values: Array<unknown>) => Promise<any>;
declare const sqlBatch: <T extends [Promise<any>, ...Array<Promise<any>>] | Array<Promise<any>>>(operations: () => T, queryOptions?: Record<string, unknown>) => Promise<PromiseTuple<T>>;
declare const runQueries: typeof runQueriesWithStorageAndTriggers;
//#endregion
export { TriggerType as C, TriggerOptions as S, getTriggerName as T, QueryHandlerOptions as _, create as a, TRIGGER_TYPES as b, get as c, runQueries as d, set as f, PromiseTuple as g, FormattedResults as h, count as i, list as l, sqlBatch as m, alter as n, createSyntaxFactory as o, sql as p, batch as r, drop as s, add as t, remove as u, StorableObject as v, Triggers as w, Trigger as x, StorableObjectValue as y };