JavaScript Style Guide

This model is a main entry point for a UnityBase server application.

Application

In terms of UnityBase application is defined by:

  • configuration (ubConfig.json by default): file what describe settings for http server, logging, authorization methods, Domain, etc. See server config json schema for full description;
  • package.json - npm/yarn configuration used to give information to package manager that allows it to identify the project as well as handle the project's dependencies

Inside package.json the main field is a primary entry point of UnityBase application. In most case entry point file content is:

const UB = require('@unitybase/ub')
UB.start()

Application initialization

once on server startup (single thread mode, http server do not accent connections)

This stage is added in UB@5.18.0 to allow custom Domain transformation before any other steps is performed.

Just after UB starts in server mode it creates a single-thread JavaScript runtime and use a @unitybase/ub/metadataTransformation.js script as an entry point for Domain loading. Script loads all *.meta and *.meta.lang files into memory, merge files with the same names and calls a _hookMetadataTransformation.js hook from models folders (if available) with two parameters (domainJSON, serverConfig)

Metadata transformation hook can mutate a Domain JSON, for example - adds additional attributes to the entities and lang files, etc

Files are merged and hooks are called in order models appears in application.domain.models server config section.

After all hooks are called resulting domainJSON is passed back to UB to initialize a Domain classes.

UB server:

  • initialize internal Domain
  • evaluate an application entry-point script (see UB.js below)
  • initialize ELS (since all models scripts is evaluated on this point all entity-level methods and endpoints are in Domain, so server can build an access matrix for methods and roles)

UB server switches to multi-thread mode and can accept HTTP requests

JS working thread (multi-thread mode)

In multi-thread mode UB uses a thread pool of size threadPoolSize from ubConfig. Threads in pool are created lazy - in case there is no free thread to accept an incoming request new thread is spawned until thread poll is not full.

Every new working thread use UB.js as entry point.

UB.js script content is embedded into executable, but it sources is also available in @unitybase/stubs/UB.js. The task of UB.js script is to require and run an application entry point script (main from package.json).

As described above entry point script will execute a UB.start() and

UB.start method of @unitybase/ub package will perform a steps below (actually for every working thread): - for each model from application.domain.models folders (except ones marked as _public_only_) load a model (see below) - register build-in UnityBase endpoints - emit App.domainIsLoaded event

Model

Server-side

Model is a commonJS module with logically grouped set of entities + server side code + client-side code. In the application config (ubConfig.json) application.domain.models section contains an array of models, required by application.

Model is loaded in server thread memory(in order they defined in application.domain.models config section) in three steps:

  • entity (global objects) are created for all *.meta files from this model
  • require is called for all *.js files paired with *.meta
  • require is called for model entry point defined in package.json placed in the model folder

Model package.json can contain engines.ub section - a minimal version of UB server for this model. Starting from UB@5.22.15 server throws if it's version is less than specified in engine.ub. The only supported semantic is >=. Example:

{
  "name": "@unitybase/uba",
  "engines": {
    "ub": ">=5.22.15"
  }
}

To simplify a ubConfig model package.json can contain config.ubmodel section what describe the model name and (optionally) ``"isPublic": true` for "browser-only" model

"config": {
    "ubmodel": {
      "name": "UBS"
    }
  },

for "browser-only" model:

  "config": {
    "ubmodel": {
      "name": "adminui-pub",
      "isPublic": true
    }
  },

For such models only path to model should be added to the application.domain.models section of ubConfig.json:

	"application": {
        ...
		"domain": {
			"models": [
			    ...
				{
					"path": "./node_modules/@unitybase/ubs"
				},

Client-side (adminUI)

Model can contain a "browser-side" part. In this case model package.json should contains browser section what point to the model initialization script for browser:

  • In case model is a published module (placed in the node_modules folder) path should be relative to the package.json:
"browser": "./public/initModel.js"
  • or for dev/prod scripts
 "browser": {
   "dev": "./public/devEntryPoint.js"
   "prod": "./public/dist/modelBundle.js"
 }
  • In case model is in models folder p[ath must be absolute
  "browser": "/clientRequire/models/TST/initModel.js",

Endpoints

UnityBase comes with simple one-level routing. App.registerEndpoint method will add a handlers functions for a first level of routing:

const fs = require('fs')
/**
 * 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) {
   fs.writeFileSync(FIXTURES + 'req', req.read('bin'))
   resp.statusCode = 200
   resp.writeEnd(fs.readFileSync(FIXTURES + 'req', {encoding: 'bin'}))
}
App.registerEndpoint('echoToFile', echoToFile)

More deep routing can be implemented inside the endpoint handler, as we did inside build-in UnityBase endpoints

JSON schemas

@unitybase/ub/public/schemas folder contains JSON schemas for server config, entity meta file and scheduler config. It's a good idea to configure your IDE for JSON schema support. See WebStorm IDE configuratuion manual

Classes

Submodules

Members

# App static

Application instance

Name Type Description
App ServerApp

# ESecurityException static

Server-side Security exception. Throwing of such exception will trigger Session.securityViolation event

Name Type Description
ESecurityException ESecurityException

# i18nExtend static

Merge localizationObject to UB.i18n

  
      const UB = require('@unitybase/ub')
UB.i18nExtend({
 "en": {yourMessage: "yourTranslationToEng", ...},
 "uk": {yourMessage: "yourTranslationToUk", ...},
  ....
})
// if logged-in user language is `en` will output "yourTranslationToEng"
console.log(UB.i18n(yourMessage))
// will output "yourTranslationToUk"
console.log(UB.i18n(yourMessage, 'uk'))
  

# isServer static

If we are in UnityBase server scripting (both -f or server thread) this property is true, if in browser - undefined or false. Use it for check execution context in scripts, shared between client & server. To check we are in server thread use process.isServer

# loadLegacyModules static

For UB < 4.2 compatibility - require all non - entity js in specified folder add its sub-folder (one level depth), exclude modules and node_modules sub-folder's. From 'public' sub-folder only cs*.js are required. To be called in model index.js as such:

const UB = require('@unitybase/ub') UB.loadLegacyModules(__dirname)

For new models we recommend to require non-entity modules manually

# ns deprecated static

Creates namespaces to be used for scoping variables and classes so that they are not global.

Try to avoid namespaces - instead create a module and use require()

  
      UB.ns('DOC.Report');
DOC.Report.myReport = function() { ... };
  

# registerMixinModule static

A way to add additional mixins into domain

# Session static

Information about the logged-in user

Name Type Description
Session Session

Methods

# DataStore (entityCodestring) → TubDataStore static

Construct new data store

Arguments:

# i18n (msgstring, args*) → * static

Return locale-specific resource from it identifier. Resources are defined by UB.i18nExtend

In case firs element of args is a string with locale code supported by application then translate to specified locale, in other case - to locale of the current user (user who done the request to the server)

Localized string can be optionally formatted by position args

Arguments:
  • msg: string

    Message to translate

  • args: *

    Format args

  
      UB.i18nExtend({
  en: { greeting: 'Hello {0}, welcome to {1}' },
  uk: { greeting: 'Привіт {0}, ласкаво просимо до {1}' }
})
UB.i18n('greeting', 'Mark', 'Kiev') // in case current user language is en -> "Hello Mark, welcome to Kiev"
UB.i18n('greeting', 'uk', 'Mark', 'Kiev') // in case ru lang is supported -> "Привіт Mark, ласкаво просимо до Kiev"
  

# Repository (entityNamestring, cfgoptobject, connectionoptSyncConnection) → ServerRepository static

Create new instance of ServerRepository

Arguments:

# initializeDomain () inner

# normalizeEnums () inner

# ns (namespacePath) → object inner

Arguments:
  • namespacePath:

# start () inner

Initialize UnityBase application:

  • create namespaces (global objects) for all *.meta files from domain
  • require all packages specified in config application.domain.models
  • apply a server-side i18n JSONs from models serverLocale folder
  • emit App.domainIsLoaded event
  • initialize BLOB stores
  • emit App.applicationReady event
  • register build-in UnityBase endpoints

# UBAbort (messageoptstring, argsany) inner

Server-side Abort exception. To be used in server-side logic in case of HANDLED exception. These errors logged using "Error" log level to prevent unnecessary EXC log entries

Arguments:
  
      // UB client will show message inside <<<>>> to user (and translate it using UB.i18n)
const UB = require('@unitybase/ub')
throw new UB.UBAbort('<<<textToDisplayForClient>>>')
// In case, client-side message shall be formatted:
throw new UB.UBAbort('<<<file_not_found>>>', 'bad_file.name')
// The "file_not_found" i18n string on client should be like `'File "{0}" is not found or not accessible'
// Format args can be translated by assing a :i18n modifier to template string: `'File "{0:i18n}" is not found or not accessible'
// In case message should not be shown to the end used by ub-pub globalExceptionHandler `<<<>>>` can be omitted
throw new UB.UBAbort('wrongParameters')
  

Types

# ubBlobHistoryAttrs inner

Properties

# ubMigrationAttrs inner

Properties

# ubVersionAttrs inner

Properties

  • ID number
  • modelName string

    Model

  • version string

    Version

  • appliedAt Date

    Applied at

  • initialVersion string

    Initial Version

  • initializedAt Date

    Initialized At