UNPKG

17.1 kBMarkdownView Raw
1# Migrating
2
3## v8 to v9
4
5Version 9 reverts the automatic NFC normalization introduced in v7.7.0. This
6means that arangojs will no longer automatically normalize unicode names and
7identifiers of collections, graphs, indexes, views, users, databases and so on.
8
9If you want to continue using NFC normalization, you can use the `normalize`
10method available on all JavaScript strings:
11
12```diff
13 import { Database } from "arangojs";
14
15 const db = new Database();
16-const collection = db.collection(myUnicodeName);
17+const collection = db.collection(myUnicodeName.normalize("NFC"));
18```
19
20Note that ArangoDB may reject non-normalized unicode names and identifiers.
21This change is intended to make it easier to recognize normalization issues in
22code interacting with ArangoDB that were previously masked by arangojs.
23
24### Simple queries
25
26Simple queries like the `removeByExample` and `firstExample` methods have been
27removed from the collections API. These methods were deprecated in ArangoDB 3.4
28and can be replaced with AQL queries. For examples for replicating each
29method's behavior in AQL, see the documentation for these methods in ArangoJS 8.
30
31### Request and Response changes
32
33Version 9 now uses native `fetch` in all environments. This means that the
34request and response objects exposed by ArangoJS now extend the fetch API's
35`Request` and `Response` objects rather than those from Node's `http` module
36and ArangoJS no longer provides the `agentOptions` or `agent` config options.
37
38#### Config changes
39
40The relevant `agentOptions` have been moved up into the `config` type and
41in most cases renamed:
42
43```diff
44 const db = new Database({
45 url: "http://localhost:8529",
46- agentOptions: {
47- maxSockets: 10,
48- keepAlive: true,
49- before: (req) => console.log(String(new Date()), 'requesting', req.url),
50- after: (res) => console.log(String(new Date()), 'received', res.request.url)
51- }
52+ poolSize: 10,
53+ keepalive: true,
54+ beforeRequest: (req) => console.log(String(new Date()), 'requesting', req.url),
55+ afterResponse: (res) => console.log(String(new Date()), 'received', res.request.url)
56 });
57```
58
59If you need to modify the request agent beyond what is possible using the fetch
60API, you can override Node's default `fetch` Agent using the `undici` module:
61
62```js
63const { Agent, setGlobalDispatcher } = require("undici");
64
65setGlobalDispatcher(
66 new Agent({
67 // your agent options here
68 })
69);
70```
71
72Note that you will have to add `undici` as a dependency to your project. There
73is currently no built-in way to override these options in Node.js without this
74module.
75
76#### Request and Response objects
77
78This change mostly affects code that uses the `db.route` API to perform
79arbitrary requests to the ArangoDB HTTP API.
80
81The fetch API `Request` and `Response` objects are a bit different from the
82equivalent objects previously exposed by these methods. Note that while this
83means response objects still provide a `body` property, its semantics are very
84different as the fetch API expects the `blob`, `json` and `text` methods to be
85used instead. ArangoJS will use the relevant method during response handling
86and store the result in the `parsedBody` method:
87
88```diff
89 const myFoxxApi = db.route('my/foxx');
90 const res = await myFoxxApi.get();
91- const token = res.headers['x-auth-token'];
92- if (res.statusCode === 200) console.log(res.body);
93+ const token = res.headers.get('x-auth-token');
94+ if (res.status === 200) console.log(res.parsedBody);
95```
96
97## v7 to v8
98
99Version 8 drops support for Internet Explorer 11 and Node.js 10 and 12. If you
100need to continue supporting Internet Explorer, you can try transpiling arangojs
101as a dependency using Babel with the relevant polyfills.
102
103### General
104
105In TypeScript the type `Dict<T>` has been removed from the `connection` module.
106The built-in type `Record<string, T>` can be used as a replacement:
107
108```diff
109 import { Database } from "arangojs";
110-import type { Dict } from "arangojs/connection";
111
112 const db = new Database();
113-let deps: Dict<string | string[] | undefined>;
114+let deps: Record<string, string | string[] | undefined>;
115 deps = await db.getServiceDependencies("/my-foxx-service", true);
116```
117
118### Default URL
119
120The default URL has been changed to `http://127.0.0.1:8529` to match the ArangoDB
121default. Previously the default URL was `http://localhost:8529`, which on some
122systems would resolve to the IPv6 address `::1` instead.
123
124If you don't want to use the IPv4 address `127.0.0.1` and instead want to continue
125letting the operating system resolve `localhost`, you can pass the URL explicitly:
126
127```diff
128 import { Database } from "arangojs";
129
130 const db = new Database({
131+ url: "http://localhost:8529"
132 });
133```
134
135### Databases
136
137Previously arangojs allowed changing the database using the deprecated
138`db.useDatabase` method. This could make it difficult to remember which
139database you were interacting with. Instead, you should create a new `Database`
140instance for each database you want to interact with using the `db.database`
141method:
142
143```diff
144 import { Database } from "arangojs";
145
146 const db = new Database();
147-db.useDatabase("database2");
148+const db2 = db.database("database2");
149```
150
151### Queries
152
153The functions `aql.literal` and `aql.join` are no longer available as methods
154on the `aql` template handler and need to be imported separately:
155
156```diff
157 import { aql } from "arangojs";
158+import { join } from "arangojs/aql";
159
160-const filters = aql.join([
161+const filters = join([
162 aql`FILTER size == 'big'`,
163 aql`FILTER color == 'yellow'`
164 ]);
165```
166
167### Users
168
169The return values of `db.getUserDatabases` and `db.getUserAccessLevel` have
170been changed to match the documented return types:
171
172```diff
173 import { Database } from "arangojs";
174
175 const db = new Database();
176-const dbs = (await db.getUserDatabases("ash")).result;
177+const dbs = await db.getUserDatabases("ash");
178for (const [db, obj] of Object.entries(dbs)) {
179 console.log(`${db}: ${obj.permission}`);
180 for (const [col, access] of Object.entries(obj.collections)) {
181 console.log(`${db}/${col}: ${access}`);
182 }
183}
184
185-const access = (await db.getUserAccessLevel("ash", "pokemons")).result;
186+const access = await db.getUserAccessLevel("ash", "pokemons");
187 if (access === "rw") {
188 db.collection("pokemons").save({ name: "Pikachu" });
189 }
190```
191
192### Graphs
193
194In TypeScript the type `GraphCreateOptions` has been renamed to
195`CreateGraphOptions`:
196
197```diff
198-import type { GraphCreateOptions } from "arangojs/graph";
199+import type { CreateGraphOptions } from "arangojs/graph";
200```
201
202### Enum re-exports
203
204Previously the `CollectionStatus`, `CollectionType` and `ViewType` enums
205were re-exported by the arangojs main module and could be imported from the
206`arangojs` package:
207
208```diff
209-import { CollectionStatus, CollectionType } from "arangojs";
210+import { CollectionStatus, CollectionType } from "arangojs/collection";
211```
212
213Note that the `ViewType` enum has been removed completely:
214
215````diff
216-import { ViewType } from "arangojs";
217-
218-const ArangoSearchViewType = ViewType.ARANGOSEARCH_VIEW;
219+const ArangoSearchViewType = "arangosearch";
220
221## v6 to v7
222
223### Configuration changes
224
225The `db.useDatabase` method has been deprecated in v7.
226
227Previously the primary use of this method was to set the database name of the
228arangojs instance. The database name can now be specified using the
229`databaseName` option in the arangojs configuration:
230
231```diff
232 const db = new Database({
233 url: "http://127.0.0.1:8529",
234+ databaseName: "my_database",
235 });
236-db.useDatabase("my_database");
237````
238
239### Shared connection pool
240
241It is now possible to have multiple `Database` objects using the same
242underlying connection pool:
243
244```diff
245-const db1 = new Database();
246-db1.useDatabase("database1");
247-const db2 = new Database();
248-db2.useDatabase("database2");
249+const db1 = new Database({ databaseName: "database1" });
250+const db2 = db1.database("database2");
251```
252
253### Indexes
254
255The helper methods for creating specific index types, e.g. `createHashIndex`,
256have been removed and replaced with the generic `ensureIndex` method (which
257was previously called `createIndex`):
258
259```diff
260-await collection.createGeoIndex(["lat", "lng"]);
261+await collection.ensureIndex({ type: "geo", fields: ["lat", "lng"] });
262```
263
264### Document and edge collections
265
266Version 7 no longer provides different methods for accessing document and edge
267collections as both types are now implemented using the same underlying class:
268
269```diff
270 const myDocumentCollection = db.collection("documents");
271-const myEdgeCollection = db.edgeCollection("edges");
272+const myEdgeCollection = db.collection("edges");
273```
274
275When using TypeScript the collection instances can still be cast to the more
276specific `DocumentCollection` and `EdgeCollection` interfaces:
277
278```ts
279interface EdgeType {
280 color: string;
281}
282const myEdgeCollection = db.collection("edges") as EdgeCollection<EdgeType>;
283```
284
285### Saving edge documents
286
287The `save` method no longer supports positional arguments for `_from` and `_to`
288values. These now need to be supplied as part of the document data:
289
290```diff
291 await edges.save(
292- "vertices/start",
293- "vertices/end",
294- { color: "red" }
295+ { _from: "vertices/start", _to: "vertices/end", color: "red" }
296 );
297```
298
299### Accessing documents
300
301The `edge` method has been removed from the low-level collection API as it was
302an alias for the `document` method, which still exists:
303
304```diff
305-const edges = db.edgeCollection("edges");
306-const edge = await edges.edge("my-edge");
307+const edges = db.collection("edges");
308+const edge = await edges.document("my-edge");
309```
310
311Graph vertex and edge collections instead only retain their specific `vertex`
312and `edge` methods which access the collection using the high-level graph API:
313
314```diff
315 const vertices = graph.vertexCollection("vertices");
316-const vertex = await vertices.document("my-vertex");
317+const vertex = await vertices.vertex("my-vertex");
318
319 const edges = graph.edgeCollection("edges");
320-const edge = await edges.document("my-edge");
321+const edge = await edges.edge("my-edge");
322```
323
324### Graph collections
325
326Graph vertex and edge collections no longer implement the generic collection
327API methods to avoid confusion between operations that are aware of the graph
328definition (and can trigger graph-related side-effects) and those that directly
329access low-level operations.
330
331As a convenience both graph collection types still provide access to the
332low-level collection interface via the `collection` property:
333
334```diff
335 const graphEdges = graph.edgeCollection("edges");
336-const outEdges = graphEdges.outEdges("vertices/start");
337+const outEdges = graphEdges.collection.outEdges("vertices/start");
338```
339
340### Cursor methods
341
342The method `each` is now called `forEach`. The method `hasNext` has been
343replaced with a getter.
344
345The methods `some` and `every` have been removed. These methods previously
346allowed iterating over cursor results in order to derive a boolean value by
347applying a callback function to each value in the result.
348
349In most cases these methods can be avoided by writing a more efficient AQL
350query:
351
352```diff
353-const cursor = await db.query(aql`
354- FOR bowl IN porridges
355- RETURN bowl
356-`);
357-const someJustRight = await cursor.some(
358- (bowl) => bowl.temperature < TOO_HOT && bowl.temperature > TOO_COLD
359-);
360+const cursor = await db.query(aql`
361+ FOR bowl IN porridges
362+ FILTER bowl.temperature < ${TOO_HOT}
363+ FILTER bowl.temperature > ${TOO_COLD}
364+ LIMIT 1
365+ RETURN 1
366+`);
367+const someJustRight = Boolean(await cursor.next());
368```
369
370If this is not an option, the old behavior can be emulated using the `forEach`
371method (previously called `each`) instead:
372
373```diff
374-const someJustRight = await cursor.some(
375- (bowl) => bowl.temperature < TOO_HOT && bowl.temperature > TOO_COLD
376-);
377+const someJustRight = !(await cursor.forEach(
378+ (bowl) => bowl.temperature === TOO_HOT || bowl.temperature === TOO_COLD
379+));
380```
381
382### Batch cursor API
383
384Cursors now provide a low-level API for iterating over the result batches
385instead of individual items, which is exposed via the `batches` property.
386
387The methods `hasMore` and `nextBatch` have been replaced with the getter
388`batches.hasMore` and the method `batches.next`:
389
390```diff
391-if (cursor.hasMore()) {
392- return await cursor.nextBatch();
393+if (cursor.batches.hasMore) {
394+ return await cursor.batches.next();
395 }
396```
397
398### Simple queries
399
400Collection methods for using simple queries (e.g. `all`, `any` and `list`)
401have been deprecated in ArangoDB 3.0 and are now also deprecated in arangojs.
402
403See the documentation of each method for an example for how to perform the same
404query using an AQL query instead.
405
406Additionally the `list` method now returns a cursor instead of an array.
407
408### ArangoSearch Views
409
410The database methods `arangoSearchView` and `createArangoSearchView` have been
411renamed to `view` and `createView` respectively as there currently is no other
412view type available in ArangoDB:
413
414```diff
415-await db.createArangoSearchView("my-view");
416-const view = db.arangoSearchView("my-view");
417+await db.createView("my-view");
418+const view = db.view("my-view");
419```
420
421### Query options
422
423The `options` argument of `db.query` has been flattened. Options that were
424previously nested in an `options` property of that argument are now specified
425directly on the argument itself:
426
427```diff
428 const cursor = await db.query(
429 aql`
430 FOR doc IN ${collection}
431 RETURN doc
432 `,
433 {
434 cache: false,
435- options: { fullCount: true },
436+ fullCount: true,
437 }
438 );
439```
440
441### Bulk imports
442
443The default value of the `type` option now depends on the input type instead
444of always defaulting to `"auto"`. If you previously relied on the default
445value being set to `"auto"`, you may now need to explicitly set this option:
446
447```diff
448-await collection.import(data);
449+await collection.import(data, { type: "auto" });
450```
451
452### Bulk operations
453
454The collection method `bulkUpdate` has been removed and the methods
455`save`, `update`, `replace` and `remove` no longer accept arrays as input.
456
457Bulk operations can now be performed using the dedicated methods
458`saveAll`, `updateAll`, `replaceAll` and `removeAll`:
459
460```diff
461-await collection.save([{ _key: "a" }, { _key: "b" }]);
462+await collection.saveAll([{ _key: "a" }, { _key: "b" }]);
463```
464
465### Cross-collection operations
466
467Collection methods no longer accept document IDs from other collections.
468Previously passing a document ID referring to a different collection would
469result in the collection performing a request to that collection instead. Now
470mismatching IDs will result in an error instead:
471
472```js
473const collection1 = db.collection("collection1");
474const doc = await collection1.document("collection2/xyz"); // ERROR
475```
476
477### Creating graphs
478
479The signatures of `db.createGraph` and `graph.create` have changed to always
480take an array of edge definitions as the first argument instead of taking the
481edge definitions as a property of the `properties` argument.
482
483Additionally the `properties` and `options` arguments have been merged:
484
485```diff
486 await graph.create(
487+ [{ collection: "edges", from: ["a"], to: ["b"] }],
488 {
489- edgeDefinitions: [{ collection: "edges", from: ["a"], to: ["b"] }],
490 isSmart: true,
491- },
492- {
493 waitForSync: true,
494 }
495 );
496```
497
498### Transactions
499
500The transaction method `run` has been renamed to `step` to make it more obvious
501that it is intended to only perform a single "step" of the transaction.
502
503See the method's documentation for examples of how to use the method correctly.
504
505Additionally the method `transaction` no longer acts as an alias for
506`executeTransaction`:
507
508```diff
509-const result = await db.transaction(collections, action);
510+const result = await db.executeTransaction(collections, action);
511```
512
513### Service development mode
514
515The methods `enableServiceDevelopmentMode` and `disableServiceDevelopmentMode`
516have been replaced with the method `setServiceDevelopmentMode`:
517
518```diff
519-await db.enableServiceDevelopmentMode("/my-foxx");
520+await db.setServiceDevelopmentMode("/my-foxx", true);
521```
522
523### System services
524
525The default value of the method `listServices` option `excludeSystem` has been
526changed from `false` to `true`:
527
528```diff
529-const services = await db.listServices(true);
530+const services = await db.listServices();
531```
532
533### Query tracking
534
535The method `setQueryTracking` has been merged into `queryTracking`:
536
537```diff
538-await db.setQueryTracking({ enabled: true });
539+await db.queryTracking({ enabled: true });
540```
541
542### Collection properties
543
544The method `setProperties` has been merged into `properties`:
545
546```diff
547-await collection.setProperties({ waitForSync: true });
548+await collection.properties({ waitForSync: true });
549```
550
551### View properties
552
553The View method `setProperties` has been renamed to `updateProperties`:
554
555```diff
556-await view.setProperties({ consolidationIntervalMsec: 234 });
557+await view.updateProperties({ consolidationIntervalMsec: 234 });
558```
559
560### Truncating collections
561
562The `db.truncate` method has been removed. The behavior can still be mimicked
563using the `db.collections` and `collection.truncate` methods:
564
565```diff
566-await db.truncate();
567+await Promise.all(
568+ db.collections().map((collection) => collection.truncate())
569+);
570```