oracle-nosqldb
Version:
Node.js driver for Oracle NoSQL Database
460 lines (411 loc) • 13.3 kB
JavaScript
/*
* Copyright (c) 2018, 2024 Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Universal Permissive License v 1.0 as shown at
* https://oss.oracle.com/licenses/upl/
*/
'use strict';
const assert = require('assert');
/**
* Defines enumeration types and constants used by the driver.
*/
/**
* @classdesc Base class for all enumerations used in the driver. All
* enumeration constants are instances of the subclasses of this class.
* Driver defines fixed number of members of each enumeration and seals the
* enumeration class so that new members cannot be created.
* @hideconstructor
*
*/
class Enum {
constructor(ordinal, desc, name) {
//Prevent construction of new objects by the user
assert(!this.constructor._sealed);
if (ordinal != null) {
this._ordinal = ordinal;
} else {
if (this.constructor._ordinalSeq == null) {
this.constructor._ordinalSeq = 0;
}
this._ordinal = this.constructor._ordinalSeq++;
}
this._desc = desc;
this._name = name;
}
/**
* Name of the enumeration constant, usually the same as its symbol name.
* @type {string}
* @readonly
*/
get name() {
return this._name;
}
/**
* Numeric integer value of the enumeration constant.
* @type {number}
* @readonly
*/
get ordinal() {
return this._ordinal;
}
/**
* Optional description of the enumeration constant.
* @type {string}
* @readonly
*/
get description() {
return this._desc;
}
/**
* Returns string representation of enumeration constant. Equivalent to
* <em>name</em> property.
* @returns {string}
*/
toString() {
return this._name;
}
static get values() {
const enumClass = this;
const vals = [];
for(let val of Object.values(enumClass)) {
if (val instanceof enumClass) {
vals.push(val);
}
}
return vals;
}
static get names() {
return this.values.map(val => val.name);
}
static find(predicate) {
const enumClass = this;
for(let val of Object.values(enumClass)) {
if (val instanceof enumClass && predicate(val)) {
return val;
}
}
}
static fromOrdinal(n) {
const enumClass = this;
for(let val of Object.values(enumClass)) {
if (val instanceof enumClass && val.ordinal == n) {
return val;
}
}
throw new RangeError(
`Ordinal ${n} is not valid for ${enumClass.name} enumeration`);
}
static seal() {
const enumClass = this;
for(let [key, val] of Object.entries(enumClass)) {
if (val instanceof enumClass) {
if (!val._name) { //Assign name if was not specified
val._name = key;
}
Object.freeze(val);
}
}
enumClass._sealed = true;
Object.freeze(enumClass);
}
}
/**
* Service type is specified in the initial configuration used to create
* {@link NoSQLClient} instance and indicates what kind of service the
* driver will be using. Currently supported values are
* {@link ServiceType.CLOUDSIM}, {@link ServiceType.CLOUD} and
* {@link ServiceType.KVSTORE}. In addition to {@link ServiceType}
* enumeration, these values may be specified as strings "CLOUDSIM", "CLOUD"
* or "KVSTORE", case-insensitive. This is useful if using JSON configuration
* file. If {@link ServiceType} is not present in the initial configuration,
* the driver will try to deduce service type from the
* information provided in authorization property {@link Config}#auth (see
* {@link AuthConfig}) in the following way:
* <ul>
* <li>If {@link Config}#auth is undefined or null, the service type is
* determined as follows: if {@link Config}#region is specified, the service
* type defaults to {@link ServiceType.CLOUD}, otherwise it defaults to
* {@link ServiceType.CLOUDSIM}
* <li>If {@link Config}#auth contains <em>iam</em> property, the service
* type is assumed to be {@link ServiceType.CLOUD}</li>
* <li>If {@link Config}#auth constains <em>kvstore</em> property, the service
* type is assumed to be {@link ServiceType.KVSTORE}. Note that unless
* {@link Config}#serviceType is explicitly specified, you may not specify
* both <em>iam</em> and <em>kvstore</em> properties in {@link AuthConfig}
* at the same time. You may specify value <em>{}</em> (empty object) for
* <em>kvstore</em> property to connect to non-secure kvstore, although it is
* advisable to specify the service type explicitly in this case. See
* {@link ServiceType.KVSTORE}</li>
* <li>If {@link Config}#auth does not contain either of the above properties,
* the driver will check if it contains user-specified
* {@link AuthorizationProvider} ({@link AuthConfig}#provider). In this case
* the service type will remain undefined and user-specified provider will be
* used to control access to the service. If there is no user-specified
* {@link AuthorizationProvider} in {@link Config}#auth, this is equivalent to
* {@link Config}#auth not defined and the service type will default to
* {@link ServiceType.CLOUD} or {@link ServiceType.CLOUDSIM} as described
* above</li>
* </ul>
*
* @extends Enum
* @hideconstructor
*
* @see {@link AuthConfig}
* @see {@link AuthorizationProvider}
*/
class ServiceType extends Enum {}
/**
* Cloud Simulator, no authorization used.
* @tutorial connect-cloud
*/
ServiceType.CLOUDSIM = new ServiceType(0);
/**
* Oracle NoSQL Cloud Service. Authorization is managed by IAM.
* @see {@link IAMConfig}
* @tutorial connect-cloud
*/
ServiceType.CLOUD = new ServiceType(1);
/**
* On Premise Oracle NoSQL Database. This includes both secure and non-secure
* stores. For secure store, authentication information must be provided in
* {@link AuthConfig}#kvstore as {@link KVStoreAuthConfig}. For non-secure
* store, it is enough to specify {@link Config}#serviceType to be
* {@link ServiceType.KVSTORE} without having {@link AuthConfig}#kvstore
* property.
* @see {@link KVStoreAuthConfig}
* @tutorial connect-on-prem
*/
ServiceType.KVSTORE = new ServiceType(2);
/**
* @ignore
*/
ServiceType.MINICLOUD = new ServiceType(3); //internal use only
ServiceType.MINICLOUD._isInternal = true;
/**
* @ignore
*/
ServiceType.DEVPOD = new ServiceType(3); //internal use only
ServiceType.DEVPOD._isInternal = true;
ServiceType.seal();
/**
* Consistency is used to provide consistency guarantees for read operations.
* <p>
* {@link Consistency.ABSOLUTE} consistency may be specified to guarantee that
* current values are read. {@link Consistency.EVENTUAL} consistency means
* that the values read may be very slightly out of date.
* {@link Consistency.ABSOLUTE} consistency results in higher cost, consuming
* twice the number of read units for the same data relative to
* {@link Consistency.EVENTUAL} consistency, and should only be used when
* required.
* </p>
* <p>
* It is possible to set a default Consistency for a {@link NoSQLClient}
* instance by providing it in the initial configuration as
* {@link Config}#consistency. In JSON configuration file, you may use string
* values such as "EVENTUAL" or "ABSOLUTE". If no consistency is specified
* for an operation and there is no default value,
* {@link Consistency.EVENTUAL} is used.
* </p>
* <p>
* Consistency can be specified in the options(<em>opt</em>) argument for all
* read operations.
* </p>
* @extends Enum
* @hideconstructor
*/
class Consistency extends Enum {}
/**
* Absolute consistency
* @type {Consistency}
*/
Consistency.ABSOLUTE = new Consistency(0);
/**
* Eventual consistency
* @type {Consistency}
*/
Consistency.EVENTUAL = new Consistency(1);
Consistency.seal();
/**
* CapacityMode specifies the type of capacity that will be set on a table. It is
* used in table creation and table capacity updates. See {@link TableLimits}.
* <p>
* Table capacity is only used in the NoSQL Cloud Service.
* </p>
* <p>
* {@link CapacityMode.PROVISIONED} is the default mode. In this mode, the
* application defines the specified maximum read and write throughput for
* a table.
* {@link CapacityMode.ON_DEMAND} mode allows for flexible throughput usage.
* In this mode, only the maximum storage size is specified.
* </p>
* @extends Enum
* @hideconstructor
*/
class CapacityMode extends Enum {}
/**
* Provisioned mode. This is the default.
* @type {CapacityMode}
* @since 5.3.0
*/
CapacityMode.PROVISIONED = new CapacityMode(1);
/**
* On Demand mode.
* @type {CapacityMode}
* @since 5.3.0
*/
CapacityMode.ON_DEMAND = new CapacityMode(2);
CapacityMode.seal();
//Not currently used by the driver.
/** @ignore */
class ScanDirection extends Enum {}
ScanDirection.UNORDERED = new ScanDirection(0);
ScanDirection.FORWARD = new ScanDirection(1);
ScanDirection.REVERSE = new ScanDirection(2);
ScanDirection.seal();
/**
* Describes the current state of the table. See
* {@link NoSQLClient#tableDDL}.
* @extends Enum
* @hideconstructor
*/
class TableState extends Enum {}
/**
* The table is ready to be used. This is the steady state after creation or
* modification.
* @type TableState
*/
TableState.ACTIVE = new TableState(0);
/**
* The table is being created and cannot yet be used.
* @type TableState
*/
TableState.CREATING = new TableState(1);
/**
* The table has been dropped or does not exist.
* @type TableState
*/
TableState.DROPPED = new TableState(2);
/**
* The table is being dropped and cannot be used.
* @type TableState
*/
TableState.DROPPING = new TableState(3);
/**
* The table is being updated. It is available for normal use, but additional
* table modification operations are not permitted while the table is in this
* state.
* @type TableState
*/
TableState.UPDATING = new TableState(4);
TableState.seal();
/**
* On premise only.
* <p>
* Describes the current state of the operation performed by
* {@link NoSQLClient#adminDDL}.
* @extends Enum
* @hideconstructor
*/
class AdminState extends Enum {}
/**
* Operation is complete and successful.
* @type AdminState
*/
AdminState.COMPLETE = new AdminState(0);
/**
* Operation is in progress.
* @type AdminState
*/
AdminState.IN_PROGRESS = new AdminState(1);
AdminState.seal();
/**
* For now this is internal, but we may expose this enumeration
* when we implement custom type mappings.
* @ignore
*/
class DBType extends Enum {}
DBType.ARRAY = new DBType(0);
DBType.BINARY = new DBType(1);
DBType.BOOLEAN = new DBType(2);
DBType.DOUBLE = new DBType(3);
DBType.INTEGER = new DBType(4);
DBType.LONG = new DBType(5);
DBType.MAP = new DBType(6);
DBType.STRING = new DBType(7);
DBType.TIMESTAMP = new DBType(8);
DBType.NUMBER = new DBType(9);
DBType.JSON_NULL = new DBType(10);
DBType.NULL = new DBType(11);
DBType.EMPTY = new DBType(12);
DBType.seal();
//Only used internally. Not clear if some limits (in particular request
//sizes) are specific to binary protocol. If so, they could be moved there.
const Limits = {
REQUEST_SIZE: 2 * 1024 * 1024,
BATCH_REQUEST_SIZE: 25 * 1024 * 1024,
BATCH_OP_NUMBER: 50,
READ_KB: 2 * 1024,
WRITE_KB: 2 * 1024,
//Maximum timeout for single http request accepted by the proxy
MAX_REQUEST_TIMEOUT: 30000
};
//Only used internally by advanced query, should not show up in the results.
const EMPTY_VALUE = Symbol('EMPTY');
//HTTP-related constants, only used internally
const HttpConstants = {
POST: 'POST',
GET: 'GET',
DELETE: 'DELETE',
PUT: 'PUT',
CONTENT_TYPE: 'Content-Type',
CONTENT_TYPE_LWR: 'content-type',
APPLICATION_JSON: 'application/json',
CONNECTION: 'Connection',
ACCEPT: 'Accept',
AUTHORIZATION: 'Authorization',
CONTENT_LENGTH: 'Content-Length',
CONTENT_LENGTH_LWR: 'content-length',
USER_AGENT: 'User-Agent',
CACHE_CONTROL: 'cache-control',
COOKIE: 'cookie',
SET_COOKIE: 'set-cookie',
HOST: 'host',
DATE: 'date',
X_DATE: 'x-date',
REQUEST_ID: 'x-nosql-request-id',
OPC_REQUEST_ID: 'opc-request-id',
DATA_PATH_NAME: 'data',
NOSQL_VERSION: 'V2',
NOSQL_PATH_NAME: 'nosql',
COMPARTMENT_ID: 'x-nosql-compartment-id',
NAMESPACE: 'x-nosql-default-ns',
REQUEST_TARGET: '(request-target)',
CONTENT_SHA256: 'x-content-sha256',
HTTP_OK: 200,
HTTP_BAD_REQUEST: 400,
HTTP_UNAUTHORIZED: 401,
HTTP_NOT_FOUND: 404,
HTTP_CONFLICT: 409,
HTTP_SERVER_ERROR: 500,
HTTP_UNAVAILABLE: 503
};
HttpConstants.NOSQL_PREFIX = HttpConstants.NOSQL_VERSION + '/' +
HttpConstants.NOSQL_PATH_NAME;
HttpConstants.NOSQL_DATA_PATH = HttpConstants.NOSQL_PREFIX + '/' +
HttpConstants.DATA_PATH_NAME;
const PACKAGE_VERSION = require('../package.json').version;
delete require.cache[require.resolve('../package.json')];
module.exports = {
Enum,
ServiceType,
Consistency,
CapacityMode,
ScanDirection,
TableState,
AdminState,
DBType,
Limits,
EMPTY_VALUE,
HttpConstants,
PACKAGE_VERSION
};