1 | import { ArangoCollection } from "./collection.js";
|
2 | import { Graph } from "./graph.js";
|
3 | import { View } from "./view.js";
|
4 | declare const type: unique symbol;
|
5 | /**
|
6 | * Generic AQL query object consisting of an AQL query string and its bind
|
7 | * parameters.
|
8 | */
|
9 | export interface AqlQuery<T = any> {
|
10 | [type]?: T | any;
|
11 | /**
|
12 | * An AQL query string.
|
13 | */
|
14 | query: string;
|
15 | /**
|
16 | * An object mapping AQL bind parameter names to their respective values.
|
17 | *
|
18 | * Names of parameters representing collections are prefixed with an
|
19 | * at-symbol.
|
20 | */
|
21 | bindVars: Record<string, any>;
|
22 | }
|
23 | /**
|
24 | * Derived type representing AQL query objects generated by the AQL helper
|
25 | * functions and the AQL template string handler. These objects can be fed
|
26 | * back into these helper functions to be inlined or merged in complex queries.
|
27 | *
|
28 | * @internal
|
29 | */
|
30 | export interface GeneratedAqlQuery<T = any> extends AqlQuery<T> {
|
31 | /**
|
32 | * @internal
|
33 | */
|
34 | _source: () => {
|
35 | strings: string[];
|
36 | args: AqlValue[];
|
37 | };
|
38 | }
|
39 | /**
|
40 | * An object representing a trusted AQL literal that will be inlined directly
|
41 | * when used in an AQL template or passed to AQL helper functions.
|
42 | *
|
43 | * Arbitrary values can be converted to trusted AQL literals by passing them
|
44 | * to the {@link literal} helper function.
|
45 | */
|
46 | export interface AqlLiteral {
|
47 | /**
|
48 | * @internal
|
49 | *
|
50 | * Returns a string representation of this AQL literal that can be inlined
|
51 | * in an AQL template.
|
52 | */
|
53 | toAQL: () => string;
|
54 | }
|
55 | /**
|
56 | * A value that can be used in an AQL template string or passed to an AQL
|
57 | * helper function.
|
58 | */
|
59 | export type AqlValue = ArangoCollection | View | Graph | GeneratedAqlQuery | AqlLiteral | string | number | boolean | null | undefined | Record<string, any> | any[];
|
60 | /**
|
61 | * Indicates whether the given value is an {@link AqlQuery}.
|
62 | *
|
63 | * @param query - A value that might be an `AqlQuery`.
|
64 | */
|
65 | export declare function isAqlQuery(query: any): query is AqlQuery;
|
66 | /**
|
67 | * Indicates whether the given value is a {@link GeneratedAqlQuery}.
|
68 | *
|
69 | * @param query - A value that might be a `GeneratedAqlQuery`.
|
70 | *
|
71 | * @internal
|
72 | */
|
73 | export declare function isGeneratedAqlQuery(query: any): query is GeneratedAqlQuery;
|
74 | /**
|
75 | * Indicates whether the given value is an {@link AqlLiteral}.
|
76 | *
|
77 | * @param literal - A value that might be an `AqlLiteral`.
|
78 | */
|
79 | export declare function isAqlLiteral(literal: any): literal is AqlLiteral;
|
80 | /**
|
81 | * Template string handler (template tag) for AQL queries.
|
82 | *
|
83 | * The `aql` tag can be used to write complex AQL queries as multi-line strings
|
84 | * without having to worry about `bindVars` and the distinction between
|
85 | * collections and regular parameters.
|
86 | *
|
87 | * Tagged template strings will return an {@link AqlQuery} object with
|
88 | * `query` and `bindVars` attributes reflecting any interpolated values.
|
89 | *
|
90 | * Any {@link collection.ArangoCollection} instance used in a query string will
|
91 | * be recognized as a collection reference and generate an AQL collection bind
|
92 | * parameter instead of a regular AQL value bind parameter.
|
93 | *
|
94 | * **Note**: you should always use the `aql` template tag when writing
|
95 | * dynamic AQL queries instead of using untagged (normal) template strings.
|
96 | * Untagged template strings will inline any interpolated values and return
|
97 | * a plain string as result. The `aql` template tag will only inline references
|
98 | * to the interpolated values and produce an AQL query object containing both
|
99 | * the query and the values. This prevents most injection attacks when using
|
100 | * untrusted values in dynamic queries.
|
101 | *
|
102 | * @example
|
103 | * ```js
|
104 | * // Some user-supplied string that may be malicious
|
105 | * const untrustedValue = req.body.email;
|
106 | *
|
107 | * // Without aql tag: BAD! DO NOT DO THIS!
|
108 | * const badQuery = `
|
109 | * FOR user IN users
|
110 | * FILTER user.email == "${untrustedValue}"
|
111 | * RETURN user
|
112 | * `;
|
113 | * // e.g. if untrustedValue is '" || user.admin == true || "':
|
114 | * // Query:
|
115 | * // FOR user IN users
|
116 | * // FILTER user.email == "" || user.admin == true || ""
|
117 | * // RETURN user
|
118 | *
|
119 | * // With the aql tag: GOOD! MUCH SAFER!
|
120 | * const betterQuery = aql`
|
121 | * FOR user IN users
|
122 | * FILTER user.email == ${untrustedValue}
|
123 | * RETURN user
|
124 | * `;
|
125 | * // Query:
|
126 | * // FOR user IN users
|
127 | * // FILTER user.email == @value0
|
128 | * // RETURN user
|
129 | * // Bind parameters:
|
130 | * // value0 -> untrustedValue
|
131 | * ```
|
132 | *
|
133 | * @example
|
134 | * ```js
|
135 | * const collection = db.collection("some-collection");
|
136 | * const minValue = 23;
|
137 | * const result = await db.query(aql`
|
138 | * FOR d IN ${collection}
|
139 | * FILTER d.num > ${minValue}
|
140 | * RETURN d
|
141 | * `);
|
142 | *
|
143 | * // Equivalent raw query object
|
144 | * const result2 = await db.query({
|
145 | * query: `
|
146 | * FOR d IN @@collection
|
147 | * FILTER d.num > @minValue
|
148 | * RETURN d
|
149 | * `,
|
150 | * bindVars: {
|
151 | * "@collection": collection.name,
|
152 | * minValue: minValue
|
153 | * }
|
154 | * });
|
155 | * ```
|
156 | *
|
157 | * @example
|
158 | * ```js
|
159 | * const collection = db.collection("some-collection");
|
160 | * const color = "green";
|
161 | * const filter = aql`FILTER d.color == ${color}'`;
|
162 | * const result = await db.query(aql`
|
163 | * FOR d IN ${collection}
|
164 | * ${filter}
|
165 | * RETURN d
|
166 | * `);
|
167 | * ```
|
168 | */
|
169 | export declare function aql<T = any>(templateStrings: TemplateStringsArray, ...args: AqlValue[]): AqlQuery<T>;
|
170 | /**
|
171 | * Marks an arbitrary scalar value (i.e. a string, number or boolean) as
|
172 | * safe for being inlined directly into AQL queries when used in an `aql`
|
173 | * template string, rather than being converted into a bind parameter.
|
174 | *
|
175 | * **Note**: Nesting `aql` template strings is a much safer alternative for
|
176 | * most use cases. This low-level helper function only exists to help with
|
177 | * rare edge cases where a trusted AQL query fragment must be read from a
|
178 | * string (e.g. when reading query fragments from JSON) and should only be
|
179 | * used as a last resort.
|
180 | *
|
181 | * @example
|
182 | * ```js
|
183 | * // BAD! DO NOT DO THIS!
|
184 | * const sortDirection = literal('ASC');
|
185 | *
|
186 | * // GOOD! DO THIS INSTEAD!
|
187 | * const sortDirection = aql`ASC`;
|
188 | * ```
|
189 | *
|
190 | * @example
|
191 | * ```js
|
192 | * // BAD! DO NOT DO THIS!
|
193 | * const filterColor = literal('FILTER d.color == "green"');
|
194 | * const result = await db.query(aql`
|
195 | * FOR d IN some-collection
|
196 | * ${filterColor}
|
197 | * RETURN d
|
198 | * `);
|
199 | *
|
200 | * // GOOD! DO THIS INSTEAD!
|
201 | * const color = "green";
|
202 | * const filterColor = aql`FILTER d.color === ${color}`;
|
203 | * const result = await db.query(aql`
|
204 | * FOR d IN some-collection
|
205 | * ${filterColor}
|
206 | * RETURN d
|
207 | * `);
|
208 | * ```
|
209 | *
|
210 | * @example
|
211 | * ```js
|
212 | * // WARNING: We explicitly trust the environment variable to be safe!
|
213 | * const filter = literal(process.env.FILTER_STATEMENT);
|
214 | * const users = await db.query(aql`
|
215 | * FOR user IN users
|
216 | * ${filter}
|
217 | * RETURN user
|
218 | * `);
|
219 | * ```
|
220 | */
|
221 | export declare function literal(value: string | number | boolean | AqlLiteral | null | undefined): AqlLiteral;
|
222 | /**
|
223 | * Constructs {@link AqlQuery} objects from an array of arbitrary values.
|
224 | *
|
225 | * **Note**: Nesting `aql` template strings is a much safer alternative
|
226 | * for most use cases. This low-level helper function only exists to
|
227 | * complement the `aql` tag when constructing complex queries from dynamic
|
228 | * arrays of query fragments.
|
229 | *
|
230 | * @param values - Array of values to join. These values will behave exactly
|
231 | * like values interpolated in an `aql` template string.
|
232 | * @param sep - Seperator to insert between values. This value will behave
|
233 | * exactly like a value passed to {@link literal}, i.e. it will be
|
234 | * inlined as-is, rather than being converted into a bind parameter.
|
235 | *
|
236 | * @example
|
237 | * ```js
|
238 | * const users = db.collection("users");
|
239 | * const filters = [];
|
240 | * if (adminsOnly) filters.push(aql`FILTER user.admin`);
|
241 | * if (activeOnly) filters.push(aql`FILTER user.active`);
|
242 | * const result = await db.query(aql`
|
243 | * FOR user IN ${users}
|
244 | * ${join(filters)}
|
245 | * RETURN user
|
246 | * `);
|
247 | * ```
|
248 | *
|
249 | * @example
|
250 | * ```js
|
251 | * const users = db.collection("users");
|
252 | * const keys = ["jreyes", "ghermann"];
|
253 | *
|
254 | * // BAD! NEEDLESSLY COMPLEX!
|
255 | * const docs = keys.map(key => aql`DOCUMENT(${users}, ${key}`));
|
256 | * const result = await db.query(aql`
|
257 | * FOR user IN [
|
258 | * ${join(docs, ", ")}
|
259 | * ]
|
260 | * RETURN user
|
261 | * `);
|
262 | * // Query:
|
263 | * // FOR user IN [
|
264 | * // DOCUMENT(@@value0, @value1), DOCUMENT(@@value0, @value2)
|
265 | * // ]
|
266 | * // RETURN user
|
267 | * // Bind parameters:
|
268 | * // @value0 -> "users"
|
269 | * // value1 -> "jreyes"
|
270 | * // value2 -> "ghermann"
|
271 | *
|
272 | * // GOOD! MUCH SIMPLER!
|
273 | * const result = await db.query(aql`
|
274 | * FOR key IN ${keys}
|
275 | * LET user = DOCUMENT(${users}, key)
|
276 | * RETURN user
|
277 | * `);
|
278 | * // Query:
|
279 | * // FOR user IN @value0
|
280 | * // LET user = DOCUMENT(@@value1, key)
|
281 | * // RETURN user
|
282 | * // Bind parameters:
|
283 | * // value0 -> ["jreyes", "ghermann"]
|
284 | * // @value1 -> "users"
|
285 | * ```
|
286 | */
|
287 | export declare function join(values: AqlValue[], sep?: string): AqlQuery;
|
288 | export {};
|
289 | //# sourceMappingURL=aql.d.ts.map |
\ | No newline at end of file |