UNPKG

arangojs

Version:

The official ArangoDB JavaScript driver.

846 lines 27.9 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Graph = exports.isArangoGraph = exports.GraphEdgeCollection = exports.GraphVertexCollection = void 0; /** * ```ts * import type { * Graph, * GraphVertexCollection, * GraphEdgeCollection, * } from "arangojs/graphs"; * ``` * * The "graphs" module provides graph related types and interfaces * for TypeScript. * * @packageDocumentation */ const collections = __importStar(require("./collections.js")); const documents = __importStar(require("./documents.js")); const errors = __importStar(require("./errors.js")); const codes_js_1 = require("./lib/codes.js"); /** * @internal */ function mungeGharialResponse(body, prop) { const { [prop]: doc, ...meta } = body; return { ...meta, ...doc }; } /** * @internal */ function coerceEdgeDefinition(options) { const edgeDefinition = {}; edgeDefinition.collection = collections.collectionToString(options.collection); edgeDefinition.from = Array.isArray(options.from) ? options.from.map(collections.collectionToString) : [collections.collectionToString(options.from)]; edgeDefinition.to = Array.isArray(options.to) ? options.to.map(collections.collectionToString) : [collections.collectionToString(options.to)]; return edgeDefinition; } //#endregion //#region GraphVertexCollection class /** * Represents a {@link collections.DocumentCollection} of vertices in a {@link Graph}. * * @param EntryResultType - Type to represent vertex document contents returned * by the server (including computed properties). * @param EntryInputType - Type to represent vertex document contents passed * when inserting or replacing vertex documents (without computed properties). */ class GraphVertexCollection { _db; _name; _graph; _collection; /** * @internal */ constructor(db, name, graph) { this._db = db; this._collection = db.collection(name); this._name = this._collection.name; this._graph = graph; } /** * @internal * * Indicates that this object represents an ArangoDB collection. */ get isArangoCollection() { return true; } /** * Database this vertex collection belongs to. */ get database() { return this._db; } /** * Name of the collection. */ get name() { return this._name; } /** * A {@link collections.DocumentCollection} instance for this vertex collection. */ get collection() { return this._collection; } /** * The {@link Graph} instance this vertex collection is bound to. */ get graph() { return this._graph; } /** * Checks whether a vertex matching the given key or id exists in this * collection. * * Throws an exception when passed a vertex or `_id` from a different * collection. * * @param selector - Document `_key`, `_id` or object with either of those * properties (e.g. a vertex from this collection). * * @example * ```js * const graph = db.graph("some-graph"); * const collection = graph.vertexCollection("vertices"); * const exists = await collection.vertexExists("abc123"); * if (!exists) { * console.log("Vertex does not exist"); * } * ``` */ async vertexExists(selector) { try { return await this._db.request({ method: "HEAD", pathname: `/_api/gharial/${encodeURIComponent(this.graph.name)}/vertex/${encodeURI(documents._documentHandle(selector, this._name))}`, }, () => true); } catch (err) { if (err.code === 404) { return false; } throw err; } } async vertex(selector, options = {}) { if (typeof options === "boolean") { options = { graceful: options }; } const { allowDirtyRead = undefined, graceful = false, rev, ...search } = options; const headers = {}; if (rev) headers["if-match"] = rev; const result = this._db.request({ pathname: `/_api/gharial/${encodeURIComponent(this.graph.name)}/vertex/${encodeURI(documents._documentHandle(selector, this._name))}`, headers, search, allowDirtyRead, }, (res) => res.parsedBody.vertex); if (!graceful) return result; try { return await result; } catch (err) { if (errors.isArangoError(err) && err.errorNum === codes_js_1.DOCUMENT_NOT_FOUND) { return null; } throw err; } } save(data, options) { return this._db.request({ method: "POST", pathname: `/_api/gharial/${encodeURIComponent(this.graph.name)}/vertex/${encodeURIComponent(this._name)}`, body: data, search: options, }, (res) => mungeGharialResponse(res.parsedBody, "vertex")); } replace(selector, newData, options = {}) { if (typeof options === "string") { options = { rev: options }; } const { rev, ...search } = options; const headers = {}; if (rev) headers["if-match"] = rev; return this._db.request({ method: "PUT", pathname: `/_api/gharial/${encodeURIComponent(this.graph.name)}/vertex/${encodeURI(documents._documentHandle(selector, this._name))}`, body: newData, search, headers, }, (res) => mungeGharialResponse(res.parsedBody, "vertex")); } update(selector, newData, options = {}) { if (typeof options === "string") { options = { rev: options }; } const headers = {}; const { rev, ...search } = options; if (rev) headers["if-match"] = rev; return this._db.request({ method: "PATCH", pathname: `/_api/gharial/${encodeURIComponent(this.graph.name)}/vertex/${encodeURI(documents._documentHandle(selector, this._name))}`, body: newData, search, headers, }, (res) => mungeGharialResponse(res.parsedBody, "vertex")); } remove(selector, options = {}) { if (typeof options === "string") { options = { rev: options }; } const headers = {}; const { rev, ...search } = options; if (rev) headers["if-match"] = rev; return this._db.request({ method: "DELETE", pathname: `/_api/gharial/${encodeURIComponent(this.graph.name)}/vertex/${encodeURI(documents._documentHandle(selector, this._name))}`, search, headers, }, (res) => mungeGharialResponse(res.parsedBody, "removed")); } } exports.GraphVertexCollection = GraphVertexCollection; //#endregion //#region GraphEdgeCollection class /** * Represents a {@link collections.EdgeCollection} of edges in a {@link Graph}. * * @param EntryResultType - Type to represent edge document contents returned * by the server (including computed properties). * @param EntryInputType - Type to represent edge document contents passed * when inserting or replacing edge documents (without computed properties). */ class GraphEdgeCollection { _db; _name; _graph; _collection; /** * @internal */ constructor(db, name, graph) { this._db = db; this._collection = db.collection(name); this._name = this._collection.name; this._graph = graph; } /** * @internal * * Indicates that this object represents an ArangoDB collection. */ get isArangoCollection() { return true; } /** * Database this edge collection belongs to. */ get database() { return this._db; } /** * Name of the collection. */ get name() { return this._name; } /** * A {@link collections.EdgeCollection} instance for this edge collection. */ get collection() { return this._collection; } /** * The {@link Graph} instance this edge collection is bound to. */ get graph() { return this._graph; } /** * Checks whether a edge matching the given key or id exists in this * collection. * * Throws an exception when passed a edge or `_id` from a different * collection. * * @param selector - Document `_key`, `_id` or object with either of those * properties (e.g. a edge from this collection). * * @example * ```js * const graph = db.graph("some-graph"); * const collection = graph.edgeCollection("friends") * const exists = await collection.edgeExists("abc123"); * if (!exists) { * console.log("Edge does not exist"); * } * ``` */ async edgeExists(selector) { try { return await this._db.request({ method: "HEAD", pathname: `/_api/gharial/${encodeURIComponent(this.graph.name)}/edge/${encodeURI(documents._documentHandle(selector, this._name))}`, }, () => true); } catch (err) { if (err.code === 404) { return false; } throw err; } } async edge(selector, options = {}) { if (typeof options === "boolean") { options = { graceful: options }; } const { allowDirtyRead = undefined, graceful = false, rev, ...search } = options; const headers = {}; if (rev) headers["if-match"] = rev; const result = this._db.request({ pathname: `/_api/gharial/${encodeURIComponent(this.graph.name)}/edge/${encodeURI(documents._documentHandle(selector, this._name))}`, search, allowDirtyRead, }, (res) => res.parsedBody.edge); if (!graceful) return result; try { return await result; } catch (err) { if (errors.isArangoError(err) && err.errorNum === codes_js_1.DOCUMENT_NOT_FOUND) { return null; } throw err; } } save(data, options) { return this._db.request({ method: "POST", pathname: `/_api/gharial/${encodeURIComponent(this.graph.name)}/edge/${encodeURIComponent(this._name)}`, body: data, search: options, }, (res) => mungeGharialResponse(res.parsedBody, "edge")); } replace(selector, newData, options = {}) { if (typeof options === "string") { options = { rev: options }; } const { rev, ...search } = options; const headers = {}; if (rev) headers["if-match"] = rev; return this._db.request({ method: "PUT", pathname: `/_api/gharial/${encodeURIComponent(this.graph.name)}/edge/${encodeURI(documents._documentHandle(selector, this._name))}`, body: newData, search, headers, }, (res) => mungeGharialResponse(res.parsedBody, "edge")); } update(selector, newData, options = {}) { if (typeof options === "string") { options = { rev: options }; } const { rev, ...search } = options; const headers = {}; if (rev) headers["if-match"] = rev; return this._db.request({ method: "PATCH", pathname: `/_api/gharial/${encodeURIComponent(this.graph.name)}/edge/${encodeURI(documents._documentHandle(selector, this._name))}`, body: newData, search, headers, }, (res) => mungeGharialResponse(res.parsedBody, "edge")); } remove(selector, options = {}) { if (typeof options === "string") { options = { rev: options }; } const { rev, ...search } = options; const headers = {}; if (rev) headers["if-match"] = rev; return this._db.request({ method: "DELETE", pathname: `/_api/gharial/${encodeURIComponent(this.graph.name)}/edge/${encodeURI(documents._documentHandle(selector, this._name))}`, search, headers, }, (res) => mungeGharialResponse(res.parsedBody, "removed")); } } exports.GraphEdgeCollection = GraphEdgeCollection; //#endregion //#region Graph class /** * Indicates whether the given value represents a {@link Graph}. * * @param graph - A value that might be a Graph. */ function isArangoGraph(graph) { return Boolean(graph && graph.isArangoGraph); } exports.isArangoGraph = isArangoGraph; /** * Represents a graph in a {@link databases.Database}. */ class Graph { _name; _db; /** * @internal */ constructor(db, name) { this._db = db; this._name = name; } /** * Indicates that this object represents an ArangoDB Graph. */ get isArangoGraph() { return true; } /** * Database this graph belongs to. */ get database() { return this._db; } /** * Name of the graph. */ get name() { return this._name; } /** * Checks whether the graph exists. * * @example * ```js * const db = new Database(); * const graph = db.graph("some-graph"); * const result = await graph.exists(); * // result indicates whether the graph exists * ``` */ async exists() { try { await this.get(); return true; } catch (err) { if (errors.isArangoError(err) && err.errorNum === codes_js_1.GRAPH_NOT_FOUND) { return false; } throw err; } } /** * Retrieves general information about the graph. * * @example * ```js * const db = new Database(); * const graph = db.graph("some-graph"); * const data = await graph.get(); * // data contains general information about the graph * ``` */ get() { return this._db.request({ pathname: `/_api/gharial/${encodeURIComponent(this._name)}` }, (res) => res.parsedBody.graph); } /** * Creates a graph with the given `edgeDefinitions` and `options` for this * graph's name. * * @param edgeDefinitions - Definitions for the relations of the graph. * @param options - Options for creating the graph. * * @example * ```js * const db = new Database(); * const graph = db.graph("some-graph"); * const info = await graph.create([ * { * collection: "edges", * from: ["start-vertices"], * to: ["end-vertices"], * }, * ]); * // graph now exists * ``` */ create(edgeDefinitions, options = {}) { const { orphanCollections, satellites, waitForSync, isSmart, ...opts } = options; return this._db.request({ method: "POST", pathname: "/_api/gharial", body: { orphanCollections: orphanCollections && (Array.isArray(orphanCollections) ? orphanCollections.map(collections.collectionToString) : [collections.collectionToString(orphanCollections)]), edgeDefinitions: edgeDefinitions.map(coerceEdgeDefinition), isSmart, name: this._name, options: { ...opts, satellites: satellites?.map(collections.collectionToString), }, }, search: { waitForSync }, }, (res) => res.parsedBody.graph); } /** * Deletes the graph from the database. * * @param dropCollections - If set to `true`, the collections associated with * the graph will also be deleted. * * @example * ```js * const db = new Database(); * const graph = db.graph("some-graph"); * await graph.drop(); * // the graph "some-graph" no longer exists * ``` */ drop(dropCollections = false) { return this._db.request({ method: "DELETE", pathname: `/_api/gharial/${encodeURIComponent(this._name)}`, search: { dropCollections }, }, (res) => res.parsedBody.removed); } /** * Returns a {@link GraphVertexCollection} instance for the given collection * name representing the collection in this graph. * * @param T - Type to use for document data. Defaults to `any`. * @param collection - Name of the vertex collection. */ vertexCollection(collection) { return new GraphVertexCollection(this._db, collections.collectionToString(collection), this); } /** * Fetches all vertex collections of this graph from the database and returns * an array of their names. * * See also {@link Graph#vertexCollections}. * * @example * ```js * const db = new Database(); * const graph = db.graph("some-graph"); * const info = await graph.create([ * { * collection: "edges", * from: ["start-vertices"], * to: ["end-vertices"], * }, * ]); * const vertexCollectionNames = await graph.listVertexCollections(); * // ["start-vertices", "end-vertices"] * ``` */ listVertexCollections() { return this._db.request({ pathname: `/_api/gharial/${encodeURIComponent(this._name)}/vertex` }, (res) => res.parsedBody.collections); } /** * Fetches all vertex collections of this graph from the database and returns * an array of {@link GraphVertexCollection} instances. * * See also {@link Graph#listVertexCollections}. * * @example * ```js * const db = new Database(); * const graph = db.graph("some-graph"); * const info = await graph.create([ * { * collection: "edges", * from: ["start-vertices"], * to: ["end-vertices"], * }, * ]); * const vertexCollections = await graph.vertexCollections(); * for (const vertexCollection of vertexCollections) { * console.log(vertexCollection.name); * // "start-vertices" * // "end-vertices" * } * ``` */ async vertexCollections() { const names = await this.listVertexCollections(); return names.map((name) => new GraphVertexCollection(this._db, name, this)); } /** * Adds the given collection to this graph as a vertex collection. * * @param collection - Collection to add to the graph. * * @example * ```js * const db = new Database(); * const graph = db.graph("some-graph"); * await graph.addVertexCollection("more-vertices"); * // The collection "more-vertices" has been added to the graph * const extra = db.collection("extra-vertices"); * await graph.addVertexCollection(extra); * // The collection "extra-vertices" has been added to the graph * ``` */ addVertexCollection(collection, options = {}) { const { satellites, ...opts } = options; return this._db.request({ method: "POST", pathname: `/_api/gharial/${encodeURIComponent(this._name)}/vertex`, body: { collection: collections.collectionToString(collection), options: { ...opts, satellites: satellites?.map(collections.collectionToString), }, }, }, (res) => res.parsedBody.graph); } /** * Removes the given collection from this graph as a vertex collection. * * @param collection - Collection to remove from the graph. * @param dropCollection - If set to `true`, the collection will also be * deleted from the database. * * @example * ```js * const db = new Database(); * const graph = db.graph("some-graph"); * const info = await graph.create([ * { * collection: "edges", * from: ["start-vertices"], * to: ["end-vertices"], * }, * ]); * await graph.removeVertexCollection("start-vertices"); * // The collection "start-vertices" is no longer part of the graph. * ``` */ removeVertexCollection(collection, dropCollection = false) { return this._db.request({ method: "DELETE", pathname: `/_api/gharial/${encodeURIComponent(this._name)}/vertex/${encodeURIComponent(collections.collectionToString(collection))}`, search: { dropCollection, }, }, (res) => res.parsedBody.graph); } /** * Returns a {@link GraphEdgeCollection} instance for the given collection * name representing the collection in this graph. * * @param T - Type to use for document data. Defaults to `any`. * @param collection - Name of the edge collection. * * @example * ```js * const db = new Database(); * const graph = db.graph("some-graph"); * const info = await graph.create([ * { * collection: "edges", * from: ["start-vertices"], * to: ["end-vertices"], * }, * ]); * const graphEdgeCollection = graph.edgeCollection("edges"); * // Access the underlying EdgeCollection API: * const edgeCollection = graphEdgeCollection.collection; * ``` */ edgeCollection(collection) { return new GraphEdgeCollection(this._db, collections.collectionToString(collection), this); } /** * Fetches all edge collections of this graph from the database and returns * an array of their names. * * See also {@link Graph#edgeCollections}. * * @example * ```js * const db = new Database(); * const graph = db.graph("some-graph"); * const info = await graph.create([ * { * collection: "edges", * from: ["start-vertices"], * to: ["end-vertices"], * }, * ]); * const edgeCollectionNames = await graph.listEdgeCollections(); * // ["edges"] * ``` */ listEdgeCollections() { return this._db.request({ pathname: `/_api/gharial/${encodeURIComponent(this._name)}/edge` }, (res) => res.parsedBody.collections); } /** * Fetches all edge collections of this graph from the database and returns * an array of {@link GraphEdgeCollection} instances. * * See also {@link Graph#listEdgeCollections}. * * @example * ```js * const db = new Database(); * const graph = db.graph("some-graph"); * const info = await graph.create([ * { * collection: "edges", * from: ["start-vertices"], * to: ["end-vertices"], * }, * ]); * const graphEdgeCollections = await graph.edgeCollections(); * for (const collection of graphEdgeCollection) { * console.log(collection.name); * // "edges" * } * ``` */ async edgeCollections() { const names = await this.listEdgeCollections(); return names.map((name) => new GraphEdgeCollection(this._db, name, this)); } /** * Adds an edge definition to this graph. * * @param edgeDefinition - Definition of a relation in this graph. * * @example * ```js * const db = new Database(); * const graph = db.graph("some-graph"); * await graph.addEdgeDefinition({ * collection: "edges", * from: ["start-vertices"], * to: ["end-vertices"], * }); * // The edge definition has been added to the graph * ``` */ addEdgeDefinition(edgeDefinition, options = {}) { const { satellites, ...opts } = options; return this._db.request({ method: "POST", pathname: `/_api/gharial/${encodeURIComponent(this._name)}/edge`, body: { ...coerceEdgeDefinition(edgeDefinition), options: { ...opts, satellites: satellites?.map(collections.collectionToString), }, }, }, (res) => res.parsedBody.graph); } replaceEdgeDefinition(collectionOrEdgeDefinitionOptions, edgeDefinitionOrOptions, options = {}) { let collection = collectionOrEdgeDefinitionOptions; let edgeDefinition = edgeDefinitionOrOptions; if (edgeDefinitionOrOptions && !edgeDefinitionOrOptions.hasOwnProperty("collection")) { options = edgeDefinitionOrOptions; edgeDefinitionOrOptions = undefined; } if (!edgeDefinitionOrOptions) { edgeDefinition = collectionOrEdgeDefinitionOptions; collection = edgeDefinition.collection; } const { satellites, ...opts } = options; return this._db.request({ method: "PUT", pathname: `/_api/gharial/${encodeURIComponent(this._name)}/edge/${encodeURIComponent(collections.collectionToString(collection))}`, body: { ...coerceEdgeDefinition(edgeDefinition), options: { ...opts, satellites: satellites?.map(collections.collectionToString), }, }, }, (res) => res.parsedBody.graph); } /** * Removes the edge definition for the given edge collection from this graph. * * @param collection - Edge collection for which to remove the definition. * @param dropCollection - If set to `true`, the collection will also be * deleted from the database. * * @example * ```js * const db = new Database(); * const graph = db.graph("some-graph"); * const info = await graph.create([ * { * collection: "edges", * from: ["start-vertices"], * to: ["end-vertices"], * }, * ]); * await graph.removeEdgeDefinition("edges"); * // The edge definition for "edges" has been replaced * ``` */ removeEdgeDefinition(collection, dropCollection = false) { return this._db.request({ method: "DELETE", pathname: `/_api/gharial/${encodeURIComponent(this._name)}/edge/${encodeURIComponent(collections.collectionToString(collection))}`, search: { dropCollection, }, }, (res) => res.parsedBody.graph); } } exports.Graph = Graph; //#endregion //# sourceMappingURL=graphs.js.map