@huz-com/tenancy

Manages multi-tenancy data & configuration

Usage no npm install needed!

<script type="module">
  import huzComTenancy from 'https://cdn.skypack.dev/@huz-com/tenancy';
</script>

README

Huz.Com > Component > Tenancy

  • Manages multi-tenancy data & configuration
  • Provides environment based configuration

Standards

  • Language: TS
  • Eslint: Yes
  • Static Code Analysis: Yes IntelliJ Code Inspections
  • DDD - Document Driven: Yes
  • EDD - Exception Driven: Yes
  • TDD - Test Driven: Yes go to test folder
  • Standards Complied: Huz Standards

Commands

  • npm run clear // clears "dist" folder
  • npm run lint // runs eslint for static code analysis
  • npm run test // runs test files in "test" folder
  • npm run build // builds JS files at "dist" folder
  • npm publish or npm run publix // publishes "dist" folder to npm

Install

npm i @huz-com/tenancy

Sample

const {tenant} = require('@huz-com/tenancy');

const data = tenant.cast(req, {}); // read from db, api of file

data.anonymous.hasMultiple; // true

Environment Customization

# .....

redis:
    prefix: HUZ
    host: 10.1.1.1
    port: 6379

# "_env" key special for environment, env data ($._env[environment]) in it will be merged root data
_env:
  prod:
    redis:
        host: 255.1.1.1
  test:
    redis:
        prefix: testing
  stage:
    redis:
        port: 5555
# .....
const {tenant} = require('@huz-com/tenancy');

const prodConfig = tenant.cast(req, {}, 'prod'); // read from db, api of file
console.log(prodConfig.redis); // {prefix: "HUZ", host: "255.1.1.1", port: 6379}

const testConfig = tenant.cast(req, {}, 'test'); // read from db, api of file
console.log(testConfig.redis); // {prefix: "testing", host: "10.1.1.1", port: 6379}

const stageConfig = tenant.cast(req, {}, 'stage'); // read from db, api of file
console.log(stageConfig.redis); // {prefix: "HUZ", host: "10.1.1.1", port: 5555}

const devConfig = tenant.cast(req, {}, 'dev'); // read from db, api of file
console.log(devConfig.redis); // {prefix: "HUZ", host: "10.1.1.1", port: 6379}

Structure

# (dataTenancyComponent.Anonymous) - Anonymous profile config
anonyous:
    enabled: true # (boolean) - anonymous is enabled?
    hasMultiple: true # (boolean) - supports multiple or isolated anonymous?
    duration: 600 # (integer, > 0, second) - temporary subscription duration, if not it should be zero
    warningInterval: 300 # (integer, > 0, second) - temporary subscription interval, for app

# (dataTenancyComponent.Api) - API (Back-End) config
api:
    host: # (string[], host) - host addresses
      - https://sample-domain.com/ # it should be homepage (root routing page) 
    internal: # (string[], alpha) - server names
      - sample-cloud-name

# (dataTenancyComponent.App) - App (Front-End) config
app:
    gtm: your-gtm # (string) - global traffic management 
    publisherId: your-publisher-id # (string) - publisher id
    host: # (string[], host) - host addresses
      - https://sample-domain.com/ # it should be homepage
    internal: # (string[], alpha) - server names
      - sample-cloud-name

# (dataTenancyComponent.Asset) - Asset (File) config
asset:
    selectableAvatars: # (string[], uuid) - media groups for select avatar
      - media-group-entity-uuid # if given, id must be existing in mediaGroupEntity
    defaultOwnerAvatars: # (string[], uuid) - media groups for creating new user, randomly set
      - media-group-entity-uuid # if given, id must be existing in mediaGroupEntity
    defaultAdultAvatars: # (string[], uuid) - media groups for preparing new adult, randomly set
      - media-group-entity-uuid # if given, id must be existing in mediaGroupEntity
    defaultKidAvatars: # (string[], uuid) - media groups for preparing new kid, randomly set
      - media-group-entity-uuid # if given, id must be existing in mediaGroupEntity

# (dataTenancyComponent.Auth) - Auth (Authentication) middleware config
auth:
    onlySingleUser: false # (boolean) - is only for demo user?
    raiseSessionTimeout: true # (boolean) - throws if session absent or timeout?
    raiseProjectConflict: true # (boolean) - throws if project is different between session and base?
    raiseIamConflict: true # (boolean) - throws if iam id is different between jwt and session?
    raiseProfileNotFound: true # (boolean) - throws if profile deleted or not-found?
    raiseProfileDisabled: true # (boolean) - throws if profile deactivated?
    logIpChanged: false # (boolean) - logs if ip address changed between session and agent?
    logCountryChanged: false # (boolean) - logs if country changed between session and agent?
    logTimezoneChanged: false # (boolean) - logs if timezone changed between session and agent?
    logUserAgentChanged: false # (boolean) - logs if user agent changed between session and agent?
    profileLookupInterval: 120 # (integer, > 0, second) - lookup interval for sync db and session

# (dataTenancyComponent.Batch) - Batch config
batch:
    tbd: false # RESERVED, to-be-defined in future

# (dataTenancyComponent.Blacklist) - Blacklist config
blacklist:
    enabled: true # (boolean) - blacklist action is enabled?

# (dataTenancyComponent.Brand) - Brand config
brand:
    enabled: true # (boolean) - brand is enabled?

# (dataTenancyComponent.Category) - Category config
category:
    enabled: true # (boolean) - category is enabled?

# (dataTenancyComponent.Collection) - Collection config
collection:
    enabled: true # (boolean) - collection is enabled?

# (dataTenancyComponent.Contact) - Contact config
contact:
    enabled: true # (boolean) - contact is enabled?
    huz: # (dataTenancyComponent.ContactItem) - to huz config
      prefix: Sample Project # (string, Title) - email subject prefix
      fromName: Huz Contact # (string, Title) - sender full name
      fromEmail: info@huz.com # (string, Email) - sender email address
      emails: # (string[], Email) - receiver's email addresses
        - name@domain.com
    client: # (dataTenancyComponent.ContactItem) - to client/customer/vendor/tenant config
      prefix: Sample Project # (string, Title) - email subject prefix
      fromName: Huz Contact # (string, Title) - sender full name
      fromEmail: info@huz.com # (string, Email) - sender email address
      emails: # (string[], Email) - receiver's email addresses
        - name@domain.com

# (dataTenancyComponent.Country) - Country config
country:
    def: NL # (countryEnum.Id) - default country code
    fromIpAddress: true # (boolean) - find country from ip address?
    criteriaType: banned # (securityTypeEnum.Id) - country security type, banned|allowed|free
    bannedList: # (countryEnum.Id[]) - banned country codes if criteriaType=banned
      - RU
      - CN
    allowedList: # (countryEnum.Id[]) - only allowed country codes if criteriaType=allowed
    viewList: # (countryEnum.Id[]) - viewed country codes (profile can select)
      - NO
      - SE
    manageList: # (countryEnum.Id[]) - managed country codes as manageable (editor can assign)
      - NO
      - SE
      - FI
  
# (dataTenancyComponent.Dictionary) - Dictionary config
dictionary:
    tbd: false # RESERVED, to-be-defined in future

# (dataTenancyComponent.Directive) - Directive config
directive:
    enabled: true # (boolean) - directive is enabled?

# (dataTenancyComponent.Download) - Download config
download:
    enabled: true # (boolean) - download is enabled?

# (dataTenancyComponent.Event) - Event config
event:
    enabled: true # (boolean) - event is enabled?

# (dataTenancyComponent.Exchange) - Exchange config
exchange:
    def: EUR # (exchangeEnum.Id) - default exchange code
    fromCountry: true # (boolean) - find exchange from country?
    viewList: # (exchangeEnum.Id[]) - viewed exchange codes (profile can select)
      - EUR
      - USD
    manageList: # (exchangeEnum.Id[]) - managed exchange codes as manageable (editor can assign)
      - EUR
      - USD
      - TRY

# (dataTenancyComponent.Favorite) - Favorite config
favorite:
    enabled: true # (boolean) - favorite is enabled?

# (dataTenancyComponent.Game) - Game config
game:
    playOnlySubscribed: false # (boolean) - play only when real-subscribed profile?
    ratios: # (dataTenancyComponent.GameRatios)
      play: 1 # (float, > 0) play effective ratio for popular point
      favoriteOk: 0.3 # (float, > 0) favorite effective ratio for popular point
      favoriteNo: 0.1 # (float, > 0) unfavorite effective ratio for popular point

# (dataTenancyComponent.GameStat) - GameStat config
gameState:
    enabled: true # (boolean) - game-stat is enabled? (game statistics for player)
    historical: true # (boolean) - historical data is enabled?
    anonymous: false # (boolean) - can anonymous user send statistics?

# (dataTenancyComponent.Integration) - Various integrations config
integration:
    azerionConnectId: null # (string, Alpha) - azerion connect id
    payByOrbitId: null # (string, Alpha) - azerion payment id

# (dataTenancyComponent.Language) - Language config
language:
    def: en # (languageEnum.Id) - default language code
    fromBrowser: true # (boolean) - find language from browser or user agent?
    viewList: # (languageEnum.Id[]) - viewed language codes (profile can select)
      - no
      - se
      - en
    manageList: # (languageEnum.Id[]) - managed language codes as manageable (editor can assign)
      - no
      - se
      - en
      - it
    replaceMap: # ([languageEnum.Id]: languageEnum.Id) - replace map for language aliases
      nd: no
      nn: no

# (dataTenancyComponent.Media) - Media config
media:
    tbd: false # RESERVED, to-be-defined in future

# (dataTenancyComponent.Middleware) - Middleware config
middleware:
    forwardedAgent: false # (boolean) - will be forwarded ip-address, user-agent and accept-language?

# (dataTenancyComponent.Newsletter) - Newsletter config
newsletter:
    enabled: true # (boolean) - newsletter is enabled?

# (dataTenancyComponent.Notification) - Notification config
notification:
    enabled: true # (boolean) - notification is enabled?
    url: https://sample-domain.com/send/ # notification send endpoint url

# (dataTenancyComponent.Order) - Order config
order:
    enabled: true # (boolean) - order is enabled?
    def: paypall # (orderProviderEnum.Id) - default provider
    providers: # (orderProviderEnum.Id[]) - available providers
      - paypall
      - payu
      - fortimo

# (dataTenancyComponent.Pegi) - Pegi config
pegi:
    enabled: true # (boolean) - pegi is enabled?
    defaultForKid: null # (string, uuid) - default pegi id for kid creation, value should be existing in pegiEntity
    desc: false # (boolean) - order by desc for games?

# (dataTenancyComponent.Plan) - Plan config
plan:
    enabled: true # (boolean) - plan is enabled?

# (dataTenancyComponent.Play) - Play config
play:
    enabled: true # (boolean) - play is enabled?
    logTimeForAnonymous: false # (boolean) - log time for anonymous profile?
    logInterval: 600 # (integer, > 0, second) - log interval or continue interval

# (dataTenancyComponent.Preference) - Preference config
preference:
    enabled: true # (boolean) - preference is enabled?

# (dataTenancyComponent.Profile) - Profile config
profile:
    owner: # (dataTenancyComponent.ProfileOwner)
      defaultName: # ([languageEnum.Id]: string) - owner's default name by language, use * for random number
        en: Guest
        tr: Misafir ****
        no: Gjest
        nl: Gast
        sv: Gäst
      mandatoryPin: false # (boolean) - owner's pin is mandatory?
    adult: # (dataTenancyComponent.ProfileAdult)
      mandatoryPin: false # (boolean) - adult's pin is mandatory?
      maxCount: 10 # (integer, > 0) - max limit for adult (zero for no-limit)
      logout: false # (boolean) - adult can be logged out?
    kid: # (dataTenancyComponent.ProfileKid)
      mandatoryPin: false # (boolean) - kid's pin is mandatory?
      maxCount: 10 # (integer, > 0) - max limit for kid (zero for no-limit)
      logout: false # (boolean) - kid can be logged out?
    themes: # (themeModel.Id[]) - usable themes
      - classic

# (dataTenancyComponent.Redis) - Redis config
redis:
    prefix: null # (string, Alpha) - key prefix for differentiate/group cache values
    host: null # (string, Host) - redis host or ip
    port: 6379 # (integer, > 0) - redis port

# (dataTenancyComponent.Rule) - Rule config
rule:
    tbd: false # RESERVED, to-be-defined in future

# (dataTenancyComponent.Search) - Search config
search:
    enabled: true # (boolean) - search is enabled?
    log: true # (boolean) - search keyword will be logged?
    referral: true # (boolean) - click from search will be tracked?
    startWith: # (dataTenancyComponent.SearchStartWith) - like A*
        order: 1 # (integer) - implementation order, zero for not
        minLength: 1 # (integer) - implement if text size longer than
        point: 0.1 # (float) - effective point, zero for not
    contain: # (dataTenancyComponent.SearchContain) - like A*B
        order: 2 # (integer) - implementation order, zero for not
        minLength: 1 # (integer) - implement if text size longer than
        point: 0.1 # (float) - effective point, zero for not
    trigram: # (dataTenancyComponent.SearchTrigram) - trigram settings
        order: 3 # (integer) - implementation order, zero for not
        minLength: 1 # (integer) - implement if text size longer than
        minRatio: 0.6 # (float, 0-1) text-similarity min threshold between 0 and 1
        point: 0.1 # (float) - effective point, zero for not
    soundex: # (dataTenancyComponent.SearchSoundex) - ;
        order: 4 # (integer) - implementation order, zero for not
        minDigit: 2 # (integer) - implement if soundex size longer than
        point: scalar.Float; // effective point, zero for not
    levenshtein: # (dataTenancyComponent.SearchLevenshtein) - ;
        order: 5 # (integer) - implementation order, zero for not
        minLength: 1 # (integer) - implement if text size longer than
        maxDistance: 10 # (integer) - max replaced letters distance in two texts
        point: 0.1 # (float) - effective point, zero for not
    slugify: # (dataTenancyComponent.SearchSlugify) - ;
        order: 6 # (integer) - implementation order, zero for not
        minLength: 1 # (integer) - implement if text size longer than
        point: 0.1 # (float) - effective point, zero for not
    stemmed: # (dataTenancyComponent.SearchStemmed) - ;
        order: 7 # (integer) - implementation order, zero for not
        minLength: 1 # (integer) - implement if text size longer than
        point: 0.1 # (float) - effective point, zero for not
    metaphone: # (dataTenancyComponent.SearchMetaphone) - ;
        order: 8 # (integer) - implementation order, zero for not
        minLength: 1 # (integer) - implement if text size longer than
        point: 0.1 # (float) - effective point, zero for not
        minDigit: 1 # (integer) - implement if metaphone size longer than
        maxDigit: 2 # (integer) - crop if metaphone size longer than
        useDouble: true # (boolean) - use double metaphone
        useAlternate: true # (boolean) - use alternate metaphone or metaphone-3

# (dataTenancyComponent.Seo) - SEO config
seo:
  sitemap: # (dataTenancyComponent.SeoSitemap[])
    - url: https://sample-domain.com/ # (string, Url) - it should be homepage
      host: # (string[], Host) - ???
      content: # (dataTenancyComponent.SeoSitemapContent[])
        - api: /categories # (string, Folder) - API endpoint folder
          key: category # (string, Alpha) - API entity name
          path: kategori # (string, Folder) - Application folder (visible web folder)

# (dataTenancyComponent.Serie) - Serie config
serie:
    enabled: true # (boolean) - serie is enabled?

# (dataTenancyComponent.Subscription) - Subscription config
subscription:
    provider: azerion-connect # (subscriptionProviderEnum.Id) - provider
    logoutRedirect: false # (boolean) - 
    temporarySubscribed: false # (boolean) - is temporary subscribed?
    subscribedDuration: 0 # (integer, > 0, second) - temporary subscription duration
    warningInterval: 0 # (integer, > 0, second) - temporary subscription interval
    host: # (string[], host) - host addresses
      - https://sample-domain.com/ # it should be homepage (root routing page) 
    internal: # (string[], alpha) - server names
      - sample-cloud-name
    vendorSpecific: # ([string]: unknown)
      - secret1: value1
    sessionKeys: # (string[], Alpha)
      - accessToken
      - redirectUrl

# (dataTenancyComponent.Tag) - Tag config
tag:
    enabled: true # (boolean) - tag is enabled?

# (dataTenancyComponent.Timezone) - Timezone config
timezone:
    def: Etc/UTC # (timezoneEnum.Id) - default timezone code
    fromIpAddress: true # (boolean) - find timezone from ip address?

# (dataTenancyComponent.User) - User config
user:
    iamPrefix: PRJ # (string, Alpha, UpperCase) - prefix for user