diff --git a/package.json b/package.json index d522ba0..967f310 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ ], "files": [ "sql.js", + "pg.js", "types/index.d.ts" ], "types": "types", diff --git a/pg.js b/pg.js new file mode 100644 index 0000000..af32081 --- /dev/null +++ b/pg.js @@ -0,0 +1,8 @@ +const sql = require('./sql') + +const sqlPG = db => async (...args) => { + const { rows } = await db.query(sql(...args)) + return rows +} + +module.exports = sqlPG diff --git a/readme.md b/readme.md index f8f3214..c373258 100644 --- a/readme.md +++ b/readme.md @@ -162,9 +162,11 @@ Since we ❤️ [node-postgres](https://github.com/brianc/node-postgres) so much ```js // long-version +const sql = require('@sequencework/sql') const { rows: movies } = await db.query(sql`select * from movies`) // equivalent, short-version +const sql = require('@sequencework/sql/pg') // ⚠️ we import @sequencework/sql/pg const movies = await sql(db)`select * from movies` // sql(db) just calls db.query so db can be a client or a pool :) ``` @@ -172,6 +174,8 @@ const movies = await sql(db)`select * from movies` You can then rewrite the previous `listMoviesByYear` function in a much more concise way 😎 ```js +const sql = require('@sequencework/sql/pg') // ⚠️ we import @sequencework/sql/pg + const listMoviesByYear = async (db, yearRange) => sql(db)` select * from movies where diff --git a/sql.js b/sql.js index 4586050..224379a 100644 --- a/sql.js +++ b/sql.js @@ -32,21 +32,7 @@ const sqlText = (count, chains, expressions) => { } } -const sql = (chains, ...expressions) => { - // if first argument is a db, then the tag is used like this : - // sql(db)`...` - if (chains.query) { - const db = chains - return async (chains, ...expressions) => { - const { rows } = await db.query(sqlText(1, chains, expressions)) - return rows - } - } - - // basic usage - // sql`...` - return sqlText(1, chains, expressions) -} +const sql = (chains, ...expressions) => sqlText(1, chains, expressions) class SqlContainer { constructor(chains, expressions) { diff --git a/test/pg.test.js b/test/pg.test.js new file mode 100644 index 0000000..a8f9654 --- /dev/null +++ b/test/pg.test.js @@ -0,0 +1,16 @@ +const sqlPG = require('../pg') + +test('shorthand for node-postgres', async () => { + const sampleBooks = ['book1', 'book2'] + const db = { + query: async ({ text, values }) => { + if (text === 'select * from books') { + return { rows: sampleBooks } + } + return { rows: [] } + } + } + + const books = await sqlPG(db)`select * from books` + expect(books).toBe(sampleBooks) +}) diff --git a/test/sql.test.js b/test/sql.test.js index 97570b7..98bb479 100644 --- a/test/sql.test.js +++ b/test/sql.test.js @@ -77,21 +77,6 @@ test('imbricated sql tags (2 levels)', () => { expect(query.values[2]).toBe(expr2) }) -test('shorthand for node-postgres', async () => { - const sampleBooks = ['book1', 'book2'] - const db = { - query: async ({ text, values }) => { - if (text === 'select * from books') { - return { rows: sampleBooks } - } - return { rows: [] } - } - } - - const books = await sql(db)`select * from books` - expect(books).toBe(sampleBooks) -}) - test('json as query parameter', () => { const jsonValue = { _sql: { some: 'data' }, item: 'value' } const query = sql`select obj from movies where obj = ${jsonValue}` diff --git a/types/index.d.ts b/types/index.d.ts index 85b45ce..b8b49cd 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,30 +1,36 @@ // TypeScript Version: 2.9 -export = sql - -declare function sql(chains: { - readonly query: ( - queryExpression: sql.QueryConfig - ) => Promise<{ - rows: any[] - }> -}): (chains: ReadonlyArray, ...expressions: any[]) => Promise - -declare function sql( - chains: ReadonlyArray, - ...expressions: any[] -): sql.QueryConfig - -declare namespace sql { +declare namespace sqlElements { interface QueryConfig { _sql?: SqlContainer text: string values: any[] } + + class SqlContainer { + constructor(chains: ReadonlyArray, expressions: any[]) + readonly chains: ReadonlyArray + readonly expressions: any[] + } } -declare class SqlContainer { - constructor(chains: ReadonlyArray, expressions: any[]) - readonly chains: ReadonlyArray - readonly expressions: any[] +declare module '@sequencework/sql' { + function sql( + chains: ReadonlyArray, + ...expressions: any[] + ): sqlElements.QueryConfig + + export = sql +} + +declare module '@sequencework/sql/pg' { + function sqlPG(chains: { + readonly query: ( + queryExpression: sqlElements.QueryConfig + ) => Promise<{ + rows: any[] + }> + }): (chains: ReadonlyArray, ...expressions: any[]) => Promise + + export = sqlPG } diff --git a/types/test.ts b/types/test.ts index 288bdfd..73a0926 100644 --- a/types/test.ts +++ b/types/test.ts @@ -2,6 +2,7 @@ // See https://github.com/DefinitelyTyped/DefinitelyTyped import sql = require('@sequencework/sql') +import sqlPG = require('@sequencework/sql/pg') const yearRange = [1983, 1992] @@ -61,7 +62,7 @@ const db = { } } const getBooks = async (): Promise => { - const rows = await sql(db)`select * from books` + const rows = await sqlPG(db)`select * from books` return rows as string[] } // $ExpectType Promise diff --git a/types/tsconfig.json b/types/tsconfig.json index e6f2740..7410f85 100644 --- a/types/tsconfig.json +++ b/types/tsconfig.json @@ -11,6 +11,9 @@ // If the library is an external module (uses `export`), this allows your test file to import "mylib" instead of "./index". // If the library is global (cannot be imported via `import` or `require`), leave this out. "baseUrl": ".", - "paths": { "@sequencework/sql": ["."] } + "paths": { + "@sequencework/sql": ["."], + "@sequencework/sql/pg": ["./pg"] + } } }