Comparing version 2.0.0-beta.3 to 2.0.0-beta.4
@@ -521,2 +521,3 @@ const fs = require('fs') | ||
, port = o.port || url.port || env.PGPORT || 5432 | ||
, user = o.user || o.username || auth[0] || env.PGUSERNAME || env.PGUSER || osUsername() | ||
@@ -527,4 +528,4 @@ return Object.assign({ | ||
path : o.path || host.indexOf('/') > -1 && host + '/.s.PGSQL.' + port, | ||
database : o.database || o.db || (url.pathname || '').slice(1) || env.PGDATABASE || 'postgres', | ||
user : o.user || o.username || auth[0] || env.PGUSERNAME || env.PGUSER || osUsername(), | ||
database : o.database || o.db || (url.pathname || '').slice(1) || env.PGDATABASE || user, | ||
user : user, | ||
pass : o.pass || o.password || auth[1] || env.PGPASSWORD || '', | ||
@@ -531,0 +532,0 @@ max : o.max || url.query.max || 10, |
{ | ||
"name": "postgres", | ||
"version": "2.0.0-beta.3", | ||
"version": "2.0.0-beta.4", | ||
"description": "Fastest full featured PostgreSQL client for Node.js", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
@@ -123,2 +123,42 @@ <img align="left" width="440" height="140" alt="Fastest full PostgreSQL nodejs client" src="https://raw.githubusercontent.com/porsager/postgres/master/postgresjs.svg?sanitize=true" /> | ||
#### TypeScript support | ||
`postgres` has TypeScript support. You can pass a row list type for your queries in this way: | ||
```ts | ||
interface User { | ||
id: number | ||
name: string | ||
} | ||
const users = await sql<User[]>`SELECT * FROM users` | ||
users[0].id // ok => number | ||
users[1].name // ok => string | ||
users[0].invalid // fails: `invalid` does not exists on `User` | ||
``` | ||
However, be sure to check the array length to avoid accessing properties of `undefined` rows: | ||
```ts | ||
const users = await sql<User[]>`SELECT * FROM users WHERE id = ${id}` | ||
if (!users.length) | ||
throw new Error('Not found') | ||
return users[0] | ||
``` | ||
You can also prefer destructuring when you only care about a fixed number of rows. | ||
In this case, we recommand you to prefer using tuples to handle `undefined` properly: | ||
```ts | ||
const [user]: [User?] = await sql`SELECT * FROM users WHERE id = ${id}` | ||
if (!user) // => User | undefined | ||
throw new Error('Not found') | ||
return user // => User | ||
// NOTE: | ||
const [first, second]: [User?] = await sql`SELECT * FROM users WHERE id = ${id}` // fails: `second` does not exist on `[User?]` | ||
// vs | ||
const [first, second] = await sql<[User?]>`SELECT * FROM users WHERE id = ${id}` // ok but should fail | ||
``` | ||
All the public API is typed. Also, TypeScript support is still in beta. Feel free to open an issue if you have trouble with types. | ||
#### Query parameters | ||
@@ -125,0 +165,0 @@ |
@@ -250,2 +250,14 @@ /** | ||
interface UnlabeledRow<T = any> { | ||
'?column?': T; | ||
} | ||
type MaybeRow = Row | undefined; | ||
type TransformRow<T> = T extends Serializable | ||
? { '?column?': T; } | ||
: T; | ||
type AsRowList<T extends any[]> = { [k in keyof T]: TransformRow<T[k]> }; | ||
interface Column<T extends string> { | ||
@@ -276,9 +288,9 @@ name: T; | ||
type ExecutionResult<T> = [] & ResultQueryMeta<number, T>; | ||
type RowList<T extends readonly Row[]> = T & ResultQueryMeta<T['length'], keyof T[number]>; | ||
type RowList<T extends MaybeRow[]> = T & Iterable<NonNullable<T[number]>> & ResultQueryMeta<T['length'], keyof T[number]>; | ||
interface PendingQuery<TRow extends readonly Row[]> extends Promise<RowList<TRow>> { | ||
stream(cb: (row: TRow[number], result: ExecutionResult<TRow[number]>) => void): Promise<ExecutionResult<keyof TRow[number]>>; | ||
cursor(cb: (row: TRow[number]) => void): Promise<ExecutionResult<keyof TRow[number]>>; | ||
cursor(size: 1, cb: (row: TRow[number]) => void): Promise<ExecutionResult<keyof TRow[number]>>; | ||
cursor(size: number, cb: (rows: TRow) => void): Promise<ExecutionResult<keyof TRow[number]>>; | ||
interface PendingQuery<TRow extends MaybeRow[]> extends Promise<RowList<TRow>> { | ||
stream(cb: (row: NonNullable<TRow[number]>, result: ExecutionResult<NonNullable<TRow[number]>>) => void): Promise<ExecutionResult<keyof NonNullable<TRow[number]>>>; | ||
cursor(cb: (row: NonNullable<TRow[number]>) => void): Promise<ExecutionResult<keyof NonNullable<TRow[number]>>>; | ||
cursor(size: 1, cb: (row: NonNullable<TRow[number]>) => void): Promise<ExecutionResult<keyof NonNullable<TRow[number]>>>; | ||
cursor(size: number, cb: (rows: NonNullable<TRow[number]>[]) => void): Promise<ExecutionResult<keyof NonNullable<TRow[number]>>>; | ||
} | ||
@@ -301,3 +313,3 @@ | ||
*/ | ||
<T extends Row | Row[] = Row>(template: TemplateStringsArray, ...args: SerializableParameter[]): PendingQuery<T extends Row[] ? T : T[]>; | ||
<T extends any[] = Row[]>(template: TemplateStringsArray, ...args: SerializableParameter[]): PendingQuery<AsRowList<T>>; | ||
@@ -327,4 +339,4 @@ /** | ||
end(options?: { timeout?: number }): Promise<void>; | ||
file<T extends Row | Row[] = Row>(path: string, options?: { cache?: boolean }): PendingQuery<T extends Row[] ? T : T[]>; | ||
file<T extends Row | Row[] = Row>(path: string, args: SerializableParameter[], options?: { cache?: boolean }): PendingQuery<T extends Row[] ? T : T[]>; | ||
file<T extends any[] = Row[]>(path: string, options?: { cache?: boolean }): PendingQuery<AsRowList<T>>; | ||
file<T extends any[] = Row[]>(path: string, args: SerializableParameter[], options?: { cache?: boolean }): PendingQuery<AsRowList<T>>; | ||
json(value: any): Parameter; | ||
@@ -340,3 +352,3 @@ listen(channel: string, cb: (value?: string) => void): PendingRequest; | ||
}; | ||
unsafe<T extends Row | Row[] = any[]>(query: string, parameters?: SerializableParameter[]): PendingQuery<T extends Row[] ? T : T[]>; | ||
unsafe<T extends any[] = Row[]>(query: string, parameters?: SerializableParameter[]): PendingQuery<AsRowList<T>>; | ||
} | ||
@@ -343,0 +355,0 @@ |
76967
1796
678