fauna
Version:
A driver to query Fauna databases in browsers, Node.js, and other Javascript runtimes
392 lines (391 loc) • 13.6 kB
TypeScript
import { QueryArgumentObject } from "./query-builder";
import { DateStub, Document, DocumentReference, EmbeddedSet, Module, NamedDocument, NamedDocumentReference, NullDocument, Page, StreamToken, TimeStub } from "./values";
/**
* A request to make to Fauna.
*/
export interface QueryRequest<T extends string | QueryInterpolation = string | QueryInterpolation> {
/** The query */
query: T;
/** Optional arguments. Variables in the query will be initialized to the
* value associated with an argument key.
*/
arguments?: EncodedObject;
}
/**
* Options for queries. Each query can be made with different options. Settings here
* take precedence over those in {@link ClientConfiguration}.
*/
export interface QueryOptions {
/** Optional arguments. Variables in the query will be initialized to the
* value associated with an argument key.
*/
arguments?: QueryArgumentObject;
/**
* Determines the encoded format expected for the query `arguments` field, and
* the `data` field of a successful response.
* Overrides the optional setting on the {@link ClientConfiguration}.
*/
format?: ValueFormat;
/**
* If true, unconditionally run the query as strictly serialized.
* This affects read-only transactions. Transactions which write
* will always be strictly serialized.
* Overrides the optional setting on the {@link ClientConfiguration}.
*/
linearized?: boolean;
/**
* Controls what Javascript type to deserialize {@link https://docs.fauna.com/fauna/current/reference/fql_reference/types#long | Fauna longs} to.
* Use 'number' to deserialize longs to number. Use 'bigint' to deserialize to bigint. Defaults to 'number'.
* Note, for extremely large maginitude numbers Javascript's number will lose precision; as Javascript's
* 'number' can only support +/- 2^53-1 whereas Fauna's long is 64 bit. If this is detected, a warning will
* be logged to the console and precision loss will occur.
* If your application uses extremely large magnitude numbers use 'bigint'.
*/
long_type?: "number" | "bigint";
/**
* The max number of times to retry the query if contention is encountered.
*Overrides the optional setting on the {@link ClientConfiguration}.
*/
max_contention_retries?: number;
/**
* Tags provided back via logging and telemetry.
* Overrides the optional setting on the {@link ClientConfiguration}.
*/
query_tags?: Record<string, string>;
/**
* The timeout to use in this query in milliseconds.
* Overrides the optional setting on the {@link ClientConfiguration}.
*/
query_timeout_ms?: number;
/**
* A traceparent provided back via logging and telemetry.
* Must match format: https://www.w3.org/TR/trace-context/#traceparent-header
* Overrides the optional setting on the {@link ClientConfiguration}.
*/
traceparent?: string;
/**
* Enable or disable typechecking of the query before evaluation. If no value
* is provided, the value of `typechecked` in the database configuration will
* be used.
* Overrides the optional setting on the {@link ClientConfiguration}.
*/
typecheck?: boolean;
/**
* Enable or disable performance hints. Defaults to disabled.
* The QueryInfo object includes performance hints in the `summary` field, which is a
* top-level field in the response object.
* Overrides the optional setting on the {@link ClientConfiguration}.
*/
performance_hints?: boolean;
/**
* Secret to use instead of the client's secret.
*/
secret?: string;
}
/**
* tagged declares that type information is transmitted and received by the driver.
* "simple" indicates it is not - pure JSON is used.
* "decorated" will cause the service output to be shown in FQL syntax that could
* hypothetically be used to query Fauna. This is intended to support CLI and
* REPL like tools.
* @example
* ```typescript
* // example of decorated output
* { time: Time("2012-01-01T00:00:00Z") }
* ```
*/
export declare type ValueFormat = "simple" | "tagged" | "decorated";
export type QueryStats = {
/** The amount of Transactional Compute Ops consumed by the query. */
compute_ops: number;
/** The amount of Transactional Read Ops consumed by the query. */
read_ops: number;
/** The amount of Transactional Write Ops consumed by the query. */
write_ops: number;
/** The query run time in milliseconds. */
query_time_ms: number;
/** The amount of data read from storage, in bytes. */
storage_bytes_read: number;
/** The amount of data written to storage, in bytes. */
storage_bytes_write: number;
/** The number of times the transaction was retried due to write contention. */
contention_retries: number;
/** The number query attempts made due to retryable errors. */
attempts: number;
/**
* A list of rate limits hit.
* Included with QueryFailure responses when the query is rate limited.
*/
rate_limits_hit?: ("read" | "write" | "compute")[];
};
export type QueryInfo = {
/** The last transaction timestamp of the query. A Unix epoch in microseconds. */
txn_ts?: number;
/** The schema version that was used for the query execution. */
schema_version?: number;
/** A readable summary of any warnings or logs emitted by the query. */
summary?: string;
/** The value of the x-query-tags header, if it was provided. */
query_tags?: Record<string, string>;
/** Stats on query performance and cost */
stats?: QueryStats;
};
/**
* A decoded response from a successful query to Fauna
*/
export type QuerySuccess<T extends QueryValue> = QueryInfo & {
/**
* The result of the query. The data is any valid JSON value.
* @remarks
* data is type parameterized so that you can treat it as a
* certain type if you are using typescript.
*/
data: T;
/** The query's inferred static result type. */
static_type?: string;
};
/**
* A decoded response from a failed query to Fauna. Integrations which only want to report a human
* readable version of the failure can simply print out the "summary" field.
*/
export type QueryFailure = QueryInfo & {
/**
* The result of the query resulting in
*/
error: {
/** A predefined code which indicates the type of error. See XXX for a list of error codes. */
code: string;
/** A short, human readable description of the error */
message: string;
/**
* A machine readable description of any constraint failures encountered by the query.
* Present only if this query encountered constraint failures.
*/
constraint_failures?: Array<ConstraintFailure>;
/**
* The user provided value passed to the originating `abort()` call.
* Present only when the query encountered an `abort()` call, which is
* denoted by the error code `"abort"`
*/
abort?: QueryValue;
};
};
/**
* A constraint failure triggered by a query.
*/
export type ConstraintFailure = {
/** Description of the constraint failure */
message: string;
/** Name of the failed constraint */
name?: string;
/** Path into the write input data to which the failure applies */
paths?: Array<Array<number | string>>;
};
export type QueryResponse<T extends QueryValue> = QuerySuccess<T> | QueryFailure;
export declare const isQuerySuccess: (res: any) => res is QuerySuccess<any>;
export declare const isQueryFailure: (res: any) => res is QueryFailure;
export declare const isQueryResponse: (res: any) => res is QueryResponse<any>;
/**
* A piece of an interpolated query. Interpolated queries can be safely composed
* together without concern of query string injection.
* @see {@link ValueFragment} and {@link FQLFragment} for additional
* information
*/
export type QueryInterpolation = FQLFragment | ValueFragment | ObjectFragment | ArrayFragment;
/**
* A piece of an interpolated query that represents an actual value. Arguments
* are passed to fauna using ValueFragments so that query string injection is
* not possible.
* @remarks A ValueFragment is created by this driver when a literal value or
* object is provided as an argument to the {@link fql} tagged template
* function.
*
* ValueFragments must always be encoded with tags, regardless of the "x-format"
* request header sent.
* @example
* ```typescript
* const num = 17;
* const query = fql`${num} + 3)`;
* // produces
* { "fql": [{ "value": { "@int": "17" } }, " + 3"] }
* ```
*/
export type ValueFragment = {
value: TaggedType;
};
/**
* A piece of an interpolated query that represents an object. Arguments
* are passed to fauna using ObjectFragments so that query arguments can be
* nested within javascript objects.
*
* ObjectFragments must always be encoded with tags, regardless of the
* "x-format" request header sent.
* @example
* ```typescript
* const arg = { startDate: DateStub.from("2023-09-01") };
* const query = fql`${arg})`;
* // produces
* {
* "fql": [
* {
* "object": {
* "startDate": {
* "value": { "@date": "2023-09-01" } // Object field values have type QueryInterpolation
* }
* }
* }
* ]
* }
* ```
*/
export type ObjectFragment = {
object: EncodedObject;
};
/**
* A piece of an interpolated query that represents an array. Arguments
* are passed to fauna using ArrayFragments so that query arguments can be
* nested within javascript arrays.
*
* ArrayFragments must always be encoded with tags, regardless of the "x-format"
* request header sent.
* @example
* ```typescript
* const arg = [1, 2];
* const query = fql`${arg})`;
* // produces
* {
* "fql": [
* {
* "array": [
* { "value": { "@int": "1" } }, // Array items have type QueryInterpolation
* { "value": { "@int": "2" } }
* ]
* }
* ]
* }
* ```
*/
export type ArrayFragment = {
array: TaggedType[];
};
/**
* A piece of an interpolated query. Interpolated Queries can be safely composed
* together without concern of query string injection.
* @remarks A FQLFragment is created when calling the {@link fql} tagged
* template function and can be passed as an argument to other Querys.
* @example
* ```typescript
* const num = 17;
* const query1 = fql`${num} + 3)`;
* const query2 = fql`5 + ${query1})`;
* // produces
* { "fql": ["5 + ", { "fql": [{ "value": { "@int": "17" } }, " + 3"] }] }
* ```
*/
export type FQLFragment = {
fql: (string | QueryInterpolation)[];
};
/**
* A source span indicating a segment of FQL.
*/
export interface Span {
/**
* A string identifier of the FQL source. For example, if performing
* a raw query against the API this would be *query*.
*/
src: string;
/**
* The span's starting index within the src, inclusive.
*/
start: number;
/**
* The span's ending index within the src, inclusive.
*/
end: number;
/**
* The name of the enclosing function, if applicable.
*/
function: string;
}
/**
* A QueryValueObject is a plain javascript object where each value is a valid
* QueryValue.
* These objects can be returned in {@link QuerySuccess}.
*/
export interface QueryValueObject {
[key: string]: QueryValue;
}
/**
* A QueryValue represents the possible return values in a {@link QuerySuccess}.
*/
export type QueryValue = null | string | number | bigint | boolean | QueryValueObject | Array<QueryValue> | Uint8Array | DateStub | TimeStub | Module | Document | DocumentReference | NamedDocument | NamedDocumentReference | NullDocument | Page<QueryValue> | EmbeddedSet | StreamToken;
export type StreamRequest = {
token: string;
start_ts?: number;
cursor?: string;
};
export type StreamEventType = "status" | "add" | "remove" | "update" | "error";
export type StreamEventStatus = {
type: "status";
txn_ts: number;
cursor: string;
stats: QueryStats;
};
export type StreamEventData<T extends QueryValue> = {
type: "add" | "remove" | "update";
txn_ts: number;
cursor: string;
stats: QueryStats;
data: T;
};
export type StreamEventError = {
type: "error";
} & QueryFailure;
export type StreamEvent<T extends QueryValue> = StreamEventStatus | StreamEventData<T> | StreamEventError;
export type FeedRequest = StreamRequest & {
page_size?: number;
};
export type FeedSuccess<T extends QueryValue> = {
events: (StreamEventData<T> | StreamEventError)[];
cursor: string;
has_next: boolean;
stats?: QueryStats;
};
export type FeedError = QueryFailure;
export type TaggedBytes = {
"@bytes": string;
};
export type TaggedDate = {
"@date": string;
};
export type TaggedDouble = {
"@double": string;
};
export type TaggedInt = {
"@int": string;
};
export type TaggedLong = {
"@long": string;
};
export type TaggedMod = {
"@mod": string;
};
export type TaggedObject = {
"@object": QueryValueObject;
};
export type TaggedRef = {
"@ref": {
id: string;
coll: TaggedMod;
} | {
name: string;
coll: TaggedMod;
};
};
export type TaggedTime = {
"@time": string;
};
export type EncodedObject = {
[key: string]: TaggedType;
};
export type TaggedType = string | boolean | null | EncodedObject | TaggedBytes | TaggedDate | TaggedDouble | TaggedInt | TaggedLong | TaggedMod | TaggedObject | TaggedRef | TaggedTime | TaggedType[];