@dataplan/pg
Version:
PostgreSQL step classes for Grafast
275 lines • 14.8 kB
TypeScript
import type { ObjectStep } from "grafast";
import { ExecutableStep } from "grafast";
import type { SQL } from "pg-sql2";
import type { PgCodecAttribute, PgCodecAttributes, PgCodecAttributeVia } from "./codecs.js";
import type { PgExecutor, PgExecutorContextPlans } from "./executor.js";
import type { Expand, GetPgCodecAttributes, GetPgRegistryCodecRelations, GetPgRegistryCodecs, PgCodec, PgCodecRelation, PgCodecRelationConfig, PgCodecWithAttributes, PgRefDefinition, PgRegistry, PgRegistryConfig, PlanByUniques } from "./interfaces.js";
import type { PgClassExpressionStep } from "./steps/pgClassExpression.js";
import type { PgSelectArgumentDigest, PgSelectArgumentSpec, PgSelectMode, PgSelectStep } from "./steps/pgSelect.js";
import type { PgSelectSinglePlanOptions, PgSelectSingleStep } from "./steps/pgSelectSingle.js";
export declare function EXPORTABLE<T, TScope extends any[]>(factory: (...args: TScope) => T, args: [...TScope], nameHint?: string): T;
export declare function isForbidden(thing: unknown): thing is {
$$export: false;
};
/** @deprecated Use DataplanPg.PgResourceUniqueExtensions instead */
export type PgResourceUniqueExtensions = DataplanPg.PgResourceUniqueExtensions;
/** @deprecated Use DataplanPg.PgResourceExtensions instead */
export type PgResourceExtensions = DataplanPg.PgResourceExtensions;
/** @deprecated Use DataplanPg.PgResourceParameterExtensions instead */
export type PgResourceParameterExtensions = DataplanPg.PgResourceParameterExtensions;
/**
* If this is a functional (rather than static) resource, this describes one of
* the parameters it accepts.
*/
export interface PgResourceParameter<TName extends string | null = string | null, TCodec extends PgCodec = PgCodec> {
/**
* Name of the parameter, if null then we must use positional rather than
* named arguments
*/
name: TName;
/**
* The type of this parameter
*/
codec: TCodec;
/**
* If true, then this parameter must be supplied, otherwise it's optional.
*/
required: boolean;
/**
* If true and the parameter is supplied, then the parameter must not be
* null.
*/
notNull?: boolean;
extensions?: PgResourceParameterExtensions;
}
/**
* Description of a unique constraint on a PgResource.
*/
export interface PgResourceUnique<TAttributes extends PgCodecAttributes = PgCodecAttributes> {
/**
* The attributes that are unique
*/
attributes: ReadonlyArray<keyof TAttributes & string>;
/**
* If this is true, this represents the "primary key" of the resource.
*/
isPrimary?: boolean;
description?: string;
/**
* Space for you to add your own metadata
*/
extensions?: PgResourceUniqueExtensions;
}
export interface PgCodecRefPathEntry {
relationName: string;
}
export type PgCodecRefPath = PgCodecRefPathEntry[];
/** @deprecated Use DataplanPg.PgCodecRefExtensions instead */
export type PgCodecRefExtensions = DataplanPg.PgCodecRefExtensions;
export interface PgCodecRef {
definition: PgRefDefinition;
paths: Array<PgCodecRefPath>;
description?: string;
extensions?: PgCodecRefExtensions;
}
export interface PgCodecRefs {
[refName: string]: PgCodecRef;
}
/**
* Configuration options for your PgResource
*/
export interface PgResourceOptions<TName extends string = string, TCodec extends PgCodec = PgCodec, TUniques extends ReadonlyArray<PgResourceUnique<GetPgCodecAttributes<TCodec>>> = ReadonlyArray<PgResourceUnique<GetPgCodecAttributes<TCodec>>>, TParameters extends readonly PgResourceParameter[] | undefined = readonly PgResourceParameter[] | undefined> {
/**
* The associated codec for this resource
*/
codec: TCodec;
/**
* The PgExecutor to use when servicing this resource; different executors can
* have different caching rules. A plan that uses one executor cannot be
* inlined into a plan for a different executor.
*/
executor: PgExecutor;
selectAuth?: (($step: PgSelectStep<PgResource<any, any, any, any, any>>) => void) | null;
name: TName;
identifier?: string;
from: TParameters extends readonly PgResourceParameter[] ? (...args: PgSelectArgumentDigest[]) => SQL : SQL;
uniques?: TUniques;
extensions?: PgResourceExtensions;
parameters?: TParameters;
description?: string;
/**
* Set true if this resource will only return at most one record - this is
* generally only useful for PostgreSQL function resources, in which case you
* should set it false if the function `returns setof` and true otherwise.
*/
isUnique?: boolean;
sqlPartitionByIndex?: SQL;
isMutation?: boolean;
hasImplicitOrder?: boolean;
/**
* If true, this indicates that this was originally a list (array) and thus
* should be treated as having a predetermined and reasonable length rather
* than being unbounded. It's just a hint to schema generation, it doesn't
* affect planning.
*/
isList?: boolean;
/**
* "Virtual" resources cannot be selected from/inserted to/etc, they're
* normally used to generate other resources that are _not_ virtual.
*/
isVirtual?: boolean;
}
export interface PgFunctionResourceOptions<TNewName extends string = string, TCodec extends PgCodec = PgCodec, TUniques extends ReadonlyArray<PgResourceUnique<GetPgCodecAttributes<TCodec>>> = ReadonlyArray<PgResourceUnique<GetPgCodecAttributes<TCodec>>>, TNewParameters extends readonly PgResourceParameter[] = readonly PgResourceParameter[]> {
name: TNewName;
identifier?: string;
from: (...args: PgSelectArgumentDigest[]) => SQL;
parameters: TNewParameters;
returnsSetof: boolean;
returnsArray: boolean;
uniques?: TUniques;
extensions?: PgResourceExtensions;
isMutation?: boolean;
hasImplicitOrder?: boolean;
selectAuth?: (($step: PgSelectStep<PgResource<any, any, any, any, any>>) => void) | null;
description?: string;
}
/**
* PgResource represents any resource of SELECT-able data in Postgres: tables,
* views, functions, etc.
*/
export declare class PgResource<TName extends string = string, TCodec extends PgCodec = PgCodec, TUniques extends ReadonlyArray<PgResourceUnique<GetPgCodecAttributes<TCodec>>> = ReadonlyArray<PgResourceUnique<GetPgCodecAttributes<TCodec>>>, TParameters extends readonly PgResourceParameter[] | undefined = readonly PgResourceParameter[] | undefined, TRegistry extends PgRegistry<any, any, any, any> = PgRegistry<any, any, any, any>> {
readonly registry: TRegistry;
readonly codec: TCodec;
readonly executor: PgExecutor;
readonly name: TName;
readonly identifier: string;
readonly from: SQL | ((...args: PgSelectArgumentDigest[]) => SQL);
readonly uniques: TUniques;
private selectAuth?;
/**
* If present, implies that the resource represents a `setof composite[]` (i.e.
* an array of arrays) - and thus is not appropriate to use for GraphQL
* Cursor Connections.
*
* @experimental
*/
sqlPartitionByIndex: SQL | null;
readonly parameters: TParameters;
readonly description: string | undefined;
readonly isUnique: boolean;
readonly isMutation: boolean;
readonly hasImplicitOrder: boolean;
/**
* If true, this indicates that this was originally a list (array) and thus
* should be treated as having a predetermined and reasonable length rather
* than being unbounded. It's just a hint to schema generation, it doesn't
* affect planning.
*/
readonly isList: boolean;
/**
* "Virtual" resources cannot be selected from/inserted to/etc, they're
* normally used to generate other resources that are _not_ virtual.
*/
readonly isVirtual: boolean;
extensions: Partial<PgResourceExtensions> | undefined;
/**
* @param from - the SQL for the `FROM` clause (without any
* aliasing). If this is a subquery don't forget to wrap it in parens.
* @param name - a nickname for this resource. Doesn't need to be unique
* (but should be). Used for making the SQL query and debug messages easier
* to understand.
*/
constructor(registry: TRegistry, options: PgResourceOptions<TName, TCodec, TUniques, TParameters>);
/**
* Often you can access table records from a table directly but also from a
* view or materialized view. This method makes it convenient to construct
* multiple datasources that all represent the same underlying table
* type/relations/etc.
*/
static alternativeResourceOptions<TCodec extends PgCodec, const TNewUniques extends ReadonlyArray<PgResourceUnique<GetPgCodecAttributes<TCodec>>>, const TNewName extends string>(baseOptions: PgResourceOptions<any, TCodec, any, undefined>, overrideOptions: {
name: TNewName;
identifier?: string;
from: SQL;
uniques?: TNewUniques;
extensions?: PgResourceExtensions;
}): PgResourceOptions<TNewName, TCodec, TNewUniques, undefined>;
/**
* Often you can access table records from a table directly but also from a
* number of functions. This method makes it convenient to construct multiple
* datasources that all represent the same underlying table
* type/relations/etc but pull their rows from functions.
*/
static functionResourceOptions<TCodec extends PgCodec, const TNewParameters extends readonly PgResourceParameter[], const TNewUniques extends ReadonlyArray<PgResourceUnique<GetPgCodecAttributes<TCodec>>>, const TNewName extends string>(baseOptions: Pick<PgResourceOptions<any, TCodec, any, any>, "codec" | "executor" | "selectAuth">, overrideOptions: PgFunctionResourceOptions<TNewName, TCodec, TNewUniques, TNewParameters>): PgResourceOptions<TNewName, TCodec, TNewUniques, TNewParameters>;
toString(): string;
getRelations(): GetPgRegistryCodecRelations<TRegistry, TCodec>;
getRelation<TRelationName extends keyof GetPgRegistryCodecRelations<TRegistry, TCodec>>(name: TRelationName): GetPgRegistryCodecRelations<TRegistry, TCodec>[TRelationName];
resolveVia(via: PgCodecAttributeVia, attr: string): {
relationName: string;
attributeName: string;
relation: PgCodecRelation;
attribute: PgCodecAttribute;
};
getReciprocal<TOtherCodec extends GetPgRegistryCodecs<TRegistry>, TOtherRelationName extends keyof GetPgRegistryCodecRelations<TRegistry, TOtherCodec>>(otherCodec: TOtherCodec, otherRelationName: TOtherRelationName): [
relationName: keyof GetPgRegistryCodecRelations<TRegistry, TCodec>,
relation: GetPgRegistryCodecRelations<TRegistry, TCodec>[keyof GetPgRegistryCodecRelations<TRegistry, TCodec>]
] | null;
get(spec: PlanByUniques<GetPgCodecAttributes<TCodec>, TUniques>, _internalOptionsDoNotPass?: PgSelectSinglePlanOptions): GetPgCodecAttributes<TCodec> extends PgCodecAttributes ? PgSelectSingleStep<this> : PgClassExpressionStep<TCodec, this>;
find(spec?: {
[key in keyof GetPgCodecAttributes<TCodec>]?: ExecutableStep | string | number;
}): PgSelectStep<this>;
execute(args?: ReadonlyArray<PgSelectArgumentSpec>, mode?: PgSelectMode): ExecutableStep<unknown>;
applyAuthorizationChecksToPlan($step: PgSelectStep<this>): void;
/**
* @deprecated Please use `.executor.context()` instead - all resources for the
* same executor must use the same context to allow for SQL inlining, unions,
* etc.
*/
context(): ObjectStep<PgExecutorContextPlans>;
}
export interface PgRegistryBuilder<TCodecs extends {
[name in string]: PgCodec<name, PgCodecAttributes | undefined, any, any, any, any, any>;
}, TResources extends {
[name in string]: PgResourceOptions<name, PgCodec, ReadonlyArray<PgResourceUnique<PgCodecAttributes>>, readonly PgResourceParameter[] | undefined>;
}, TRelations extends {
[codecName in keyof TCodecs]?: {
[relationName in string]: PgCodecRelationConfig<PgCodec<string, PgCodecAttributes, any, any, undefined, any, undefined>, PgResourceOptions<any, PgCodecWithAttributes, any, any>>;
};
}, TExecutors extends {
[name in string]: PgExecutor<any>;
}> {
getRegistryConfig(): PgRegistryConfig<Expand<TCodecs>, Expand<TResources>, Expand<TRelations>, Expand<TExecutors>>;
addExecutor<const TExecutor extends PgExecutor>(codec: TExecutor): PgRegistryBuilder<TCodecs, TResources, TRelations, TExecutors & {
[name in TExecutor["name"]]: TExecutor;
}>;
addCodec<const TCodec extends PgCodec>(codec: TCodec): PgRegistryBuilder<TCodecs & {
[name in TCodec["name"]]: TCodec;
}, TResources, TRelations, TExecutors>;
addResource<const TResource extends PgResourceOptions<any, any, any, any>>(resource: TResource): PgRegistryBuilder<TCodecs & {
[name in TResource["codec"]["name"]]: TResource["codec"];
}, TResources & {
[name in TResource["name"]]: TResource;
}, TRelations, TExecutors>;
addRelation<TCodec extends PgCodec, const TCodecRelationName extends string, const TRemoteResource extends PgResourceOptions<any, any, any, any>, const TCodecRelation extends Omit<PgCodecRelationConfig<TCodec, TRemoteResource>, "localCodec" | "remoteResourceOptions">>(codec: TCodec, relationName: TCodecRelationName, remoteResource: TRemoteResource, relation: TCodecRelation): PgRegistryBuilder<TCodecs, TResources, TRelations & {
[codecName in TCodec["name"]]: {
[relationName in TCodecRelationName]: TCodecRelation & {
localCodec: TCodec;
remoteResourceOptions: TRemoteResource;
};
};
}, TExecutors>;
build(): PgRegistry<Expand<TCodecs>, Expand<TResources>, Expand<TRelations>, Expand<TExecutors>>;
}
export declare function makeRegistry<TCodecs extends {
[name in string]: PgCodec<name, PgCodecAttributes | undefined, any, any, any, any, any>;
}, TResourceOptions extends {
[name in string]: PgResourceOptions<name, PgCodec, ReadonlyArray<PgResourceUnique<PgCodecAttributes<any>>>, readonly PgResourceParameter[] | undefined>;
}, TRelations extends {
[codecName in keyof TCodecs]?: {
[relationName in string]: PgCodecRelationConfig<PgCodec<string, PgCodecAttributes, any, any, undefined, any, undefined>, PgResourceOptions<any, PgCodecWithAttributes, any, any>>;
};
}, TExecutors extends {
[name in string]: PgExecutor;
}>(config: PgRegistryConfig<TCodecs, TResourceOptions, TRelations, TExecutors>): PgRegistry<TCodecs, TResourceOptions, TRelations, TExecutors>;
export declare function makeRegistryBuilder(): PgRegistryBuilder<{}, {}, {}, {}>;
export declare function makePgResourceOptions<const TResourceOptions extends PgResourceOptions<any, any, any, any>>(options: TResourceOptions): TResourceOptions;
//# sourceMappingURL=datasource.d.ts.map