![PlanetScale serverless driver for JavaScript](https://github.com/planetscale/database-js/assets/440926/0dfab33f-b01f-4814-ae40-c5fe5cbe94e3) # PlanetScale serverless driver for JavaScript A Fetch API-compatible PlanetScale database driver for serverless and edge compute platforms that require HTTP external connections, such as Cloudflare Workers or Vercel Edge Functions ## Installation ```sh npm install @planetscale/database ``` ## Usage ```ts import { connect } from '@planetscale/database' const config = { host: '', username: '', password: '' } const conn = connect(config) const results = await conn.execute('select 1 from dual where 1=?', [1]) console.log(results) ``` ### Database URL A single database URL value can be used to configure the `host`, `username`, and `password` values. ```ts import { connect } from '@planetscale/database' const config = { url: process.env['DATABASE_URL'] || 'mysql://user:pass@host' } const conn = connect(config) ``` ### Connection factory Use the `Client` connection factory class to create fresh connections for each transaction or web request handler. ```ts import { Client } from '@planetscale/database' const client = new Client({ host: '', username: '', password: '' }) const conn = client.connection() const results = await conn.execute('select 1 from dual') console.log(results) ``` ### Transactions Use the `transaction` function to safely perform database transactions. If any unhandled errors are thrown during execution of the transaction, the transaction will be rolled back. The following example is based on [the Slotted Counter Pattern](https://planetscale.com/blog/the-slotted-counter-pattern). ```ts import { connect } from '@planetscale/database' const config = { host: '', username: '', password: '' } const conn = connect(config) const results = await conn.transaction(async (tx) => { const whenBranch = await tx.execute('INSERT INTO branches (database_id, name) VALUES (?, ?)', [42, "planetscale"]) const whenCounter = await tx.execute('INSERT INTO slotted_counters(record_type, record_id, slot, count) VALUES (?, ?, RAND() * 100, 1) ON DUPLICATE KEY UPDATE count = count + 1', ['branch_count', 42]) return [whenBranch, whenCounter] }) console.log(results) ``` ### Usage with PlanetScale Boost To enable PlanetScale Boost, run `SET @@boost_cached_queries = true` once. All subsequent queries run on the same connection will use boost if it's enabled for the query pattern. Non-matching queries will run as normal. To learn more, visit: [Query caching with PlanetScale Boost](https://planetscale.com/docs/concepts/query-caching-with-planetscale-boost) ```ts const conn = client.connection() // Enable boost for the connection await conn.execute('SET @@boost_cached_queries = true') const results = await conn.execute('...') // Optionally, you may disable boost for the connection by setting to false await conn.execute('SET @@boost_cached_queries = false') ``` ### Custom fetch function Node.js version 18 includes a built-in global `fetch` function. When using an older version of Node.js, you can provide a custom fetch function implementation. We recommend the [`undici`][1] package on which Node's built-in fetch is based. [1]: https://github.com/nodejs/undici ```ts import { connect } from '@planetscale/database' import { fetch } from 'undici' const config = { fetch, host: '', username: '', password: '' } const conn = connect(config) const results = await conn.execute('select 1 from dual') console.log(results) ``` To leverage HTTP/2, you can use the [`fetch-h2`][2] shim. `fetch-h2` also supports Node.js 12+. [2]: https://www.npmjs.com/package/fetch-h2 ```ts import { connect } from '@planetscale/database' import { context } from 'fetch-h2' const { fetch, disconnectAll } = context() const config = { fetch, host: '', username: '', password: '' } const conn = connect(config) const results = await conn.execute('select 1 from dual') console.log(results) await disconnectAll() ``` ### Custom query parameter format function Query replacement parameters identified with `?` are replaced with escaped values. Named replacement parameters are supported with a colon prefix. ```ts const results1 = await conn.execute('select 1 from dual where 1=?', [42]) const results2 = await conn.execute('select 1 from dual where 1=:id', { id: 42 }) ``` Providing a custom format function overrides the built-in escaping with an external library, like [`sqlstring`](https://github.com/mysqljs/sqlstring). ```ts import { connect } from '@planetscale/database' import SqlString from 'sqlstring' const config = { format: SqlString.format, host: '', username: '', password: '' } const conn = connect(config) const results = await conn.execute('select 1 from dual where 1=?', [42]) console.log(results) ``` ### Custom type casting function Column values are converted to their corresponding JavaScript data types. This can be customized by providing a `cast` function. ```ts import { connect, cast } from '@planetscale/database' function inflate(field, value) { if (field.type === 'INT64' || field.type === 'UINT64') { return BigInt(value) } return cast(field, value) } const config = { cast: inflate, host: '', username: '', password: '' } const conn = connect(config) ``` You can also pass a custom `cast` function to `execute`. If present, this will override the `cast` function set by the connection: ```ts const result = await conn.execute( 'SELECT userId, SUM(balance) AS balance FROM UserBalanceItem GROUP BY userId', {}, { cast: (field, value) => { if (field.name === 'balance') { return BigInt(value) } return cast(field, value) } } ) ``` ### Row return values Rows can be returned as an object or an array of column values by passing an `as` option to `execute`. ```ts const query = 'select 1 as one, 2 as two where 1=?' const objects = conn.execute(query, [1], { as: 'object' }) // objects.rows => [{one: '1', two: '2'}] const arrays = conn.execute(query, [1], { as: 'array' }) // arrays.rows => [['1', '2']] ``` ## Development ```sh npm install npm test ``` ## Need help? Get help from [the PlanetScale support team](https://support.planetscale.com/), or [join our community on Discord](https://discord.gg/EqrcEf2dGv) or [GitHub discussion board](https://github.com/planetscale/discussion/discussions) to see how others are using PlanetScale. ## License Distributed under the Apache 2.0 license. See LICENSE for details.