@neondatabase/serverless
Advanced tools
Comparing version 0.5.7 to 0.6.0
@@ -110,2 +110,54 @@ # Options and configuration | ||
## `transaction(...)` function | ||
The `transaction(queriesOrFn, options)` function, is exposed as a property on the query function. It allows multiple queries to be executed within a single, non-interactive transaction. | ||
The first argument to `transaction()`, `queriesOrFn`, is either (1) an array of queries or (2) a non-`async` function that receives a query function as its argument and returns an array of queries. | ||
The array-of-queries case looks like this: | ||
```javascript | ||
import { neon } from '@neondatabase/serverless'; | ||
const sql = neon(process.env.DATABASE_URL); | ||
const showLatestN = 10; | ||
const [posts, tags] = await sql.transaction([ | ||
sql`SELECT * FROM posts ORDER BY posted_at DESC LIMIT ${showLatestN}`, | ||
sql`SELECT * FROM tags`, | ||
], { | ||
isolationLevel: 'RepeatableRead', | ||
readOnly: true, | ||
}); | ||
``` | ||
Or as an example of the function case: | ||
```javascript | ||
const [authors, tags] = await neon(process.env.DATABASE_URL) | ||
.transaction(txn => [ | ||
txn`SELECT * FROM authors`, | ||
txn`SELECT * FROM tags`, | ||
]); | ||
``` | ||
The optional second argument to `transaction()`, `options`, has the same keys as the options to the ordinary query function -- `arrayMode`, `fullResults` and `fetchOptions` -- plus three additional keys that concern the transaction configuration. These transaction-related keys are: `isolationMode`, `readOnly` and `deferrable`. | ||
Note that options **cannot** be supplied for individual queries within a transaction. Query and transaction options must instead be passed as the second argument of the `transaction()` function. For example, this `arrayMode` setting is ineffective (and TypeScript won't compile it): `await sql.transaction([sql('SELECT now()', [], { arrayMode: true })])`. Instead, use `await sql.transaction([sql('SELECT now()')], { arrayMode: true })`. | ||
### `isolationMode` | ||
This option selects a Postgres [transaction isolation mode](https://www.postgresql.org/docs/current/transaction-iso.html). If present, it must be one of: `'ReadUncommitted'`, `'ReadCommitted'`, `'RepeatableRead'` or `'Serializable'`. | ||
### `readOnly` | ||
If `true`, this option ensures that a `READ ONLY` transaction is used to execute the queries passed. | ||
### `deferrable` | ||
If `true` (and if `readOnly` is also `true`, and `isolationMode` is `'Serializable'`), this option ensures that a `DEFERRABLE` transaction is used to execute the queries passed. | ||
## `neonConfig` configuration | ||
@@ -112,0 +164,0 @@ |
152
index.d.ts
@@ -222,24 +222,146 @@ | ||
export interface ParameterizedQuery { | ||
query: string; | ||
params: any[]; | ||
} | ||
export interface HTTPQueryOptions<ArrayMode extends boolean, FullResults extends boolean> { | ||
/** | ||
* When `arrayMode` is `false`, which is the default, result rows are | ||
* returned as objects whose keys represent column names, such as | ||
* `{ id: 1 }`). | ||
* | ||
* When `arrayMode` is `true`, rows are returned as arrays (and keys are not | ||
* provided), e.g. `[1]`. | ||
*/ | ||
arrayMode?: ArrayMode; | ||
/** | ||
* When `fullResults` is `false`, which is the default, only result rows are | ||
* returned, e.g. `[{ id: 1 }]`). | ||
* | ||
* When `fullResults` is `true`, a result object is returned that matches | ||
* what's returned by node-postgres. This has a `rows` property, which is an | ||
* array of result rows, plus `fields`, which provides column names and | ||
* types, `command` and `rowCount`. | ||
*/ | ||
fullResults?: FullResults; // default false | ||
/** | ||
* Any options in `fetchOptions` are merged in to the options passed to | ||
* `fetch`. In case of conflict with what would otherwise be passed, these | ||
* options take precedence. | ||
*/ | ||
fetchOptions?: Record<string, any>; | ||
} | ||
export interface HTTPTransactionOptions<ArrayMode extends boolean, FullResults extends boolean> extends HTTPQueryOptions<ArrayMode, FullResults> { | ||
/** | ||
* Postgres transaction isolation level: see https://www.postgresql.org/docs/current/transaction-iso.html. | ||
* Note that `ReadUncommitted` actually gets you `ReadCommitted` in Postgres. | ||
* */ | ||
isolationLevel?: 'ReadUncommitted' | 'ReadCommitted' | 'RepeatableRead' | 'Serializable'; | ||
/** | ||
* When `readOnly` is `false`, which is the default, a `READ WRITE` Postgres | ||
* transaction is used. | ||
* | ||
* When `readOnly` is `true`, a `READ ONLY` Postgres transaction is used. | ||
* */ | ||
readOnly?: boolean; | ||
/** | ||
* When `deferrable` is `false`, which is the default, a `NOT DEFERRABLE` | ||
* Postgres transaction is used. | ||
* | ||
* When `deferrable` is `true` (and `isolationLevel` is `Serializable` and | ||
* `readOnly` is `true`), a `DEFERRABLE` Postgres transaction is used. | ||
* */ | ||
deferrable?: boolean; | ||
} | ||
export interface NeonQueryPromise<ArrayMode extends boolean, FullResults extends boolean, T = any> extends Promise<T> { | ||
parameterizedQuery: ParameterizedQuery; | ||
opts?: HTTPQueryOptions<ArrayMode, FullResults>; | ||
} | ||
export interface NeonQueryInTransaction { | ||
// this is a simplified form of query, which has only a `parameterizedQuery` (no `opts` and not a `Promise`) | ||
parameterizedQuery: ParameterizedQuery; | ||
} | ||
export interface NeonQueryFunctionInTransaction<ArrayMode extends boolean, FullResults extends boolean> { | ||
// this is a simplified form of NeonQueryFunction (below): | ||
// * `opts` cannot be passed | ||
// * no `transaction()` method is available | ||
// tagged-template function usage | ||
(strings: TemplateStringsArray, ...params: any[]): | ||
NeonQueryPromise<ArrayMode, FullResults, FullResults extends true ? FullQueryResults<ArrayMode> : QueryRows<ArrayMode>>; | ||
// ordinary function usage (*no* options overrides) | ||
(string: string, params?: any[]): | ||
NeonQueryPromise<ArrayMode, FullResults, FullResults extends true ? FullQueryResults<ArrayMode> : QueryRows<ArrayMode>>; | ||
} | ||
export interface NeonQueryFunction<ArrayMode extends boolean, FullResults extends boolean> { | ||
// tagged-template function usage | ||
(strings: TemplateStringsArray, ...params: any[]): | ||
Promise<FullResults extends true ? FullQueryResults<ArrayMode> : QueryRows<ArrayMode>>; | ||
NeonQueryPromise<ArrayMode, FullResults, FullResults extends true ? FullQueryResults<ArrayMode> : QueryRows<ArrayMode>>; | ||
// ordinary function usage, with options overrides | ||
<ArrayModeOverride extends boolean = ArrayMode, FullResultsOverride extends boolean = FullResults>( | ||
strings: string, | ||
string: string, | ||
params?: any[], | ||
options?: { | ||
arrayMode?: ArrayModeOverride; | ||
fullResults?: FullResultsOverride; | ||
fetchOptions?: Record<string, any>; | ||
}): | ||
Promise<FullResultsOverride extends true ? FullQueryResults<ArrayModeOverride> : QueryRows<ArrayModeOverride>>; | ||
opts?: HTTPQueryOptions<ArrayModeOverride, FullResultsOverride> | ||
): NeonQueryPromise< | ||
ArrayModeOverride, | ||
FullResultsOverride, | ||
FullResultsOverride extends true ? FullQueryResults<ArrayModeOverride> : QueryRows<ArrayModeOverride> | ||
>; | ||
/** | ||
* The `transaction()` function allows multiple queries to be submitted (over | ||
* HTTP) as a single, non-interactive Postgres transaction. | ||
* | ||
* For example: | ||
* ``` | ||
* import { neon } from "@neondatabase/serverless"; | ||
* const sql = neon("postgres://user:pass@host/db"); | ||
* | ||
* const results = await sql.transaction([ | ||
* sql`SELECT 1 AS num`, | ||
* sql`SELECT 'a' AS str`, | ||
* ]); | ||
* // -> [[{ num: 1 }], [{ str: "a" }]] | ||
* | ||
* // or equivalently: | ||
* const results = await sql.transaction(txn => [ | ||
* txn`SELECT 1 AS num`, | ||
* txn`SELECT 'a' AS str`, | ||
* ]); | ||
* // -> [[{ num: 1 }], [{ str: "a" }]] | ||
* ``` | ||
* @param queriesOrFn Either an array of queries, or a (non-`async`) function | ||
* that receives a query function and returns an array of queries. | ||
* @param opts The same options that may be set on individual queries in a | ||
* non-transaction setting -- that is, `arrayMode` `fullResults` and | ||
* `fetchOptions` -- plus the transaction options `isolationLevel`, | ||
* `readOnly` and `deferrable`. Note that none of these options can be set on | ||
* individual queries within a transaction. | ||
* @returns An array of results. The structure of each result object depends | ||
* on the `arrayMode` and `fullResults` options. | ||
*/ | ||
transaction: <ArrayModeOverride extends boolean = ArrayMode, FullResultsOverride extends boolean = FullResults>( | ||
queriesOrFn: NeonQueryPromise<ArrayMode, FullResults>[] | // not ArrayModeOverride or FullResultsOverride: clamp these values to the current ones | ||
((sql: NeonQueryFunctionInTransaction<ArrayModeOverride, FullResultsOverride>) => NeonQueryInTransaction[]), | ||
opts?: HTTPTransactionOptions<ArrayModeOverride, FullResultsOverride> | ||
) => Promise<FullResultsOverride extends true ? FullQueryResults<ArrayModeOverride>[] : QueryRows<ArrayModeOverride>[]>; | ||
} | ||
/** | ||
* This experimental function returns an async tagged-template function that | ||
* runs a single SQL query (no session or transactions) with low latency over | ||
* https. By default, it returns database rows directly. Types should match | ||
* those returned by this driver (i.e. Pool or Client) over WebSockets. | ||
* This function returns an async tagged-template function that runs a single | ||
* SQL query (no session or transactions) with low latency over https. Support | ||
* for multiple queries as a non-interactive transaction is provided by | ||
* the `transaction` property of the query function. | ||
* | ||
* By default, the query function returns database rows directly. Types should | ||
* match those returned by this driver (i.e. Pool or Client) over WebSockets. | ||
* | ||
* The returned function can also be called directly (i.e. not as a template | ||
@@ -291,7 +413,3 @@ * function). In that case, pass it a query string with embedded `$1`, `$2` | ||
connectionString: string, | ||
options?: { | ||
arrayMode?: ArrayMode; | ||
fullResults?: FullResults; | ||
fetchOptions?: Record<string, any>; | ||
} | ||
options?: HTTPTransactionOptions<ArrayMode, FullResults>, | ||
): NeonQueryFunction<ArrayMode, FullResults>; | ||
@@ -298,0 +416,0 @@ |
{ | ||
"name": "@neondatabase/serverless", | ||
"version": "0.5.7", | ||
"version": "0.6.0", | ||
"author": "Neon", | ||
@@ -5,0 +5,0 @@ "description": "node-postgres for serverless environments from neon.tech", |
@@ -98,11 +98,31 @@ # @neondatabase/serverless [BETA] | ||
### `transaction()` | ||
Multiple queries can be issed via fetch request within a single, non-interactive transaction by using the `transaction()` function. This is exposed as a property on the query function. | ||
For example: | ||
```javascript | ||
import { neon } from '@neondatabase/serverless'; | ||
const sql = neon(process.env.DATABASE_URL); | ||
const showLatestN = 10; | ||
const [posts, tags] = await sql.transaction([ | ||
sql`SELECT * FROM posts ORDER BY posted_at DESC LIMIT ${showLatestN}`, | ||
sql`SELECT * FROM tags`, | ||
]); | ||
``` | ||
There are some [additional options](CONFIG.md) when using `transaction()`. | ||
### `Pool` and `Client` | ||
Use the `Pool` or `Client` constructors instead when you need: | ||
Use the `Pool` or `Client` constructors, instead of the functions described above, when you need: | ||
* **session or transaction support**, or | ||
* **session or interactive transaction support**, and/or | ||
* **node-postgres compatibility**, to enable query libraries like [Kysely](https://kysely.dev/) or [Zapatos](https://jawj.github.io/zapatos/). | ||
* **compatibility with node-postgres**, which supports query libraries like [Kysely](https://kysely.dev/) or [Zapatos](https://jawj.github.io/zapatos/). | ||
Using `Pool` and `Client`, queries are carried by WebSockets. There are **two key things** you need to know: | ||
Queries using `Pool` and `Client` are carried by WebSockets. There are **two key things** to know about this: | ||
@@ -136,3 +156,3 @@ 1. **In Node.js** and some other environments, there's no built-in WebSocket support. In these cases, supply a WebSocket constructor function. | ||
const pool = new Pool({ connectionString: process.env.DATABASE_URL }); | ||
pool.on('error', err => console.error(err)); | ||
pool.on('error', err => console.error(err)); // deal with e.g. re-connect | ||
// ... | ||
@@ -170,3 +190,3 @@ | ||
We can rewrite the Vercel Edge Function above to use `Pool`, as follows: | ||
We can rewrite the Vercel Edge Function shown above (under the heading 'Deploy it') to use `Pool`, as follows: | ||
@@ -173,0 +193,0 @@ ```javascript |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
185149
2009
288