Ltijs Sequelize Database Plugin
Ltijs Sequelize Database Plugin is an official plugin for the LTI Advantage Complete Certified `ltijs` library, enabling it to persist LTI platform and deployment data using databases supported by Sequelize. It provides a robust, production-ready solution for managing LTI data with relational databases like MySQL, PostgreSQL, and MariaDB. The current stable version is 2.4.4, with releases often coinciding with new feature additions or compatibility updates for the core `ltijs` library, as seen with versions 2.4.0 and 2.3.0 introducing support for new `ltijs` features. This tight integration ensures seamless operation and access to advanced LTI features like Dynamic Registration Service and `authorizationServer` platform fields. Its primary differentiation is its certified compatibility and direct integration with `ltijs`, offering a tested and reliable database solution for LTI service providers.
Common errors
-
SequelizeConnectionError: connect ECONNREFUSED 127.0.0.1:3306
cause The database server is not running or is not accessible from the application's host and port specified in the Sequelize options.fixVerify your database server is running and configured to accept connections from the host where your Node.js application is running. Check firewall rules, database server status, and the `host` and `port` settings in your `Database` constructor options. -
Error: The dialect mysql is not supported. Please use one of the following: mariadb, postgres, mssql, sqlite
cause The specified `dialect` in the `Database` options is either misspelled, unsupported by the installed Sequelize version, or the necessary database driver package (e.g., `mysql2` for `mysql`) has not been installed.fixDouble-check the `dialect` spelling. Ensure you have installed the correct Sequelize driver package (e.g., `npm install mysql2` for MySQL, `npm install pg pg-hstore` for PostgreSQL) in addition to `sequelize` and `ltijs-sequelize`. -
TypeError: Cannot read properties of undefined (reading 'setup')
cause The `lti` object was incorrectly imported or instantiated from the `ltijs` package. `setup` is a method of the `Provider` instance, not the top-level `ltijs` module itself.fixEnsure you import or require the `Provider` export correctly from `ltijs`, typically as `import { Provider as LtiProvider } from 'ltijs'` or `const lti = require('ltijs').Provider`. -
LTI Storage Plugin not configured.
cause The `ltijs.setup` method was called without providing a `plugin` object in its configuration, or the provided plugin object was invalid or `null`/`undefined`.fixEnsure that an instantiated `ltijs-sequelize` `Database` object is correctly passed to the `plugin` field in `lti.setup` configuration: `lti.setup('LTIKEY', { plugin: db }, { ...options })`. -
ER_BAD_DB_ERROR: Unknown database 'your_database_name'
cause The database specified in the `Database` constructor ('database' argument) does not exist on the configured database server.fixManually create the database on your database server *before* running your application, or configure your database user with permissions to create databases if using a dialect that supports automatic database creation (though this is less common for security reasons).
Warnings
- breaking Compatibility between `ltijs-sequelize` and `ltijs` is strict and tied to specific major/minor versions. Using an incompatible `ltijs-sequelize` version with a new `ltijs` major or minor release can lead to runtime errors or unexpected behavior due to schema or API changes.
- gotcha When initializing the `Database` plugin, the `options` object passed to the constructor *must* explicitly include `host` and `dialect` fields, which are fundamental for Sequelize to connect to your chosen database.
- breaking As of `ltijs-sequelize` v2.4.0, automatic database migrations are supported. While this feature enhances flexibility, it means schema changes might be applied automatically, which could be an unexpected behavior for production environments without proper review.
- gotcha The `ltijs.setup` `cookies.secure` option should be set to `true` in production to prevent cookies from being sent over insecure connections, which is a security vulnerability for LTI messages. `sameSite: 'none'` is also critical for cross-site LTI launches.
- gotcha This plugin requires specific database drivers (e.g., `mysql2`, `pg`, `tedious`) to be installed separately based on the `dialect` chosen in the Sequelize options. Failure to install the correct driver will result in connection errors.
Install
-
npm install ltijs-sequelize -
yarn add ltijs-sequelize -
pnpm add ltijs-sequelize
Imports
- Database
import { Database } from 'ltijs-sequelize'import Database from 'ltijs-sequelize'
- Provider (from ltijs)
import Provider from 'ltijs'
import { Provider } from 'ltijs' - SequelizeOptions (type)
import type { Options as SequelizeOptions } from 'sequelize';
Quickstart
const path = require('path')
// Require Provider
const lti = require('ltijs').Provider
const Database = require('ltijs-sequelize')
// Setup ltijs-sequelize using the same arguments as Sequelize's generic contructor
const db = new Database('database', 'user', 'password',
{
host: 'localhost',
dialect: 'mysql', // Or 'postgres', 'mariadb', 'mssql', 'sqlite'
logging: false,
// Other Sequelize options like pool, define, etc.
// Example: dialectOptions for SSL for PostgreSQL on Heroku
// dialectOptions: {
// ssl: {
// require: true,
// rejectUnauthorized: false
// }
// }
})
// Setup provider, passing the db object to the plugin field
lti.setup(process.env.LTIJS_KEY ?? 'LTIKEY_YOUR_SECRET', // Key used to sign cookies and tokens. USE A STRONG RANDOM KEY!
{
plugin: db // Passing db object to plugin field
},
{ // Optional Ltijs configuration options
appRoute: '/',
loginRoute: '/login',
cookies: {
secure: process.env.NODE_ENV === 'production', // Set to true in production
sameSite: 'none' // Required for cross-site LTI launches
},
// Other Ltijs options like devMode, staticPath, etc.
// example: staticPath: path.join(__dirname, './public')
})
// Example of how to initialize and connect
async function startLti() {
try {
await db.deploy(); // Deploys database schema, creates tables if they don't exist
await lti.deploy(); // Deploys Ltijs, setting up routes and middleware
console.log('LTI and Database plugin deployed successfully.');
} catch (err) {
console.error('Failed to deploy LTI or database plugin:', err);
process.exit(1);
}
}
startLti();