1 | # ArangoDB JavaScript Driver
|
2 |
|
3 | The official ArangoDB JavaScript client for Node.js and the browser.
|
4 |
|
5 | [![license - APACHE-2.0](https://img.shields.io/npm/l/arangojs.svg)](http://opensource.org/licenses/APACHE-2.0)
|
6 | [![Tests](https://github.com/arangodb/arangojs/workflows/Tests/badge.svg)](https://github.com/arangodb/arangojs/actions?query=workflow:Tests)
|
7 |
|
8 | [![npm package status](https://nodei.co/npm/arangojs.png?downloads=true&stars=true)](https://npmjs.org/package/arangojs)
|
9 |
|
10 | ## Links
|
11 |
|
12 | - [API Documentation](https://arangodb.github.io/arangojs/latest/modules/index.html)
|
13 |
|
14 | - [Changelog](https://arangodb.github.io/arangojs/CHANGELOG)
|
15 |
|
16 | - [Migration Guide](http://arangodb.github.io/arangojs/MIGRATING)
|
17 |
|
18 | ## Install
|
19 |
|
20 | ### With npm or yarn
|
21 |
|
22 | ```sh
|
23 | npm install --save arangojs
|
24 | ## - or -
|
25 | yarn add arangojs
|
26 | ```
|
27 |
|
28 | ### For browsers
|
29 |
|
30 | When using modern JavaScript tooling with a bundler and compiler (e.g. Babel),
|
31 | arangojs can be installed using `npm` or `yarn` like any other dependency.
|
32 |
|
33 | You can also use [jsDelivr CDN](https://www.jsdelivr.com) during development:
|
34 |
|
35 | ```html
|
36 | <script type="importmap">
|
37 | {
|
38 | "imports": {
|
39 | "arangojs": "https://cdn.jsdelivr.net/npm/arangojs@9.0.0-preview.1/esm/index.js?+esm"
|
40 | }
|
41 | }
|
42 | </script>
|
43 | <script type="module">
|
44 | import { Database } from "arangojs";
|
45 | const db = new Database();
|
46 | // ...
|
47 | </script>
|
48 | ```
|
49 |
|
50 | ## Basic usage example
|
51 |
|
52 | Modern JavaScript/TypeScript with async/await and ES Modules:
|
53 |
|
54 | ```js
|
55 | import { Database, aql } from "arangojs";
|
56 |
|
57 | const db = new Database();
|
58 | const Pokemons = db.collection("my-pokemons");
|
59 |
|
60 | async function main() {
|
61 | try {
|
62 | const pokemons = await db.query(aql`
|
63 | FOR pokemon IN ${Pokemons}
|
64 | FILTER pokemon.type == "fire"
|
65 | RETURN pokemon
|
66 | `);
|
67 | console.log("My pokemans, let me show you them:");
|
68 | for await (const pokemon of pokemons) {
|
69 | console.log(pokemon.name);
|
70 | }
|
71 | } catch (err) {
|
72 | console.error(err.message);
|
73 | }
|
74 | }
|
75 |
|
76 | main();
|
77 | ```
|
78 |
|
79 | Using a different database:
|
80 |
|
81 | ```js
|
82 | const db = new Database({
|
83 | url: "http://127.0.0.1:8529",
|
84 | databaseName: "pancakes",
|
85 | auth: { username: "root", password: "hunter2" },
|
86 | });
|
87 |
|
88 | // The credentials can be swapped at any time
|
89 | db.useBasicAuth("admin", "maplesyrup");
|
90 | ```
|
91 |
|
92 | Old-school JavaScript with promises and CommonJS:
|
93 |
|
94 | ```js
|
95 | var arangojs = require("arangojs");
|
96 | var Database = arangojs.Database;
|
97 |
|
98 | var db = new Database();
|
99 | var pokemons = db.collection("pokemons");
|
100 |
|
101 | db.query({
|
102 | query: "FOR p IN @@c FILTER p.type == 'fire' RETURN p",
|
103 | bindVars: { "@c": "pokemons" },
|
104 | })
|
105 | .then(function (cursor) {
|
106 | console.log("My pokemons, let me show you them:");
|
107 | return cursor.forEach(function (pokemon) {
|
108 | console.log(pokemon.name);
|
109 | });
|
110 | })
|
111 | .catch(function (err) {
|
112 | console.error(err.message);
|
113 | });
|
114 | ```
|
115 |
|
116 | **Note**: The examples throughout this documentation use `async`/`await`
|
117 | and other modern language features like multi-line strings and template tags.
|
118 | When developing for an environment without support for these language features,
|
119 | substitute promises for `await` syntax as in the above example.
|
120 |
|
121 | ## Compatibility
|
122 |
|
123 | The arangojs driver is compatible with the latest stable version of ArangoDB
|
124 | available at the time of the driver release and remains compatible with the
|
125 | two most recent Node.js LTS versions in accordance with the official
|
126 | [Node.js long-term support schedule](https://github.com/nodejs/LTS). Versions
|
127 | of ArangoDB that have reached their [end of life](https://arangodb.com/subscriptions/end-of-life-notice/)
|
128 | by the time of a driver release are explicitly not supported.
|
129 |
|
130 | For a list of changes between recent versions of the driver, see the
|
131 | [CHANGELOG](https://arangodb.github.io/arangojs/CHANGELOG).
|
132 |
|
133 | **Note:** arangojs is only intended to be used in Node.js or a browser to access
|
134 | ArangoDB **from outside the database**. If you are looking for the ArangoDB
|
135 | JavaScript API for [Foxx](https://foxx.arangodb.com) or for accessing ArangoDB
|
136 | from within the `arangosh` interactive shell, please refer to the documentation
|
137 | of the [`@arangodb` module](https://www.arangodb.com/docs/stable/foxx-reference-modules.html#the-arangodb-module)
|
138 | and [the `db` object](https://www.arangodb.com/docs/stable/appendix-references-dbobject.html) instead.
|
139 |
|
140 | ## Error responses
|
141 |
|
142 | If arangojs encounters an API error, it will throw an `ArangoError` with
|
143 | an `errorNum` property indicating the ArangoDB error code and the `code`
|
144 | property indicating the HTTP status code from the response body.
|
145 |
|
146 | For any other non-ArangoDB error responses (4xx/5xx status code), it will throw
|
147 | an `HttpError` error with the status code indicated by the `code` property.
|
148 |
|
149 | If the server response did not indicate an error but the response body could
|
150 | not be parsed, a regular `SyntaxError` may be thrown instead.
|
151 |
|
152 | In all of these cases the server response object will be exposed as the
|
153 | `response` property on the error object.
|
154 |
|
155 | If the request failed at a network level or the connection was closed without
|
156 | receiving a response, the underlying system error will be thrown instead.
|
157 |
|
158 | ## Common issues
|
159 |
|
160 | ### Missing functions or unexpected server errors
|
161 |
|
162 | Please make sure you are using the latest version of this driver and that the
|
163 | version of the arangojs documentation you are reading matches that version.
|
164 |
|
165 | Changes in the major version number of arangojs (e.g. 7.x.y -> 8.0.0) indicate
|
166 | backwards-incompatible changes in the arangojs API that may require changes in
|
167 | your code when upgrading your version of arangojs.
|
168 |
|
169 | Additionally please ensure that your version of Node.js (or browser) and
|
170 | ArangoDB are supported by the version of arangojs you are trying to use. See
|
171 | the [compatibility section](#compatibility) for additional information.
|
172 |
|
173 | **Note**: As of June 2018 ArangoDB 2.8 has reached its End of Life and is no
|
174 | longer supported in arangojs 7 and later. If your code needs to work with
|
175 | ArangoDB 2.8 you can continue using arangojs 6 and enable ArangoDB 2.8
|
176 | compatibility mode by setting the config option `arangoVersion: 20800` to
|
177 | enable the ArangoDB 2.8 compatibility mode in arangojs 6.
|
178 |
|
179 | You can install an older version of arangojs using `npm` or `yarn`:
|
180 |
|
181 | ```sh
|
182 | # for version 6.x.x
|
183 | yarn add arangojs@6
|
184 | # - or -
|
185 | npm install --save arangojs@6
|
186 | ```
|
187 |
|
188 | ### No code intelligence when using require instead of import
|
189 |
|
190 | If you are using `require` to import the `arangojs` module in JavaScript, the
|
191 | default export might not be recognized as a function by the code intelligence
|
192 | of common editors like Visual Studio Code, breaking auto-complete and other
|
193 | useful features.
|
194 |
|
195 | As a workaround, use the `arangojs` function exported by that module instead
|
196 | of calling the module itself:
|
197 |
|
198 | ```diff
|
199 | const arangojs = require("arangojs");
|
200 |
|
201 | - const db = arangojs({
|
202 | + const db = arangojs.arangojs({
|
203 | url: ARANGODB_SERVER,
|
204 | });
|
205 | ```
|
206 |
|
207 | Alternatively you can use the `Database` class directly:
|
208 |
|
209 | ```diff
|
210 | const arangojs = require("arangojs");
|
211 | + const Database = arangojs.Database;
|
212 |
|
213 | - const db = arangojs({
|
214 | + const db = new Database({
|
215 | url: ARANGODB_SERVER,
|
216 | });
|
217 | ```
|
218 |
|
219 | Or using object destructuring:
|
220 |
|
221 | ```diff
|
222 | - const arangojs = require("arangojs");
|
223 | + const { Database } = require("arangojs");
|
224 |
|
225 | - const db = arangojs({
|
226 | + const db = new Database({
|
227 | url: ARANGODB_SERVER,
|
228 | });
|
229 | ```
|
230 |
|
231 | ### Error stack traces contain no useful information
|
232 |
|
233 | Due to the async, queue-based behavior of arangojs, the stack traces generated
|
234 | when an error occur rarely provide enough information to determine the location
|
235 | in your own code where the request was initiated.
|
236 |
|
237 | Using the `precaptureStackTraces` configuration option, arangojs will attempt
|
238 | to always generate stack traces proactively when a request is performed,
|
239 | allowing arangojs to provide more meaningful stack traces at the cost of an
|
240 | impact to performance even when no error occurs.
|
241 |
|
242 | ```diff
|
243 | const { Database } = require("arangojs");
|
244 |
|
245 | const db = new Database({
|
246 | url: ARANGODB_SERVER,
|
247 | + precaptureStackTraces: true,
|
248 | });
|
249 | ```
|
250 |
|
251 | Note that arangojs will attempt to use `Error.captureStackTrace` if available
|
252 | and fall back to generating a stack trace by throwing an error. In environments
|
253 | that do not support the `stack` property on error objects, this option will
|
254 | still impact performance but not result in any additional information becoming
|
255 | available.
|
256 |
|
257 | ### Node.js `ReferenceError: window is not defined`
|
258 |
|
259 | If you compile your Node project using a build tool like Webpack, you may need
|
260 | to tell it to
|
261 | [target the correct environment](https://webpack.js.org/configuration/target/):
|
262 |
|
263 | ```diff
|
264 | // webpack.config.js
|
265 | + "target": "node",
|
266 | ```
|
267 |
|
268 | To support use in both browser and Node environments arangojs uses the
|
269 | [`package.json` `browser` field](https://github.com/defunctzombie/package-browser-field-spec),
|
270 | to substitute browser-specific implementations for certain modules.
|
271 | Build tools like Webpack will respect this field when targetting a browser
|
272 | environment and may need to be explicitly told you are targetting Node instead.
|
273 |
|
274 | ### Node.js with self-signed HTTPS certificates
|
275 |
|
276 | If you need to support self-signed HTTPS certificates in Node.js, you may have
|
277 | to override the global fetch agent. At the time of this writing, there is no
|
278 | official way to do this for the native `fetch` implementation in Node.js.
|
279 |
|
280 | However as Node.js uses the `undici` module for its `fetch` implementation
|
281 | internally, you can override the global agent by adding `undici` as a
|
282 | dependency to your project and using its `setGlobalDispatcher` as follows:
|
283 |
|
284 | ```js
|
285 | import { Agent, setGlobalDispatcher } from "undici";
|
286 |
|
287 | setGlobalDispatcher(
|
288 | new Agent({
|
289 | ca: [
|
290 | fs.readFileSync(".ssl/sub.class1.server.ca.pem"),
|
291 | fs.readFileSync(".ssl/ca.pem"),
|
292 | ],
|
293 | })
|
294 | );
|
295 | ```
|
296 |
|
297 | Although this is **strongly discouraged**, it's also possible to disable
|
298 | HTTPS certificate validation entirely, but note this has
|
299 | **extremely dangerous** security implications:
|
300 |
|
301 | ```js
|
302 | import { Agent, setGlobalDispatcher } from "undici";
|
303 |
|
304 | setGlobalDispatcher(
|
305 | new Agent({
|
306 | rejectUnauthorized: false,
|
307 | })
|
308 | );
|
309 | ```
|
310 |
|
311 | When using arangojs in the browser, self-signed HTTPS certificates need to
|
312 | be trusted by the browser or use a trusted root certificate.
|
313 |
|
314 | ### Streaming transactions leak
|
315 |
|
316 | When using the `transaction.step` method it is important to be aware of the
|
317 | limitations of what a callback passed to this method is allowed to do.
|
318 |
|
319 | ```js
|
320 | const collection = db.collection(collectionName);
|
321 | const trx = db.transaction(transactionId);
|
322 |
|
323 | // WARNING: This code will not work as intended!
|
324 | await trx.step(async () => {
|
325 | await collection.save(doc1);
|
326 | await collection.save(doc2); // Not part of the transaction!
|
327 | });
|
328 |
|
329 | // INSTEAD: Always perform a single operation per step:
|
330 | await trx.step(() => collection.save(doc1));
|
331 | await trx.step(() => collection.save(doc2));
|
332 | ```
|
333 |
|
334 | Please refer to the documentation of this method for additional examples.
|
335 |
|
336 | ### Streaming transactions timeout in cluster
|
337 |
|
338 | Example messages: `transaction not found`, `transaction already expired`.
|
339 |
|
340 | Transactions have
|
341 | [different guarantees](https://www.arangodb.com/docs/stable/transactions-limitations.html#in-clusters)
|
342 | in a cluster.
|
343 |
|
344 | When using arangojs in a cluster with load balancing, you may need to adjust
|
345 | the value of `config.poolSize` to accommodate the number of transactions
|
346 | you need to be able to run in parallel. The default value is likely to be too
|
347 | low for most cluster scenarios involving frequent streaming transactions.
|
348 |
|
349 | **Note**: When using a high value for `config.poolSize` you may have
|
350 | to adjust the maximum number of threads in the ArangoDB configuration using
|
351 | [the `server.maximal-threads` option](https://www.arangodb.com/docs/3.7/programs-arangod-server.html#server-threads)
|
352 | to support larger numbers of concurrent transactions on the server side.
|
353 |
|
354 | ## License
|
355 |
|
356 | The Apache License, Version 2.0. For more information, see the accompanying
|
357 | LICENSE file.
|
358 |
|
359 | Includes code from [x3-linkedlist](https://github.com/x3cion/x3-linkedlist)
|
360 | used under the MIT license.
|