Singleton instance of UnityBase application. Allow direct access to the database connections, blob stores, HTTP endpoints (full control on HTTP request & response) registration, read domain and server config.
Mixes EventEmitter, and emit:
launchEndpoint:before
with parameters: (req, resp, endpointName)endpointName + ':before'
event before endpoint handler executionendpointName + ':after'
event in case neither exception is raised nor App.preventDefault()launchEndpoint:after
with parameters: (req, resp, endpointName, defaultPrevented)
To prevent endpoint handler execution App.preventDefault() can be used inside :before
handler.
const App = require('@unitybase/ub').App
// Register public (accessible without authentication) endpoint
App.registerEndpoint('echoToFile', echoToFile, false)
// write custom request body to file FIXTURES/req and echo file back to client
// @param {THTTPRequest} req
// @param {THTTPResponse} resp
function echoToFile (req, resp) {
var fs = require('fs')
fs.writeFileSync(path.join(FIXTURES, 'req'), req.read('bin'))
resp.statusCode = 200
resp.writeEnd(fs.readFileSync(path.join(FIXTURES, 'req'), {encoding: 'bin'}))
}
//Before getDocument requests
//@param {THTTPRequest} req
//@param {THTTPResponse} resp
function doSomethingBeforeGetDocumentCall(req, resp){
console.log('User with ID', Session.userID, 'try to get document')
}
// Adds hook called before each call to getDocument endpoint
App.on('getDocument:before', doSomethingBeforeGetDocumentCall)
//
//After getDocument requests
//@param {THTTPRequest} req
//@param {THTTPResponse} resp
function doSomethingAfterGetDocumentCall(req, resp){
params = req.parsedParameters
console.log('User with ID', Session.userID, 'obtain document using params', params)
}
App.on('getDocument:after', doSomethingAfterGetDocumentCall)
# new App ()
Members
# blobStores static
BLOB stores methods. For usage examples see:
- App.blobStores.getContent - load content of BLOB into memory
- App.blobStores.getContentPath - get a path to the file based store BLOB content
- App.blobStores.putContent - put a BLOB content to the temporary storage
- App.blobStores.markRevisionAsPermanent - mark specified revision of a historical store as permanent
- App.blobStores.internalWriteDocumentToResp - mark specified revision of a historical store as permanent
# dbConnections : Object.<string, DBConnection> static
Databases connections pool
# defaultLang : String static
Application default language
# domainInfo : UBDomain static
Extended information about application domain (metadata)
# emitterEnabled : Boolean deprecated static
Is event emitter enabled for App singleton. Default is false
Starting from 1.11 this property ignored (always TRUE)
# endpointContext : Object static
Endpoint context. Application logic can store here some data what required during single HTTP method call;
Starting from UB@5.17.9 server reset App.endpointContext
to {} after endpoint implementation execution,
so in the beginning of execution it's always empty
App.endpointContext.MYMODEL_mykey = 'some value we need to share between different methods during a single user request handling'
# externalURL : String static
URL that the User from the internet will use to access your server. To be used in case server is behind a reverse proxy
# localIPs static
List of a local server IP addresses CRLF (or CR for non-windows) separated
# package : Object static
Application package.json
content (parsed)
# serverConfig : Object static
Server configuration - result of argv.getServerConfiguration
Name | Type | Description |
---|---|---|
httpServer | Object | HTTP server config |
application | Object | |
application.name | string | |
application.defaultLang | string | |
application.domain | Object | |
application.domain.models | Array | |
application.domain.supportedLanguages | Array.<string> | |
application.customSettings | Object | |
uiSettings | Object | Section |
security | Object |
# serverPublicCert : string static
Defense edition only, Base64 encoded public server certificate
Contains non empty value in case security.dstu.trafficEncryption
=== true
and
key name defined in security.dstu.novaLib.keyName
# serverURL : String static
Full URl HTTP server is listen on (if HTTP server enabled, else - empty string)
# staticPath : String static
Full path to application static folder if any, '' if static folder not set
Methods
# addAppLevelMethod () static deprecated
Use App.registerEndpoint instead
# authFromRequest (noHTTPBodyInResp: boolean, doSetOutCookie: boolean) → Boolean static
Try retrieve or create new session from request headers.
Return true
if success, false
if more auth handshakes is required.
In case of invalid credential throw security exception
# dbCommit (connectionNameopt: String) → Boolean static
Commit active database transaction if any.
In case connectionName
is not passed will commit all active transactions for all connections.
Return true
if transaction is committed, or false
if database not in use or no active transaction.
Arguments:
connectionName
: String
# dbInTransaction (connectionName: String) → Boolean static
Check database are used in current endpoint context and DB transaction is already active.
Arguments:
connectionName
: String
# dbRollback (connectionNameopt: String) → Boolean static
Rollback active database transaction if any.
In case connectionName
is not passed will rollback all active transactions for all connections.
Return true
if transaction is rollback'ed, or false
if database not in use or no active transaction.
Arguments:
connectionName
: String
# dbStartTransaction (connectionName: String) → Boolean static
Start a transaction for a specified database. If database is not used in this context will create a connection to the database and start transaction.
For Oracle with DBLink first statement to DBLink'ed table must be either update/insert/delete or you MUST manually start transaction to prevent "ORA-01453: SET TRANSACTION be first statement"
Arguments:
connectionName
: String
# deleteFromFTSIndex (entityName: String, instanceID: Number) static
Delete row from FTS index for exemplar with instanceID
of entity entityName
(mixin fts
must be enabled for entity)
# els (entityCode: String, methodCode: String) → boolean static
Check Entity-Level-Security for specified entity/method
if App.els('uba_user', 'insert'){
// do something
}
# enterCriticalSection (csIndex: number) static
Waits for ownership of the specified critical section object. The function returns when the calling thread is granted ownership.
** IMPORTANT** A thread must call App.leaveCriticalSection
once for each time that it entered the critical section.
Arguments:
csIndex
: numberA critical section index returned by
App.registerCriticalSection
# getUISettings () → string static deprecated
Use App.serverConfig.uiSettings: Object instead
Return stringified JSON specified in serverConfig.uiSettings
# globalCacheGet (key: String) → String static
Get value from global cache. Global cache shared between all threads.
Return '' (empty string) in case key not present in cache.
Arguments:
key
: StringKey to retrive
# globalCachePut (key: String, value: String) static
Put value to global cache.
# grantEndpointToRole (endpointName: String, roleCode: String) → boolean static
Grant endpoint to role
Return:
true if endpoint exists and role not already granted, false otherwise
# leaveCriticalSection (csIndex: number) static
Releases ownership of the specified critical section
Arguments:
csIndex
: number
# logEnter (methodName: string) static
Enter a log recursion call.
** IMPORTANT** A thread must call App.logLeave
once for each time that it entered the log recursion
Arguments:
methodName
: string
function wrapEnterLeave(enterText, originalMethod) {
return function(ctx) {
App.logEnter(enterText)
try {
originalMethod(ctx)
} finally {
App.logLeave()
}
}
}
# logLeave () static
Exit a log recursion call
# logout () static
Logout a current user (kill current session)
# logoutAllWithTheSameNameExceptMe () static
Logout all users with the same name as current user, except currently logged user
# preventDefault () static
Accessible inside app-level :before
event handler. Call to prevent default method handler.
In this case developer are responsible to fill response object, otherwise HTTP 400 is returned.
# registerCriticalSection (csName: string) → number static
Register a named critical section. Can be done only in initialization mode. In case section with the same name already registered in another thread - returns existed CS index
All threads MUST register section in the same way, do not put call into condition what may evaluates too the different values in the different threads.
Arguments:
csName
: stringCritical section name
const App = require('@unitybase/ub').App
// critical section must be registered once in the moment modules are evaluated without any conditions
const MY_CS = App.registerCriticalSection('SHARED_FILE_ACCESS')
function concurrentFileAccess() {
// prevents mutual access to the same file from the different threads
App.enterCriticalSection(FSSTORAGE_CS)
try {
const data = fs.readfileSync('/tmp/concurrent.txt', 'utf8')
// do some operation what modify data
fs.writefileSync('/tmp/concurrent.txt', data)
} finally {
// important to leave critical section in finally block to prevent forever lock
App.leaveCriticalSection(FSSTORAGE_CS)
}
}
# registerEndpoint (endpointName: String, handler: function, authorizationRequiredopt: boolean, isDefaultopt: boolean) static
Register a server endpoint. One of the endpoints can be default endpoint - it will be used as a fallback in case URL do not start with any of known endpoints name.
Exceptions inside endpoint handler are intercepted by UB server. In case exception is occurred server will rollback any active DB transactions and serialize an exception message to response depending on server execution mode:
- for
dev
mode - original exception text will be serialized (for debugging purpose) - for production mode - in case exception message is wrapped into
<<<..>>>
then this message will be serialized, if not - text will be alwaysInternal server error
(for security reason)
Recommended way to throw an handled error inside endpoint handler is throw new UB.UBAbort('.....')
Arguments:
// Write a custom request body to file FIXTURES/req and echo file back to client
// @param {THTTPRequest} req
// @param {THTTPResponse} resp
//
function echoToFile(req, resp) {
var fs = require('fs');
fs.writeFileSync(FIXTURES + 'req', req.read('bin'));
resp.statusCode = 200;
resp.writeEnd(fs.readFileSync(FIXTURES + 'req', {encoding: 'bin'}));
}
App.registerEndpoint('echoToFile', echoToFile);
# removeUserSessions (userID: number) → boolean static
Remove all user sessions (logout user).
Return:
true if user had had any session
Arguments:
userID
: number
# serviceMethodByPassAuthentication () static deprecated
Use App.registerEndpoint instead
# updateFTSIndex (entityName: String, instanceID: Number) static
Update FTS index for for exemplar with instanceID
of entity entityName
(mixin fts
must be enabled for entity).
In case row dose not exist in FTS perform insert action automatically.