baqend
Version:
Baqend JavaScript SDK
542 lines (535 loc) • 19.5 kB
TypeScript
import { DeviceFactory, Entity, EntityFactory, FileFactory, LoginOption, ManagedFactory, OAuthOptions, UserFactory } from './binding';
import { Class, JsonMap, Lockable } from './util';
import { Connector, Message } from './connector';
import { BloomFilter } from './caching';
import { GeoPoint } from './GeoPoint';
import type { EntityManagerFactory } from './EntityManagerFactory';
import * as model from './model';
import type { Metamodel } from './metamodel';
import { Builder } from './query';
import { Code, Logger, Modules, PushMessage, TokenStorage, ValidationResult } from './intersection';
import { MFAResponse } from './util/Mfa';
export declare class EntityManager extends Lockable {
/**
* Constructor for a new List collection
*/
readonly List: ArrayConstructor;
/**
* Constructor for a new Set collection
*/
readonly Set: SetConstructor;
/**
* Constructor for a new Map collection
*/
readonly Map: MapConstructor;
/**
* Constructor for a new GeoPoint
*/
readonly GeoPoint: typeof GeoPoint;
/**
* Determine whether the entity manager is open.
* true until the entity manager has been closed
*/
get isOpen(): boolean;
/**
* The authentication token if the user is logged in currently
*/
get token(): string | null;
/**
* Whether caching is disabled
* @deprecated
*/
get isCachingDisabled(): boolean;
/**
* Whether caching is enabled
*/
isCachingEnabled(): this is {
bloomFilter: BloomFilter;
cacheWhiteList: Set<string>;
cacheBlackList: Set<string>;
};
/**
* Returns true if the device token is already registered, otherwise false.
*/
get isDeviceRegistered(): boolean;
/**
* The authentication token if the user is logged in currently
* @param value
*/
set token(value: string | null);
/**
* Log messages can created by calling log directly as function, with a specific log level or with the helper
* methods, which a members of the log method.
*
* Logs will be filtered by the client logger and the before they persisted. The default log level is
* 'info' therefore all log messages below the given message aren't persisted.
*
* Examples:
* <pre class="prettyprint">
// default log level ist info
db.log('test message %s', 'my string');
// info: test message my string
// pass a explicit log level as the first argument, one of ('trace', 'debug', 'info', 'warn', 'error')
db.log('warn', 'test message %d', 123);
// warn: test message 123
// debug log level will not be persisted by default, since the default logging level is info
db.log('debug', 'test message %j', {number: 123}, {});
// debug: test message {"number":123}
// data = {}
// One additional json object can be provided, which will be persisted together with the log entry
db.log('info', 'test message %s, %s', 'first', 'second', {number: 123});
// info: test message first, second
// data = {number: 123}
//use the log level helper
db.log.info('test message', 'first', 'second', {number: 123});
// info: test message first second
// data = {number: 123}
//change the default log level to trace, i.e. all log levels will be persisted, note that the log level can be
//additionally configured in the baqend
db.log.level = 'trace';
//trace will be persisted now
db.log.trace('test message', 'first', 'second', {number: 123});
// info: test message first second
// data = {number: 123}
* </pre>
*/
readonly log: Logger;
/**
* The connector used for requests
*/
connection: Connector | null;
/**
* All managed and cached entity instances
* @type Map<String,Entity>
* @private
*/
private entities;
readonly entityManagerFactory: EntityManagerFactory;
readonly metamodel: Metamodel;
readonly code: Code;
readonly modules: Modules;
/**
* The current logged in user object
*/
me: model.User | null;
/**
* The current registered device object
*/
deviceMe: model.Device | null;
/**
* Returns the tokenStorage which will be used to authorize all requests.
*/
tokenStorage: TokenStorage;
/**
* The bloom filter which contains staleness information of cached objects
*/
bloomFilter: BloomFilter | null;
/**
* Set of object ids that were revalidated after the Bloom filter was loaded.
*/
cacheWhiteList: Set<string> | null;
/**
* Set of object ids that were updated but are not yet included in the bloom filter.
* This set essentially implements revalidation by side effect which does not work in Chrome.
*/
cacheBlackList: Set<string> | null;
/**
* Bloom filter refresh interval in seconds.
*/
bloomFilterRefresh: number;
/**
* Bloom filter refresh Promise
*/
readonly bloomFilterLock: Lockable;
/**
* A File factory for file objects.
* The file factory can be called to create new instances for files.
* The created instances implements the {@link File} interface
*/
File: FileFactory;
/**
* the shared connection data if this EntityManager shares the credentials with the EntityManagerFactory
* @private
*/
private connectData;
/**
* @param entityManagerFactory The factory which of this entityManager instance
*/
constructor(entityManagerFactory: EntityManagerFactory);
/**
* Connects this entityManager, used for synchronous and asynchronous initialization
* @param useSharedTokenStorage Indicates if the shared credentials should be used
*/
connected(useSharedTokenStorage?: boolean): void;
/**
* @param types
* @return * @private
*/
private _createObjectFactory;
send(message: Message, ignoreCredentialError?: boolean): Promise<import("./connector").Response>;
/**
* Get an instance whose state may be lazily fetched
*
* If the requested instance does not exist in the database, the
* EntityNotFoundError is thrown when the instance state is first accessed.
* The application should not expect that the instance state will be available upon detachment,
* unless it was accessed by the application while the entity manager was open.
*
* @param entityClass
* @param key
* @return
*/
getReference<T extends Entity>(entityClass: Class<T> | string, key?: string): T;
/**
* Creates an instance of {@link Builder<T>} for query creation and execution
*
* The query results are instances of the resultClass argument.
*
* @param resultClass - the type of the query result
* @return A query builder to create one ore more queries for the specified class
*/
createQueryBuilder<T extends Entity>(resultClass: Class<T>): Builder<T>;
/**
* Clear the persistence context, causing all managed entities to become detached
*
* Changes made to entities that have not been flushed to the database will not be persisted.
*
* @return
*/
clear(): void;
/**
* Close an application-managed entity manager
*
* After the close method has been invoked, all methods on the EntityManager instance
* and any Query and TypedQuery objects obtained from it will throw the IllegalStateError
* and isOpen (which will return false).
*
* @return
*/
close(): void;
/**
* Check if the instance is a managed entity instance belonging to the current persistence context
*
* @param entity - entity instance
* @return boolean indicating if entity is in persistence context
*/
contains(entity: Entity): boolean;
/**
* Check if an object with the id from the given entity is already attached
*
* @param entity - entity instance
* @return boolean indicating if entity with same id is attached
*/
containsById(entity: Entity): boolean;
/**
* Remove the given entity from the persistence context, causing a managed entity to become detached
*
* Unflushed changes made to the entity if any (including removal of the entity),
* will not be synchronized to the database. Entities which previously referenced the detached entity will continue
* to reference it.
*
* @param entity The entity instance to detach.
* @return
*/
detach(entity: Entity): Promise<Entity>;
/**
* Resolve the depth by loading the referenced objects of the given entity
*
* @param entity - entity instance
* @param [options] The load options
* @return
*/
resolveDepth<T extends Entity>(entity: T, options?: {
refresh?: boolean;
local?: boolean;
depth?: number | boolean;
resolved?: Entity[];
}): Promise<T>;
/**
* Search for an entity of the specified oid
*
* If the entity instance is contained in the persistence context, it is returned from there.
*
* @param entityClass - entity class
* @param oid - Object ID
* @param [options] The load options.
* @return the loaded entity or null
*/
load<T extends Entity>(entityClass: Class<T> | string, oid?: string, options?: {
refresh?: boolean;
local?: boolean;
resolved?: Entity[];
}): Promise<T | null>;
/**
* @param entity
* @param options
* @return
*/
insert(entity: Entity, options?: {
depth?: number | boolean;
refresh?: boolean;
}): Promise<Entity>;
/**
* @param entity
* @param options
* @return
*/
update(entity: Entity, options?: {
force?: boolean;
depth?: number | boolean;
refresh?: boolean;
}): Promise<Entity>;
/**
* @param entity
* @param options The save options
* @param withoutLock Set true to save the entity without locking
* @return
*/
save<E extends Entity>(entity: E, options?: {
force?: boolean;
depth?: number | boolean;
refresh?: boolean;
}, withoutLock?: boolean): Promise<E>;
/**
* @param entity
* @param cb pre-safe callback
* @return
*/
optimisticSave<E extends Entity>(entity: E, cb: (entity: E, abort: () => void) => any): Promise<E>;
/**
* @param entity
* @param cb pre-safe callback
* @return
* @private
*/
private _optimisticSave;
/**
* Save the object state without locking
* @param entity
* @param options
* @param msgFactory
* @return
* @private
*/
private _locklessSave;
/**
* Save and lock the object state
* @param entity
* @param options
* @param msgFactory
* @return
* @private
*/
private _save;
/**
* Returns all referenced sub entities for the given depth and root entity
* @param entity
* @param depth
* @param [resolved]
* @param initialEntity
* @return
*/
getSubEntities(entity: Entity, depth?: boolean | number, resolved?: Entity[], initialEntity?: Entity): Entity[];
/**
* Returns all referenced one level sub entities for the given path
* @param entity
* @param path
* @return
*/
getSubEntitiesByPath(entity: Entity, path: string[]): Entity[];
/**
* Delete the entity instance.
* @param entity
* @param options The delete options
* @return
*/
delete<T extends Entity>(entity: T, options?: {
force?: boolean;
depth?: number | boolean;
}): Promise<T>;
/**
* Synchronize the persistence context to the underlying database.
*
* @return
*/
flush(): Promise<any>;
/**
* Make an instance managed and persistent.
* @param entity - entity instance
* @return
*/
persist(entity: Entity): void;
/**
* Refresh the state of the instance from the database, overwriting changes made to the entity, if any.
* @param entity - entity instance
* @param options The refresh options
* @return
*/
refresh<T extends Entity>(entity: T, options: {
depth?: number | boolean;
}): Promise<T | null>;
/**
* Attach the instance to this database context, if it is not already attached
* @param entity The entity to attach
* @return
*/
attach(entity: Entity): void;
private _attach;
removeReference(entity: Entity): void;
register(user: model.User, password: string, loginOption: LoginOption | boolean): Promise<model.User | null>;
login(username: string, password: string, loginOption: LoginOption | boolean): Promise<model.User | null>;
logout(): Promise<void>;
/**
* Starts the MFA initiate process - note you must be logged in, to start the mfa setup process
*
* @returns A promise that resolves to an object with the following properties:
* - qrCode: A Base64 representation of the QR code for MFA setup.
* - keyUri: The URI for the MFA secret key.
* @example
* const { qrCode, keyUri } = await db.initMFA();
* const code = await setupMFADevice(qrCode, keyUri);
* const user = await db.finishMFA(code);
*/
initMFA(): Promise<MFAResponse>;
/**
* Finishes the MFA (Multi-Factor Authentication) initiation process.
*
* @param code - The verification code for MFA.
* @returns A promise that resolves with the user object of the logged-in user.
*/
finishMFA(code: number): Promise<model.User>;
/**
* Submit a verification code after a login
*
* @param code - A 6 digit verification code
* @param token - An MFA token obtained during the login process
* @return The logged-in user object
*/
submitMFACode(code: number, token: string): Promise<model.User>;
/**
* Disables Multi-Factor Authentication for the currently logged in user.
*
* @throws {PersistentError} - Thrown when the user is not logged in.
* @return A promise that resolves when Multi-Factor Authentication is successfully disabled.
*/
disableMFA(): Promise<any>;
/**
* Returns the current MFA status of the user
*
* @returns A promise that resolves to the MFA status of the user.
* Possible values are 'ENABLED' if MFA is enabled, 'DISABLED' if MFA is
* disabled, or 'PENDING' if MFA status is pending.
*/
getMFAStatus(): Promise<'ENABLED' | 'DISABLED' | 'PENDING'>;
loginWithOAuth(provider: string, options: OAuthOptions): any | string | Promise<model.User | null>;
private _loginOAuthDevice;
renew(loginOption?: LoginOption | boolean): Promise<model.User | null>;
newPassword(username: string, password: string, newPassword: string): Promise<model.User>;
newPasswordWithToken(token: string, newPassword: string, loginOption?: LoginOption | boolean): Promise<model.User | null>;
resetPassword(username: string): Promise<import("./connector").Response>;
changeUsername(username: string, newUsername: string, password: string): Promise<import("./connector").Response>;
private _updateUser;
private _logout;
private _userRequest;
/**
* @param deviceType The OS of the device (IOS/Android)
* @param subscription WebPush subscription
* @param device
* @return
*/
registerDevice(deviceType: string, subscription: PushSubscription | {
token: string;
}, device: model.Device | null): Promise<model.Device>;
private _updateDevice;
checkDeviceRegistration(): Promise<boolean>;
pushDevice(pushMessage: PushMessage): Promise<import("./connector").Response>;
/**
* The given entity will be checked by the validation code of the entity type.
*
* @param entity
* @return result
*/
validate(entity: Entity): ValidationResult;
/**
* Adds the given object id to the cacheWhiteList if needed.
* @param objectId The id to add.
* @return
*/
addToWhiteList(objectId: string): void;
/**
* Adds the given object id to the cacheBlackList if needed.
* @param objectId The id to add.
* @return
*/
addToBlackList(objectId: string | null): void;
refreshBloomFilter(): Promise<BloomFilter | null>;
private _updateBloomFilter;
/**
* Checks the freshness of the bloom filter and does a reload if necessary
*/
ensureBloomFilterFreshness(): void;
/**
* Checks for a given id, if revalidation is required, the resource is stale or caching was disabled
* @param id The object id to check
* @return Indicates if the resource must be revalidated
*/
mustRevalidate(id: string): boolean;
/**
* @param id To check the bloom filter
* @param message To attach the headers
* @param refresh To force the reload headers
* @return
*/
ensureCacheHeader(id: string | null, message: Message, refresh?: boolean): void;
/**
* Creates a absolute url for the given relative one
* @param relativePath the relative url
* @param authorize indicates if authorization credentials should be generated and be attached to the url
* @return a absolute url which is optionally signed with a resource token which authenticates the currently
* logged in user
*/
createURL(relativePath: string, authorize?: boolean): Promise<string>;
/**
* Requests a perpetual token for the given user
*
* Only users with the admin role are allowed to request an API token.
*
* @param entityClass
* @param user The user object or id of the user object
* @return
*/
requestAPIToken(entityClass: Class<model.User>, user: model.User | string): Promise<JsonMap>;
/**
* Revoke all created tokens for the given user
*
* This method will revoke all previously issued tokens and the user must login again.
*
* @param entityClass
* @param user The user object or id of the user object
*/
revokeAllTokens(entityClass: Class<model.User>, user: model.User | string): Promise<any>;
executeQuery<T extends Entity>(resultClass: Class<T>, query: string, triggeredBy: string, ttl: string): Promise<any[]>;
private _getUserReference;
}
export interface EntityManager extends Lockable {
[Class: string]: EntityFactory<any> | ManagedFactory<any> | any;
/**
* An User factory for user objects.
* The User factory can be called to create new instances of users or can be used to register/login/logout users.
* The created instances implements the {@link model.User} interface
*/
readonly User: UserFactory;
/**
* An Role factory for role objects.
* The Role factory can be called to create new instances of roles, later on users can be attached to roles to manage
* the access permissions through this role
* The created instances implements the {@link model.Role} interface
*/
readonly Role: EntityFactory<model.Role>;
/**
* An Device factory for user objects.
* The Device factory can be called to create new instances of devices or can be used to register, push to and
* check registration status of devices.
*/
readonly Device: DeviceFactory;
}