import { DataDiscoveryFilter } from './datadiscoveryfilter.js';
import { BaseRequestHandler } from './baserequesthandler.js';
import { SlashDBClient } from './slashdbclient.js';
const SDB_DDD_NO_CLIENTOBJ = 'Parameter clientObj missing or not valid SlashDBClient object';
const SDB_DDD_NO_DB = 'Parameter db must be a string';
class DataDiscoveryDatabase {
constructor(clientObj, dbName) {
if (!clientObj || !(clientObj instanceof SlashDBClient)) {
throw ReferenceError(SDB_DDD_NO_CLIENTOBJ);
}
if (!dbName || typeof(dbName) !== 'string') {
throw ReferenceError(SDB_DDD_NO_DB);
}
if (!isNaN(dbName)) {
throw TypeError(SDB_DDR_NO_DB);
}
this.sdbClient = clientObj;
this.dbName = dbName;
}
// explore resources in DB
async getDataDiscoveryResources() {
let db = await this.sdbClient.getReflectStatus(this.dbName);
const resources = {};
if (db.model !== 'Connected') {
console.log(`Database ${this.dbName} is not connected`);
return;
}
for (const resource of db.tables) {
resources[resource.table_name] = new DataDiscoveryResource(this.dbName, resource.table_name, this.sdbClient);
}
return resources;
}
}
const SDB_DDR_NO_CLIENTOBJ = 'Parameter clientObj missing or not valid SlashDBClient object';
const SDB_DDR_NO_RESOURCE = 'Parameter resourceName must be a string';
const SDB_DDR_NO_DB = 'Parameter db must be a string or a DataDiscoveryDatabase object';
const SDR_DDR_NO_DB_NAME = 'DataDiscoveryDatabase object missing/invalid parameter dbName, must be string';
const SDB_DDR_INVALID_PATH_EMPTY = 'Empty path given';
const SDB_DDR_INVALID_PATH_TYPE = 'Path is not a string or a DataDiscoveryFilter object';
/**
* Executes HTTP requests for SlashDB Data Discovery functionality. `Extends the BaseRequestHandler` class
* for most methods.
*/
class DataDiscoveryResource extends BaseRequestHandler {
/**
* Create a `DataDiscoveryResource` object for a given SlashDB instance
* @extends BaseRequestHandler
* @param {string | DataDiscoveryDatabase} db - name of database to interact with via this instance, or a previously configured `DataDiscoveryDatabase` object
* @param {string} resource - name of resource (table) to interact with via this instance
* @param {SlashDBClient} [clientObj] - an optional configured `SlashDBClient` object
* @throws {ReferenceError | TypeError} if `db` parameter is a `DataDiscoveryObject` that is missing `dbName` property or has invalid `dbName` property
* @throws {TypeError} if `db` parameter is: not a `DataDiscoveryObject`/not a string/parses to a number
* @throws {TypeError} if `resource` parameter is not a string or an empty string, or parses to a number
* @throws {ReferenceError} if no `clientObj` parameter was given, and a valid `SlashDBClient` object is not contained within `db` parameter,
* which must be a `DataDiscoveryDatabase` object if `clientObj` is omitted
*/
constructor(db, resourceName, clientObj) {
super(clientObj);
// db parameter can be a string or a DataDiscoveryDatabase
if (db instanceof DataDiscoveryDatabase) {
if (!db.dbName || typeof(db.dbName) !== 'string') {
throw ReferenceError(SDR_DDR_NO_DB_NAME);
}
if (!isNaN(db.dbName)) {
throw TypeError(SDR_DDR_NO_DB_NAME);
}
this.dbName = db.dbName;
}
else if (typeof(db) === 'string') {
if (!isNaN(db)) {
throw TypeError(SDB_DDR_NO_DB);
}
this.dbName = db;
}
else {
throw TypeError(SDB_DDR_NO_DB);
}
// resourceName is always a string
if (typeof(resourceName) !== 'string' || resourceName.trim().length < 1) {
throw TypeError(SDB_DDR_NO_RESOURCE);
}
if (!isNaN(resourceName)) {
throw TypeError(SDB_DDR_NO_RESOURCE);
}
this.dbPrefix = '/db/'
this.resourceName = resourceName;
// if no client object explicity given, the client object must be in the db parameter,
// which must be a DataDiscoveryDatabase object in order to proceed
if (!clientObj) {
if (! (db instanceof DataDiscoveryDatabase)) {
throw ReferenceError(SDB_DDR_NO_DB);
}
if (!db.sdbClient || !(db.sdbClient instanceof SlashDBClient)) {
throw ReferenceError(SDB_DDR_NO_CLIENTOBJ);
}
this.sdbClient = db.sdbClient;
}
}
/**
* Builds the full endpoint to the requested resource. Meant for internal use only.
* @param {string | DataDiscoveryFilter} [path] - an optional string containing a URI segment with SQL query parameters/values and URL query parameters
* (e.g. `/FirstName/Tim?distinct=true`), or a `DataDiscoveryFilter` object that contains all the query details
* @returns {string} the full endpoint
* @throws {ReferenceError} if no `SlashDBClient` object is found attached to this object
* @throws {SyntaxError} if `path` parameter is an empty string
* @throws {TypeError} if `path` parameter is neither a string or a `DataDiscoveryFilter` object
*/
_buildEndpointString(path) {
if (! this.sdbClient || ! (this.sdbClient instanceof SlashDBClient)) {
throw ReferenceError(SDB_DDR_NO_CLIENTOBJ);
}
let endpoint = this.dbPrefix + `${this.dbName}/` + this.resourceName;
// if no path is provided, the HTTP operation will act on all resource records
if (!path) {
return this.sdbClient.host + endpoint;
}
// path can be string or DataDiscoveryFilter object
if (typeof(path) === 'string') {
if (path.trim().length < 1) {
throw SyntaxError(SDB_DDR_INVALID_PATH_EMPTY);
}
// prefix the URL path with fwd slash if it's missing
if (Array.from(path)[0] !== '/') {
path =`/${path}`;
}
}
else if ( path instanceof DataDiscoveryFilter) {
path = path.endpoint;
}
else {
throw TypeError(SDB_DDR_INVALID_PATH_TYPE);
}
return this.sdbClient.host + endpoint + path;
}
}
export { DataDiscoveryResource, DataDiscoveryDatabase }