import { ArangoCollection } from "./collection"; import { Graph } from "./graph"; import { View } from "./view"; declare const type: unique symbol; /** * Generic AQL query object consisting of an AQL query string and its bind * parameters. */ export interface AqlQuery { [type]?: T | any; /** * An AQL query string. */ query: string; /** * An object mapping AQL bind parameter names to their respective values. * * Names of parameters representing collections are prefixed with an * at-symbol. */ bindVars: Record; } /** * Derived type representing AQL query objects generated by the AQL helper * functions and the AQL template string handler. These objects can be fed * back into these helper functions to be inlined or merged in complex queries. * * @internal */ export interface GeneratedAqlQuery extends AqlQuery { /** * @internal */ _source: () => { strings: string[]; args: AqlValue[]; }; } /** * An object representing a trusted AQL literal that will be inlined directly * when used in an AQL template or passed to AQL helper functions. * * Arbitrary values can be converted to trusted AQL literals by passing them * to the {@link literal} helper function. */ export interface AqlLiteral { /** * @internal * * Returns a string representation of this AQL literal that can be inlined * in an AQL template. */ toAQL: () => string; } /** * A value that can be used in an AQL template string or passed to an AQL * helper function. */ export type AqlValue = ArangoCollection | View | Graph | GeneratedAqlQuery | AqlLiteral | string | number | boolean | null | undefined | Record | any[]; /** * Indicates whether the given value is an {@link AqlQuery}. * * @param query - A value that might be an `AqlQuery`. */ export declare function isAqlQuery(query: any): query is AqlQuery; /** * Indicates whether the given value is a {@link GeneratedAqlQuery}. * * @param query - A value that might be a `GeneratedAqlQuery`. * * @internal */ export declare function isGeneratedAqlQuery(query: any): query is GeneratedAqlQuery; /** * Indicates whether the given value is an {@link AqlLiteral}. * * @param literal - A value that might be an `AqlLiteral`. */ export declare function isAqlLiteral(literal: any): literal is AqlLiteral; /** * Template string handler (template tag) for AQL queries. * * The `aql` tag can be used to write complex AQL queries as multi-line strings * without having to worry about `bindVars` and the distinction between * collections and regular parameters. * * Tagged template strings will return an {@link AqlQuery} object with * `query` and `bindVars` attributes reflecting any interpolated values. * * Any {@link collection.ArangoCollection} instance used in a query string will * be recognized as a collection reference and generate an AQL collection bind * parameter instead of a regular AQL value bind parameter. * * **Note**: you should always use the `aql` template tag when writing * dynamic AQL queries instead of using untagged (normal) template strings. * Untagged template strings will inline any interpolated values and return * a plain string as result. The `aql` template tag will only inline references * to the interpolated values and produce an AQL query object containing both * the query and the values. This prevents most injection attacks when using * untrusted values in dynamic queries. * * @example * ```js * // Some user-supplied string that may be malicious * const untrustedValue = req.body.email; * * // Without aql tag: BAD! DO NOT DO THIS! * const badQuery = ` * FOR user IN users * FILTER user.email == "${untrustedValue}" * RETURN user * `; * // e.g. if untrustedValue is '" || user.admin == true || "': * // Query: * // FOR user IN users * // FILTER user.email == "" || user.admin == true || "" * // RETURN user * * // With the aql tag: GOOD! MUCH SAFER! * const betterQuery = aql` * FOR user IN users * FILTER user.email == ${untrustedValue} * RETURN user * `; * // Query: * // FOR user IN users * // FILTER user.email == @value0 * // RETURN user * // Bind parameters: * // value0 -> untrustedValue * ``` * * @example * ```js * const collection = db.collection("some-collection"); * const minValue = 23; * const result = await db.query(aql` * FOR d IN ${collection} * FILTER d.num > ${minValue} * RETURN d * `); * * // Equivalent raw query object * const result2 = await db.query({ * query: ` * FOR d IN @@collection * FILTER d.num > @minValue * RETURN d * `, * bindVars: { * "@collection": collection.name, * minValue: minValue * } * }); * ``` * * @example * ```js * const collection = db.collection("some-collection"); * const color = "green"; * const filter = aql`FILTER d.color == ${color}'`; * const result = await db.query(aql` * FOR d IN ${collection} * ${filter} * RETURN d * `); * ``` */ export declare function aql(templateStrings: TemplateStringsArray, ...args: AqlValue[]): GeneratedAqlQuery; /** * Marks an arbitrary scalar value (i.e. a string, number or boolean) as * safe for being inlined directly into AQL queries when used in an `aql` * template string, rather than being converted into a bind parameter. * * **Note**: Nesting `aql` template strings is a much safer alternative for * most use cases. This low-level helper function only exists to help with * rare edge cases where a trusted AQL query fragment must be read from a * string (e.g. when reading query fragments from JSON) and should only be * used as a last resort. * * @example * ```js * // BAD! DO NOT DO THIS! * const sortDirection = literal('ASC'); * * // GOOD! DO THIS INSTEAD! * const sortDirection = aql`ASC`; * ``` * * @example * ```js * // BAD! DO NOT DO THIS! * const filterColor = literal('FILTER d.color == "green"'); * const result = await db.query(aql` * FOR d IN some-collection * ${filterColor} * RETURN d * `); * * // GOOD! DO THIS INSTEAD! * const color = "green"; * const filterColor = aql`FILTER d.color === ${color}`; * const result = await db.query(aql` * FOR d IN some-collection * ${filterColor} * RETURN d * `); * ``` * * @example * ```js * // WARNING: We explicitly trust the environment variable to be safe! * const filter = literal(process.env.FILTER_STATEMENT); * const users = await db.query(aql` * FOR user IN users * ${filter} * RETURN user * `); * ``` */ export declare function literal(value: string | number | boolean | AqlLiteral | null | undefined): AqlLiteral; /** * Constructs {@link AqlQuery} objects from an array of arbitrary values. * * **Note**: Nesting `aql` template strings is a much safer alternative * for most use cases. This low-level helper function only exists to * complement the `aql` tag when constructing complex queries from dynamic * arrays of query fragments. * * @param values - Array of values to join. These values will behave exactly * like values interpolated in an `aql` template string. * @param sep - Seperator to insert between values. This value will behave * exactly like a value passed to {@link literal}, i.e. it will be * inlined as-is, rather than being converted into a bind parameter. * * @example * ```js * const users = db.collection("users"); * const filters = []; * if (adminsOnly) filters.push(aql`FILTER user.admin`); * if (activeOnly) filters.push(aql`FILTER user.active`); * const result = await db.query(aql` * FOR user IN ${users} * ${join(filters)} * RETURN user * `); * ``` * * @example * ```js * const users = db.collection("users"); * const keys = ["jreyes", "ghermann"]; * * // BAD! NEEDLESSLY COMPLEX! * const docs = keys.map(key => aql`DOCUMENT(${users}, ${key}`)); * const result = await db.query(aql` * FOR user IN [ * ${join(docs, ", ")} * ] * RETURN user * `); * // Query: * // FOR user IN [ * // DOCUMENT(@@value0, @value1), DOCUMENT(@@value0, @value2) * // ] * // RETURN user * // Bind parameters: * // @value0 -> "users" * // value1 -> "jreyes" * // value2 -> "ghermann" * * // GOOD! MUCH SIMPLER! * const result = await db.query(aql` * FOR key IN ${keys} * LET user = DOCUMENT(${users}, key) * RETURN user * `); * // Query: * // FOR user IN @value0 * // LET user = DOCUMENT(@@value1, key) * // RETURN user * // Bind parameters: * // value0 -> ["jreyes", "ghermann"] * // @value1 -> "users" * ``` */ export declare function join(values: AqlValue[], sep?: string): GeneratedAqlQuery; export {}; //# sourceMappingURL=aql.d.ts.map