title | label | order | desc | keywords |
---|---|---|---|---|
SQLite |
SQLite |
60 |
Payload supports SQLite through an officially supported Drizzle Database Adapter. |
SQLite, documentation, typescript, Content Management System, cms, headless, javascript, node, react, nextjs |
To use Payload with SQLite, install the package @payloadcms/db-sqlite
. It leverages Drizzle ORM and libSQL
to interact with a SQLite database that you provide.
It automatically manages changes to your database for you in development mode, and exposes a full suite of migration controls for you to leverage in order to keep other database environments in sync with your schema. DDL transformations are automatically generated.
To configure Payload to use SQLite, pass the sqliteAdapter
to your Payload Config as follows:
import { sqliteAdapter } from '@payloadcms/db-sqlite'
export default buildConfig({
// Your config goes here
collections: [
// Collections go here
],
// Configure the SQLite adapter here
db: sqliteAdapter({
// SQLite-specific arguments go here.
// `client.url` is required.
client: {
url: process.env.DATABASE_URL,
authToken: process.env.DATABASE_AUTH_TOKEN,
},
}),
})
Option | Description |
---|---|
client * |
Client connection options that will be passed to createClient from @libsql/client . |
push |
Disable Drizzle's db push in development mode. By default, push is enabled for development mode only. |
migrationDir |
Customize the directory that migrations are stored. |
logger |
The instance of the logger to be passed to drizzle. By default Payload's will be used. |
idType |
A string of 'number', or 'uuid' that is used for the data type given to id columns. |
transactionOptions |
A SQLiteTransactionConfig object for transactions, or set to false to disable using transactions. More details |
localesSuffix |
A string appended to the end of table names for storing localized fields. Default is '_locales'. |
relationshipsSuffix |
A string appended to the end of table names for storing relationships. Default is '_rels'. |
versionsSuffix |
A string appended to the end of table names for storing versions. Defaults to '_v'. |
beforeSchemaInit |
Drizzle schema hook. Runs before the schema is built. More Details |
afterSchemaInit |
Drizzle schema hook. Runs after the schema is built. More Details |
generateSchemaOutputFile |
Override generated schema from payload generate:db-schema file path. Defaults to {CWD}/src/payload-generated.schema.ts |
autoIncrement |
Pass true to enable SQLite AUTOINCREMENT for primary keys to ensure the same ID cannot be reused from deleted rows |
allowIDOnCreate |
Set to true to use the id passed in data on the create API operations without using a custom ID field. |
After Payload is initialized, this adapter will expose the full power of Drizzle to you for use if you need it.
To ensure type-safety, you need to generate Drizzle schema first with:
npx payload generate:db-schema
Then, you can access Drizzle as follows:
// Import table from the generated file
import { posts } from './payload-generated-schema'
// To avoid installing Drizzle, you can import everything that drizzle has from our re-export path.
import { eq, sql, and } from '@payloadcms/db-sqlite/drizzle'
// Drizzle's Querying API: https://orm.drizzle.team/docs/rqb
const posts = await payload.db.drizzle.query.posts.findMany()
// Drizzle's Select API https://orm.drizzle.team/docs/select
const result = await payload.db.drizzle
.select()
.from(posts)
.where(
and(eq(posts.id, 50), sql`lower(${posts.title}) = 'example post title'`),
)
In addition to exposing Drizzle directly, all of the tables and Drizzle relations are exposed for you via the payload.db
property as well.
- Tables -
payload.db.tables
- Relations -
payload.db.relations
Drizzle exposes two ways to work locally in development mode.
The first is db push
, which automatically pushes changes you make to your Payload Config (and therefore, Drizzle schema) to your database so you don't have to manually migrate every time you change your Payload Config. This only works in development mode, and should not be mixed with manually running migrate
commands.
You will be warned if any changes that you make will entail data loss while in development mode. Push is enabled by default, but you can opt out if you'd like.
Alternatively, you can disable push
and rely solely on migrations to keep your local database in sync with your Payload Config.
In SQLite, migrations are a fundamental aspect of working with Payload and you should become familiar with how they work.
For more information about migrations, click here.
Runs before the schema is built. You can use this hook to extend your database structure with tables that won't be managed by Payload.
import { sqliteAdapter } from '@payloadcms/db-sqlite'
import { integer, sqliteTable } from '@payloadcms/db-sqlite/drizzle/sqlite-core'
sqliteAdapter({
beforeSchemaInit: [
({ schema, adapter }) => {
return {
...schema,
tables: {
...schema.tables,
addedTable: sqliteTable('added_table', {
id: integer('id').primaryKey({ autoIncrement: true }),
}),
},
}
},
],
})
One use case is preserving your existing database structure when migrating to Payload. By default, Payload drops the current database schema, which may not be desirable in this scenario.
To quickly generate the Drizzle schema from your database you can use Drizzle Introspection
You should get the schema.ts
file which may look like this:
import {
sqliteTable,
text,
uniqueIndex,
integer,
} from 'drizzle-orm/sqlite-core'
export const users = sqliteTable('users', {
id: integer('id').primaryKey({ autoIncrement: true }),
fullName: text('full_name'),
phone: text('phone', { length: 256 }),
})
export const countries = sqliteTable(
'countries',
{
id: integer('id').primaryKey({ autoIncrement: true }),
name: text('name', { length: 256 }),
},
(countries) => {
return {
nameIndex: uniqueIndex('name_idx').on(countries.name),
}
},
)
You can import them into your config and append to the schema with the beforeSchemaInit
hook like this:
import { sqliteAdapter } from '@payloadcms/db-sqlite'
import { users, countries } from '../drizzle/schema'
sqliteAdapter({
beforeSchemaInit: [
({ schema, adapter }) => {
return {
...schema,
tables: {
...schema.tables,
users,
countries,
},
}
},
],
})
Make sure Payload doesn't overlap table names with its collections. For example, if you already have a collection with slug "users", you should either change the slug or dbName
to change the table name for this collection.
Runs after the Drizzle schema is built. You can use this hook to modify the schema with features that aren't supported by Payload, or if you want to add a column that you don't want to be in the Payload config.
To extend a table, Payload exposes extendTable
utillity to the args. You can refer to the Drizzle documentation.
The following example adds the extra_integer_column
column and a composite index on country
and city
columns.
import { sqliteAdapter } from '@payloadcms/db-sqlite'
import { index, integer } from '@payloadcms/db-sqlite/drizzle/sqlite-core'
import { buildConfig } from 'payload'
export default buildConfig({
collections: [
{
slug: 'places',
fields: [
{
name: 'country',
type: 'text',
},
{
name: 'city',
type: 'text',
},
],
},
],
db: sqliteAdapter({
afterSchemaInit: [
({ schema, extendTable, adapter }) => {
extendTable({
table: schema.tables.places,
columns: {
extraIntegerColumn: integer('extra_integer_column'),
},
extraConfig: (table) => ({
country_city_composite_index: index(
'country_city_composite_index',
).on(table.country, table.city),
}),
})
return schema
},
],
}),
})
Columns and tables, added in schema hooks won't be added to the generated via payload generate:db-schema
Drizzle schema.
If you want them to be there, you either have to edit this file manually or mutate the internal Payload "raw" SQL schema in the beforeSchemaInit
:
import { sqliteAdapter } from '@payloadcms/db-sqlite'
sqliteAdapter({
beforeSchemaInit: [
({ schema, adapter }) => {
// Add a new table
adapter.rawTables.myTable = {
name: 'my_table',
columns: {
my_id: {
name: 'my_id',
type: 'integer',
primaryKey: true,
},
},
}
// Add a new column to generated by Payload table:
adapter.rawTables.posts.columns.customColumn = {
name: 'custom_column',
// Note that Payload SQL doesn't support everything that Drizzle does.
type: 'integer',
notNull: true,
}
// Add a new index to generated by Payload table:
adapter.rawTables.posts.indexes.customColumnIdx = {
name: 'custom_column_idx',
unique: true,
on: ['custom_column'],
}
return schema
},
],
})