UNPKG

@flexvertex/flexvertex-driver

Version:

The official FlexVertex Node.js driver

567 lines (439 loc) 17.4 kB
import fs from 'node:fs'; import { JSONParse, JSONStringify } from 'json-with-bigint'; import { FlexCommons } from '../commons/FlexCommons.js'; import { FlexCargo } from '../journey/FlexCargo.js'; import { FlexObject } from '../objects/FlexObject.js'; import { FlexConnection } from '../connections/FlexConnection.js'; import { FlexResultSet } from './FlexResultSet.js'; /** * Represents a FlexVertex Schema. */ export class FlexSchema { // Holds the list of FlexObjects to save. #objectsToSave = new Map(); #objectsToDelete = new Array(); // Holds the list of FlexConnections to save. #cxsToSave = new Map(); #cxsToDelete = new Array(); #dnsPath; #flexSession; /** * * @param {!FlexSession} flexSession - The FlexSession this FlexSchema belongs * @param {?string} dnsPath - The /Domain/Nexus/Schema path */ constructor(flexSession, dnsPath) // dnsPath may be null { this.#flexSession = flexSession; this.#dnsPath = dnsPath; } /** * Should be called when this FlexSchema is no longer needed. */ close() { // console.log("--FlexSchema.close()"); } createConnection(sourceKey, destinationKey, options) { let cx = new FlexConnection(this, sourceKey, destinationKey, options); cx.save(); return cx; } async createObject(flexObject) { // console.log("FlexSchema.createObject()"); if(flexObject === undefined) throw "FlexSchema.createObject() FlexObject is undefined!"; if(flexObject.className === undefined) throw "FlexSchema.createObject() FlexObject.className is undefined!"; if(flexObject.properties === undefined) throw "FlexSchema.createObject() FlexObject.properties is undefined!"; // console.log("FlexSchema.createObject() about to call post, props = " + JSONStringify(flexObject.properties)); const response = await this.#flexSession.axInstance.post('schema/createObject', { Class: flexObject.className, Attributes: flexObject.attributes, Properties: flexObject.properties }); // console.log("FlexSchema.createObject() post complete response = " + response); if(response.data === undefined) throw "FlexSchema.createObject() Returned Response is undefined!"; if(response.data.ObjectKey === undefined) throw "FlexSchema.createObject() Returned ObjectKey is undefined!"; // console.log("response.data.objectKey = " + response.data.objectKey); flexObject.objectKey = response.data.ObjectKey; return response.data; } /** * Deletes the specified {@link FlexConnection}. FlexSchema.save() must be called to complete the deletion. * @param {!FlexConnection} flexConnection */ deleteConnection(flexConnection) { if(flexConnection === undefined) throw "FlexSchema.deleteConnection() FlexConnection is undefined!"; //console.log("--deleteConnection() objectKey = " + flexConnection.objectKey); if(FlexCommons.isDefined(flexConnection.objectKey)) this.#cxsToDelete.push(flexConnection.objectKey); } /** * Deletes a {@link FlexConnection} by specifying its ObjectKey. FlexSchema.save() must be called to complete the deletion. * @param {!string} objectKey */ deleteConnectionByKey(objectKey) { if(objectKey === undefined) throw "FlexSchema.deleteConnectionByKey() ObjectKey is undefined!"; // console.log("--deleteConnectionByKey() objectKey = " + objectKey); if(FlexCommons.isDefined(objectKey)) this.#cxsToDelete.push(objectKey); } /** * Deletes the specified {@link FlexObject}. FlexSchema.save() must be called to complete the deletion. * @param {!FlexObject} flexObject */ deleteObject(flexObject) { if(flexObject === undefined) throw "FlexSchema.deleteObject() FlexObject is undefined!"; //console.log("--deleteObject() objectKey = " + flexObject.objectKey); if(FlexCommons.isDefined(flexObject.objectKey)) this.#objectsToDelete.push(flexObject.objectKey); } /** * Deletes a {@link FlexObject} by specifying its ObjectKey. FlexSchema.save() must be called to complete the deletion. * @param {!string} objectKey */ deleteObjectByKey(objectKey) { if(objectKey === undefined) throw "FlexSchema.deleteObjectByKey() ObjectKey is undefined!"; // console.log("--deleteObjectByKey() objectKey = " + objectKey); if(FlexCommons.isDefined(objectKey)) this.#objectsToDelete.push(objectKey); /* const response = await this.#flexSession.axInstance.delete('schema/deleteObject', { params: { objectKey: objectKey } });*/ // return response.data; } /** * Executes a Voyage from a local file * @param {!string} voyagerFilePath - The path to the Voyager file * @param {Object} [namedParams] - Each property in the object is passed to Voyager as a namedParams property * @returns {FlexCargo} */ async executeVoyagerFile(voyagerFilePath, namedParams) { try { const voyage = fs.readFileSync(voyagerFilePath, 'utf8'); return this.executeVoyage(voyage, namedParams); } catch(err) { console.error("FlexSchema.executeVoyagerFile() error: " + err); } } /** * Executes a Voyage from the passed-in string * @param {!string} voyage - The Voyager contents * @param {Object} [namedParams] - Each property in the object is passed to Voyager as a namedParams property * @returns {FlexCargo} */ async executeVoyage(voyage, namedParams) { // console.log("-- FlexSchema.executeVoyage() voyage = " + voyage); if(namedParams == null) namedParams = { }; const response = await this.#flexSession.axInstance.post('schema/executeVoyage', { Voyage: voyage, NamedParams: namedParams, DNS: this.#dnsPath }); if(response === undefined) throw "FlexSchema.executeVoyage() response is undefined!"; if(response.data === undefined) throw "FlexSchema.executeVoyage() response.data is undefined!"; if(response.data.Cargo === undefined) throw "FlexSchema.executeVoyage() response.data Cargo is undefined!"; // console.log("-- FlexSchema.executeVoyage() response.data.Cargo = " + JSONStringify(response.data.Cargo)); let cargo = new FlexCargo(this, response.data.Cargo); // console.log("-- FlexSchema.executeVoyage() cargo = " + cargo); return cargo; } /** * Executes a Voyage from a remote asset * @param {!string} assetPath - The asset path to the Voyager file * @param {Object} [namedParams] - Each property in the object is passed to Voyager as a namedParams property * @returns {FlexCargo} */ async executeVoyagerAsset(assetPath, namedParams) { if(namedParams == null) namedParams = { }; const response = await this.#flexSession.axInstance.post('schema/executeVoyagerAsset', { AssetPath: assetPath, NamedParams: namedParams, DNS: this.#dnsPath }); if(response === undefined) throw "FlexSchema.executeVoyagerAsset() response is undefined!"; if(response.data === undefined) throw "FlexSchema.executeVoyagerAsset() response.data is undefined!"; if(response.data.Cargo === undefined) throw "FlexSchema.executeVoyagerAsset() response.data Cargo is undefined!"; let cargo = new FlexCargo(this, response.data.Cargo); return cargo; } /** * Loads and returns a {@link FlexConnection} from the specified ObjectKey * @param {!string} objectKey * @returns FlexConnection */ async loadConnection(objectKey) { if(objectKey === undefined) throw "FlexSchema.loadConnection() objectKey is undefined!"; const response = await this.#flexSession.axInstance.get('schema/loadConnection', { params: { ObjectKey: objectKey }, DNS: this.#dnsPath }); if(response.data === undefined) throw "FlexSchema.loadConnection() Returned Response is undefined!"; if(response.data.Connection === undefined) throw "FlexSchema.loadConnection() Returned Response Connection is undefined!"; let cx = FlexConnection.createFromObject(this, response.data.Connection); // console.log("-- loadConnection() data = " + JSONStringify(response.data)); // if(response.data.Connection.Class === undefined) throw "FlexSchema.loadConnection() Returned Class is undefined!"; // if(response.data.connection.objectKey === undefined) throw "FlexSchema.loadConnection() Returned objectKey is undefined!"; // if(response.data.connection.properties === undefined) throw "FlexSchema.loadConnection() Returned properties is undefined!"; // let cx = new FlexConnection(this, response.data.Connection); // cx.objectKey = response.data.connection.objectKey; // cx.attributes = response.data.connection.attributes; // cx.properties = response.data.connection.properties; return cx; } /** * Loads and returns a {@link FlexObject} from the specified ObjectKey * @param {!string} objectKey * @returns FlexObject */ async loadObject(objectKey) { if(objectKey === undefined) throw "FlexSchema.loadObject() objectKey is undefined!"; const response = await this.#flexSession.axInstance.get('schema/loadObject', { params: { ObjectKey: objectKey }, DNS: this.#dnsPath }); if(response.data === undefined) throw "FlexSchema.loadObject() Returned Response is undefined!"; if(response.data.Object === undefined) throw "FlexSchema.loadObject() Returned Object is undefined!"; // console.log("-- loadObject() data = " + JSONStringify(response.data)); let obj = FlexObject.createFromObject(this, response.data.Object); /* if(response.data.object.class === undefined) throw "FlexSchema.loadObject() Returned class is undefined!"; if(response.data.object.objectKey === undefined) throw "FlexSchema.loadObject() Returned objectKey is undefined!"; if(response.data.object.properties === undefined) throw "FlexSchema.loadObject() Returned properties is undefined!"; let obj = new FlexObject(this, response.data.object.class); obj.objectKey = response.data.object.objectKey; obj.attributes = response.data.object.attributes; obj.properties = response.data.object.properties; */ return obj; } /** * * @param {!string} sql * @param {Object} [namedParams] - Each property in the object is passed to the SQL executor as a named parameter * @returns {FlexResultSet} */ async query(sql, namedParams) { // let keys = Object.keys(namedParams) // console.log("query(sql, namedParams)"); if(namedParams == null) namedParams = { }; const response = await this.#flexSession.axInstance.post('schema/sql', { Query: sql, NamedParams: namedParams, DNS: this.#dnsPath }); if(response === undefined) throw "FlexSchema.query() response is undefined!"; const objectArray = new Array(); if(response.data === undefined) throw "FlexSchema.query() response.data is undefined!"; if(!(response.data.ResultSet === undefined)) { let rs = new FlexResultSet(this, response.data.ResultSet); return rs; } return null; } async saveObject(flexObject) { if(flexObject === undefined) throw "FlexSchema.saveObject() FlexObject is undefined!"; /* if(flexObject.objectKey === undefined) { if(flexObject.className === undefined) throw "FlexSchema.saveObject() FlexObject.className is undefined!"; return this.createObject(flexObject); } else { return this.updateObject(flexObject); } */ // this.#objectsToSave.push(flexObject); // Object.defineProperty(this.#objectsToSave, flexObject.uniqueID, { value: flexObject, enumerable: true, writable: true }); this.#objectsToSave.set(flexObject.uniqueID, flexObject); /* if(flexObject.isNew()) { this.#objectsToSave.push({ class: flexObject.className, properties: flexObject.properties }); } else { this.#objectsToSave.push({ objectKey: flexObject.objectKey, properties: flexObject.properties }); }*/ } addSavingConnection(flexConnection) { if(flexConnection === undefined) throw "FlexSchema.addSavingConnection() FlexConnection is undefined!"; // this.#cxsToSave.push(flexConnection); // console.log("FlexSchema.addSavingCx() cx uniqueID = " + flexConnection.uniqueID); // Object.defineProperty(this.#cxsToSave, flexConnection.uniqueID, { value: flexConnection, enumerable: true, writable: true }); this.#cxsToSave.set(flexConnection.uniqueID, flexConnection); } /** * Must be called anytime a FlexObject or FlexConnection needs to be saved or deleted. * */ async save() { // The order of operations must be: // - SaveObjects // - SaveConnections // - DeleteConnections // - DeleteObjects // This is important because deleting objects with connections will delete the connections too. // To avoid an error by calling DeleteConnections, last, we make sure the connections are deleted first, just in case. // console.log("-- save() objectArray = " + JSONStringify(this.#objectsToSave)); //objects: Object.fromEntries(this.#objectsToSave) let saveObjArray = new Array(); let saveCxArray = new Array(); let deleteCxArray = new Array(); let deleteObjArray = new Array(); this.#objectsToSave.forEach((value, key) => { saveObjArray.push(value.getObject()); }); this.#cxsToSave.forEach((value, key) => { saveCxArray.push(value.getObject()); }); for(const objectKey of this.#cxsToDelete) { deleteCxArray.push(objectKey); } for(const objectKey of this.#objectsToDelete) { deleteObjArray.push(objectKey); } // Save the Objects if(saveObjArray.length > 0) { const response = await this.#flexSession.axInstance.post('schema/saveObjects', { SaveObjects: saveObjArray, DNS: this.#dnsPath }) .catch(function(error) { console.log("-- save() error = " + error); }); if(response === undefined) throw "FlexSchema.save() saveObjects response is undefined!"; if(response.data === undefined) throw "FlexSchema.save() saveObjects response.data is undefined!"; if(FlexCommons.isDefined(response.data.SavedObjects)) { for(const so of response.data.SavedObjects) { if(FlexCommons.isDefined(so.UniqueID)) { let obj = this.#objectsToSave.get(so.UniqueID); if(FlexCommons.isDefined(obj)) { obj.objectKey = so.ObjectKey; } } } } // Empty the arrays. saveObjArray = [ ]; this.#objectsToSave.clear(); } // Save the Connections if(saveCxArray.length > 0) { const cxResponse = await this.#flexSession.axInstance.post('schema/saveConnections', { SaveConnections: saveCxArray, DNS: this.#dnsPath }) .catch(function(error) { console.log("-- save() cx error = " + error); }); if(cxResponse === undefined) throw "FlexSchema.save() saveConnections response is undefined!"; if(cxResponse.data === undefined) throw "FlexSchema.save() saveConnections response.data is undefined!"; if(FlexCommons.isDefined(cxResponse.data.SavedConnections)) { for(const so of cxResponse.data.SavedConnections) { if(FlexCommons.isDefined(so.UniqueID)) { let obj = this.#cxsToSave.get(so.UniqueID); if(FlexCommons.isDefined(obj)) obj.objectKey = so.ObjectKey; } } } // Empty the arrays. saveCxArray = [ ]; this.#cxsToSave.clear(); } // Delete the Connections if(deleteCxArray.length > 0) { const cxResponse = await this.#flexSession.axInstance.delete('schema/deleteConnections', { data: { ObjectKeys: deleteCxArray } }) .catch(function(error) { console.log("-- save() cx error = " + error); }); if(cxResponse === undefined) throw "FlexSchema.save() deleteConnections response is undefined!"; if(cxResponse.data === undefined) throw "FlexSchema.save() deleteConnections response.data is undefined!"; // console.log("-- save() deleteConnections response = " + JSONStringify(cxResponse.data)); deleteCxArray = [ ]; this.#cxsToDelete = [ ]; } // Delete the Objects (do this last) if(deleteObjArray.length > 0) { const response = await this.#flexSession.axInstance.delete('schema/deleteObjects', { data: { ObjectKeys: deleteObjArray } }) .catch(function(error) { console.log("-- save() error = " + error); }); if(response === undefined) throw "FlexSchema.save() deleteObjects response is undefined!"; if(response.data === undefined) throw "FlexSchema.save() deleteObjects response.data is undefined!"; // console.log("-- save() deleteObjects response = " + JSONStringify(response.data)); // Empty the arrays. deleteObjArray = [ ]; this.#objectsToDelete = [ ]; } // console.log("-- save() response = " + JSONStringify(response.data)); // return response.data; } async updateObject(flexObject) { if(flexObject === undefined) throw "FlexSchema.updateObject() FlexObject is undefined!"; if(flexObject.objectKey === undefined) throw "FlexSchema.updateObject() FlexObject.objectKey is undefined!"; const response = await this.#flexSession.axInstance.post('schema/updateObject', { ObjectKey: flexObject.objectKey, Properties: flexObject.properties, DNS: this.#dnsPath }); return response.data; } }