BBC's guide to development
  • General

    • About
    • Tools
    • Git(hub)
    • Showpad
    • Hosting
    • Maintenance
    • Security
    • Go live checklist
  • Front-end development

    • Bundlers
    • CSS/SCSS
    • Javascript
    • Vue
    • PHP
    • Mails
    • Dev Faq
  • Functions
  • Mixins
  • General

    • OOP Structure
  • Component Classes

    • Accordion
    • App
    • Component
    • HighwayApp
    • Popup
    • PNG Sequencer
    • Tab
  • Manager Classes

    • BountListenerMgr
    • Cache
    • Configuration
    • InViewStateMgr
    • Instance Manager
    • Event dispatcher
  • Factories

    • SwiperFactory
  • PDF

    • AssetLoader
    • BasePdfDoc
    • TemplatePdfDoc
    • CustomPdfDoc
  • Utility functions

    • canvas
    • Connection Status
    • css
    • dev
    • placeholder
    • dom
    • fetch
    • json
    • object
    • scroll
    • scrollbar
    • spreadsheets
    • string
    • url
  • General

    • ComponentMgr
    • ThreeJsViewer
  • Components

    • ComponentMgr
    • GltfModel
    • Snappable
    • Socket
    • ThreeJsViewer
    • ThreeJsViewerCamera
  • Loaders

    • ConfigurationSerializer
    • GltfBlockParser
  • Utils

    • CanvasInputAdapter
    • CollisionManager
    • SocketGridExpander
    • blender
    • headless
  • General

    • Troubleshooting
    • Legacy
  • Components

    • AssetBar
    • ConfigGenerator
    • ShowpadApp
  • Managers

    • Assets
    • AppsDb
    • Config
  • Utils

    • Connection Status
    • general
    • showpad-interactive
    • showpad-upload
  • Components

    • Accordion
    • BackButton
    • Breadcrumb
    • ByltButton
    • Hamburger
    • Icon
    • Logo
    • Loader
    • Modal
    • Popup
    • Prompt
    • ProgressBar
    • TextLoader
  • Composables

    • useDebugMode
    • useConnectionStatus
  • Utils

    • dom
    • props
  • General

    • General
    • Tracking
  • Components

    • Accordion
    • ActionButton
    • AssetItem
    • AssetList
    • BackButton
    • ConfigGenButton
    • Logo
    • Media
    • Modal
    • Popup
    • Prompt
    • SPButton
    • SPRouterView
    • SPTrackedRouterLink
    • TextLoader
    • View
  • Composables

    • useConnectionStatus
  • Stores

    • useAppsDbStore
    • useBreadcrumbStore
    • useShowpadAPIStore
    • useShowpadSDKStore
    • useSpConfigStore
    • useSpStore
    • useSpTrackingStore
  • The New Kit

    • General
    • Installation & Usage
    • ACF Blocks
    • PHPCS
    • Functions
    • Vite
    • WP Config
    • Staging Deployment
  • Best Practices

    • Page Structure
    • Fonts/Typography
  • Todo
GitHub
  • General

    • About
    • Tools
    • Git(hub)
    • Showpad
    • Hosting
    • Maintenance
    • Security
    • Go live checklist
  • Front-end development

    • Bundlers
    • CSS/SCSS
    • Javascript
    • Vue
    • PHP
    • Mails
    • Dev Faq
  • Functions
  • Mixins
  • General

    • OOP Structure
  • Component Classes

    • Accordion
    • App
    • Component
    • HighwayApp
    • Popup
    • PNG Sequencer
    • Tab
  • Manager Classes

    • BountListenerMgr
    • Cache
    • Configuration
    • InViewStateMgr
    • Instance Manager
    • Event dispatcher
  • Factories

    • SwiperFactory
  • PDF

    • AssetLoader
    • BasePdfDoc
    • TemplatePdfDoc
    • CustomPdfDoc
  • Utility functions

    • canvas
    • Connection Status
    • css
    • dev
    • placeholder
    • dom
    • fetch
    • json
    • object
    • scroll
    • scrollbar
    • spreadsheets
    • string
    • url
  • General

    • ComponentMgr
    • ThreeJsViewer
  • Components

    • ComponentMgr
    • GltfModel
    • Snappable
    • Socket
    • ThreeJsViewer
    • ThreeJsViewerCamera
  • Loaders

    • ConfigurationSerializer
    • GltfBlockParser
  • Utils

    • CanvasInputAdapter
    • CollisionManager
    • SocketGridExpander
    • blender
    • headless
  • General

    • Troubleshooting
    • Legacy
  • Components

    • AssetBar
    • ConfigGenerator
    • ShowpadApp
  • Managers

    • Assets
    • AppsDb
    • Config
  • Utils

    • Connection Status
    • general
    • showpad-interactive
    • showpad-upload
  • Components

    • Accordion
    • BackButton
    • Breadcrumb
    • ByltButton
    • Hamburger
    • Icon
    • Logo
    • Loader
    • Modal
    • Popup
    • Prompt
    • ProgressBar
    • TextLoader
  • Composables

    • useDebugMode
    • useConnectionStatus
  • Utils

    • dom
    • props
  • General

    • General
    • Tracking
  • Components

    • Accordion
    • ActionButton
    • AssetItem
    • AssetList
    • BackButton
    • ConfigGenButton
    • Logo
    • Media
    • Modal
    • Popup
    • Prompt
    • SPButton
    • SPRouterView
    • SPTrackedRouterLink
    • TextLoader
    • View
  • Composables

    • useConnectionStatus
  • Stores

    • useAppsDbStore
    • useBreadcrumbStore
    • useShowpadAPIStore
    • useShowpadSDKStore
    • useSpConfigStore
    • useSpStore
    • useSpTrackingStore
  • The New Kit

    • General
    • Installation & Usage
    • ACF Blocks
    • PHPCS
    • Functions
    • Vite
    • WP Config
    • Staging Deployment
  • Best Practices

    • Page Structure
    • Fonts/Typography
  • Todo
GitHub
  • AppsDb

AppsDb

import AppsDb from '@bbc/front-end-kit/js/showpad/managers/AppsDb';

AppsDB is a key-value store designed to enrich Showpad Apps with features like offline storage, cross-platform compatibility, and secure data protection. It operates on a structure where data is organized into stores containing store entries, each identified by an ID and a scope.

There are two types of scopes: USER and GLOBAL. USER-scoped entries are tied to individual users, allowing personalized data without overlap, while GLOBAL-scoped entries are accessible to all users but require specific OAuth2 permissions to create.

Warning

Although AppsDB is promoted as a tool to enhance offline functionality, it's important to note that only local (user-scoped) stores are fully accessible offline.

In contrast, global (global-scoped) data is restricted to read-only access when offline.

This class wraps Showpads' logic into a neat and transportable instance.

It also extends the EventDispatcher so it comes with all the benefits of our internal event management as well.

Vue applications

For Vue-based Showpad applications, use useAppsDbStore instead. It provides the same functionality with reactive state, singleton management, automatic queuing, and a clean composable API.

Store scopes

AppsDB supports two types of data stores:

Local Stores

  • Scoped to individual users (user-scoped)
  • Each user has their own isolated data space
  • Full read/write access for the owning user
  • Works offline
  • No special permissions needed

Global Stores

  • Accessible across the entire Showpad platform (global-scoped)
  • Shared data visible to all users
  • Read access for all users
  • Write access restricted to:
    • Admins by default
    • Normal users with valid access token
  • Limited offline functionality (read-only)

To grant normal users write access to global stores, provide an access token via the accessToken property. You can obtain this token using the getApiConfig utility.

Access token

Example of how to get the access token for a global store:

import { getApiConfig } from '@bbc/front-end-kit/js/showpad';

async function initDbs() {
    // get api config instance
    const apiConfig = await getApiConfig();

    // get access token
    const accessToken = apiConfig.accessToken;

    // init global store with access token
    const globalStore = new AppsDb({
        id: 'my-global-store',
        type: 'global',
        accessToken
    });

    // or apply the access token at a later stage
    globalStore.accessToken = accessToken;
}



Getting started

AppsDb can be initialized directly.

const myStore = new AppsDb({
    id: 'my-apps-db-store'
    type: 'local'
});

Caution

AppsDB fails miserably (without clear explanation appart from 'BAD_FORMAT' error) when the given id/name contains invalid characters. It is not documented what characters are allowed and what are not. So we advise to always use lowercase characters and hyphens to separate words, periods have been proven problematic.

Tips

It is adivsed to always create a child appsDb class that extends from AppsDb wherin the id and type are preset:

class myAppsDb extends AppsDb {
    constructor(args = {}) {
        args.id = 'my-apps-db-storeb';
        args.type = 'global';

        super(args);
    }
}

Initialising it later becomes a breeze

const myStore = new myAppsDb();
Example used in real project

The project needed a store in which settings could be saved. To quickly add and retrieve settings from the store, the class was extended with 2 extra methods that added extra functionalities to the actual entry retrieval.

  • getSettings: Retrieved the entry using a name instead of an id and returned the settings value of the retrieved entry
  • setSettings: Sets the settings property of the entry found using only the name instead of the id.

Every entry represented a scoped set of settings for any puprose.

import AppsDB from "@bbc/front-end-kit/js/showpad/managers/AppsDb";


export class SettingAppsDb extends AppsDB {
    
    async getSettings(name) {
        const entry = await findEntryBySettingName.call(this, name)
        return entry.settings;
    }

    async setSettings(name, settings) {
        // get setting first to get the id
        const entry = await findEntryBySettingName.call(this, name) || {
            name,
            settings: null
        };

        // update settings
        entry.settings = settings;

        // save to db
        return await this.setEntry(entry);
    }
}


// utils
function findEntryBySettingName(name) {
    return new Promise((resolve, reject) => {
        return this.getAllEntries()
            .then(entries => {
                resolve(entries.find(entry => entry.name === name));
            })
            .catch(error => {
                resolve(null)
            });
    })
}

Usage:

// initialise db (still passing id & type as it needed to support multiple scoped sets of settings)
const settingsDb = new SettingsAppsDb({
    id: 'bbc.wiki.settings',
    type: 'local'
});

// get settings using
const settings = settingsDb.getSettings('my-settings');

// chagne something
settings.appTitle = 'New App Title'

// set settings (will create new entry or update the already existing one)
settingsDb.setSettings('my-settings', settings)

API

constructor (args = {})

The constructor method initialises the new AppsDb instance.

Parameters

  • args: The configuration object used by the constructor to initialise the AppsDb in the desired way.
    • id: The store id it needs to manage
    • type: The scope of the store it needs to work in (global or local)
    • accessToken: The access token to use for global stores on non-admin accounts
    • oauthInstance: (depracated] The OAuth instance to use for global stores on non-admin accounts

Warning

The oauthInstance parameter is deprecated due to the fact that OAuth is not supported with SSO.

Use accessToken instead for extra grants using the access token.

Methods

init ()

Initialises the store if it does not exist and if the current user is an admin user. It is important for Admins to run the app a first time after it has been published for the very first time else a "Only admins can run this method" erro may be triggered by the Showpad.createStore() method.

Preview mode

This method will automatically detect Showpad's preview mode (detected when getUserInfo() returns no fullName) and mock all the methods so that many of the instantly occurring errors can be bypassed. When active, _type is set to 'preview' and all writes return mock data. It will still cause issues/bugs in the app but these should be limited to data manipulation as much as possible.

Offline fallback

When Showpad.createStore() fails because the command is not supported offline, init() falls back to a slower existence probe: it sets a temporary entry, then deletes it after a 750ms delay. If that succeeds the store is considered to exist and the promise resolves with true.

create ()

Warning

Deprecated in favour of init. The logic has been replaced by a call to init behind the scenes. The behavior may be slightly different than the original.

Creates the store in case it doesn't exist yet. Showpad throws a 409 error in case the store already exists. This method will catch it gracefully (while still showing it in the console) so the code can continue without issue.

Return

Returns a Promise that will pass a Boolean determining if the creation has happened (true) or not (false).

exists ()

Warning

Deprecated in favour of init. The logic has been replaced by a call to init behind the scenes. The behavior may be slightly different than the original.

Checks if the AppsDb already exists without creating it.

Return

Returns a Promise that will pass a Boolean determining if the db exists (true) or not (false).

getEntry (id, options = {})

Retrieves a specific entry from the database based on the id that was provided.

Parameters
  • id: The id of the entry that needs to be looked up.
  • options: Reserved for future use — not read by the current source.
Return

Returns a Promise that will pass the retrieved entry as the parameter in the chain of the promise.

getAllEntries (options = {})

Retrieves all entries from the database without pagination.

Parameters
  • options: Extra options object to influence the method in its execution
    • raw: Will force to return the raw version of the entry in the AppsDb. Actual values are saved in the value property of the entry. As we expect that this is the content that will be requested the most, AppsDb will provide it automatically. Use this property to prevent this behavior.
Return

Returns a Promise that will pass an Array of all the entries it retrieved from the AppsDb in the chain of the promise.

setEntry (entry)

Sets an entry into the AppsDb. If the entry lacks an id, it will be considered new and will be added as a new entry. If it contains and id, it will be considered an existing entry and will try to update it. If in any case it has an id but doesn't exist yet, it will simply be considered as new as well.

Parameters
  • entry: The entry it needs to add/update in the appsDb

Cleans up strings

It will clean up all the strings it can find in the given entry object to make sure some of the unsupported characters will be removed. Showpad tends to fail with a dubious error when it can not process a certain character and may cause it to save everything up until that character and corrupt the store. This in turn may cause the whole application to fail to load.

This can have an effect on the resulted data that is saved.

Character limit

As of 24/06/2024 Showpad has a hard cut-off limit in character count for the entry values. Longer strings will be chunked an thus result in partially saved contents with possible data corruption and (hard to debug) failing app logic in return.

Limit using the SDK is set to 10mb per entry value (our understanding is that the rest of the entry object is not count as part of that limit), but be carefull.

  • Global scoped setEntry documentation
  • User scoped setEntry documentation
Return

Returns a Promise that will pass the added/upated entry as the parameter in the chain of the promise. That entry will be the actual representation of the entry in the AppsDb. So when it didn't have an id when passed, it will have one when returned.

deleteEntry (id)

Delete an entry from the AppsDb based on the given id.

Parameters
  • id: The id of the entry it needs to delete.
`Return``

Returns a Promise that resolves when the deletion is completed.

duplicateEntry (item)

Will duplicate a given entry. It will make sure that properties like id, updated_at and created_at will be cleared before the duplicated entry is set to the AppsDb.

Parameters
  • item: Either the entry object or a String id of the entry to duplicate.
Return

Returns a Promise that will pass the duplicated entry as the parameter in the chain of the promise. That entry will be the actual representation of the entry in the AppsDb.

clear ()

Clears the whole AppsDb by fetching all entries and deleting each one individually.

Return

Returns a Promise that resolves with an array of per-entry delete results when all deletions have completed.

Caution

Intended to be used by developers only during development when the data is not important as the effects are permanent.

Getters & Setters

id

Returns the store id that the app is using to identify the store to manage

type

The scope of the store to use: global or local

accessToken

The access token to use for global stores on non-admin accounts

Dispatches the access-token-changed event when the access token is changed.

oauthInstance

The OAuth instance to use for global stores on non-admin accounts. Both getter and setter log a deprecation warning. The setter dispatches the oauth-instance-changed event when the value changes.

Warning

The oauthInstance parameter is deprecated due to the fact that OAuth is not supported with SSO.

Use accessToken instead for extra grants using the access token.

Private properties

_id

The id that is used to retrieve dat store using the Showpad library

_type

The scope from which the appsdb needs to retrieve the entries from.

_accessToken

The access token to use for global stores on non-admin accounts

_oauthInstance

The OAuth instance to use for global stores on non-admin accounts

Events

Event payload inconsistency

Some events wrap their payload in a detail property (accessed as e.detail.*), while others expose properties directly on the event object (e.*). This is a source-level inconsistency — see the "Access via" column below.

EventAccess viaPayload
get-entrye.detail.*id, data, error
get-all-entriese.detail.*data, error
set-entrye.*entry, data, error
delete-entrye.*id, data, error
clearede.*data, error, total
errore.detailthe raw error object
access-token-changede.detailthe new access token value
oauth-instance-changede.detailthe new OAuth instance value

get-entry

Dispatched when an entry is retrieved or failed to be retrieved. Payload (via e.detail): id, data (raw entry), error.

get-all-entries

Dispatched when all entries are retrieved or failed to be retrieved. Payload (via e.detail): data (raw entries array), error.

set-entry

Dispatched when an entry is set or failed to be set. Payload (directly on event): entry (the data passed to the method), data (saved entry), error.

delete-entry

Dispatched when an entry is deleted or failed to be deleted. Payload (directly on event): id, data, error.

cleared

Dispatched when the whole store is cleared or fails to be cleared. Payload (directly on event): data (entries that were deleted), error, total (count of entries deleted).

error

Dispatched when an error occurs. Payload: the raw error object via e.detail.

access-token-changed

Dispatched when the access token is changed via the setter. Payload: the new token value via e.detail.

oauth-instance-changed

Dispatched when the OAuth instance is changed via the setter. Payload: the new instance value via e.detail.

Dependencies

  • Experience APP SDK: Showpad's library
  • uuid: A library to quickly generate uuid strings
Edit this page
Last Updated: 4/27/26, 12:56 PM
Contributors: Nicolas Jaenen