diff --git a/index.ts b/index.ts index 9c1e9b1..4728162 100644 --- a/index.ts +++ b/index.ts @@ -35,7 +35,7 @@ export const GENERIC_LIST_VIEW = { /** * Configures a Davenport client and database by validating the CouchDB version, creating indexes and design documents, and then returning a client to interact with the database. */ -export async function configureDatabase(databaseUrl: string, configuration: DatabaseConfiguration, options?: ClientOptions): Promise> { +export async function configureDatabase(databaseUrl: string, configuration: DatabaseConfiguration, options?: ClientOptions): Promise> { const dbInfo = await Axios.get(databaseUrl); if (!isOkay(dbInfo)) { @@ -130,7 +130,7 @@ export async function configureDatabase(databaseUrl: string, })); } - return new Client(databaseUrl, configuration.name, options); + return new Client(databaseUrl, configuration.name, options); } /** @@ -232,7 +232,9 @@ export class Client { /** * Counts all documents by the given selector. Warning: this uses more memory than a regular count, because it needs to pull in the _id field of all selected documents. For large queries, it's better to create a dedicated view and use the .view function. */ - public async countBySelector(selector: Partial): Promise { + public async countBySelector(selector: DocSelector): Promise + public async countBySelector(selector: Partial): Promise + public async countBySelector(selector): Promise { const result = await this.find({ fields: ["_id"], selector, @@ -338,7 +340,7 @@ export class Client { /** * Checks that a document that matches the field value exists. */ - public async existsBySelector(value, field: keyof T): Promise { + public async existsByFieldValue(value, field: keyof T): Promise { const findResult = await this.find({ fields: ["_id"], limit: 1, @@ -350,6 +352,19 @@ export class Client { return findResult.length > 0; } + /** + * Checks that a document matching the selector exists. + */ + public async existsBySelector(selector: DocSelector): Promise { + const findResult = await this.find({ + fields: ["_id"], + limit: 1, + selector: selector as any, + }); + + return findResult.length > 0; + } + /** * Executes a view with the given designDocName and viewName. */ @@ -468,7 +483,7 @@ export interface FindOptions { limit?: number; skip?: number; use_index?: Object; - selector: Partial; + selector: Partial | DocSelector; } export interface CouchDBView { @@ -497,4 +512,38 @@ export interface ClientOptions { * Whether the Davenport client should log warnings. */ warnings: boolean; -} \ No newline at end of file +} + +export interface PropSelector { + /** + * Property is equal to this value. + */ + $eq?: any; + + /** + * Property is not equal to this value. + */ + $ne?: any; + + /** + * Property is greater than this value. + */ + $gt?: any; + + /** + * Property is greater than or equal to this value. + */ + $gte?: any; + + /** + * Property is less than this value. + */ + $lt?: any; + + /** + * Property is lesser than or equal to this value. + */ + $lte?: any; +} + +export type DocSelector = Partial>; \ No newline at end of file diff --git a/package.json b/package.json index 443361b..f03a097 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "davenport", - "version": "1.2.0", + "version": "2.0.0", "description": "A CouchDB client for simplifying common tasks like get, list, create, update and delete. Comes complete with full TypeScript definitions.", "main": "bin/index.js", "typings": "bin/index.d.ts", diff --git a/tests/index.ts b/tests/index.ts index 1967cf5..3b84bbd 100644 --- a/tests/index.ts +++ b/tests/index.ts @@ -1,6 +1,6 @@ import inspect from "logspect"; import { Expect, AsyncTest, Timeout, TestFixture } from "alsatian"; -import Client, { configureDatabase, CouchDoc, DesignDocConfiguration } from "../"; +import Client, { configureDatabase, CouchDoc, DesignDocConfiguration, PropSelector } from "../"; const DB_URL = "http://localhost:5984"; const DB_NAME = "davenport_tests"; @@ -168,6 +168,29 @@ export class DavenportTestFixture { Expect(count).toBe(3); } + @AsyncTest("Davenport.count with selector indexes") + @Timeout(5000) + public async countWithSelectorIndexesTest() { + const client = new Client(DB_URL, DB_NAME); + const uuid = `a-unique-string-${Date.now()}`; + + for (let i = 0; i < 3; i++) { + await client.post({ + bar: i, + foo: i + 1, + hello: uuid + }) + }; + + const count = await client.countBySelector({ + hello: { + $eq: uuid + } + }); + + Expect(count).toBe(3); + } + @AsyncTest("Davenport.delete") @Timeout(5000) public async deleteTest() { @@ -202,6 +225,21 @@ export class DavenportTestFixture { Expect(exists).toBe(true); } + @AsyncTest("Davenport.exists with field value") + @Timeout(5000) + public async existsWithFieldValueTest() { + const client = new Client(DB_URL, DB_NAME); + const uuid = `a-unique-string-${Date.now()}`; + const createResult = await client.post({ + bar: 5, + foo: 4, + hello: uuid, + }) + const exists = await client.existsByFieldValue(uuid, "hello"); + + Expect(exists).toBe(true); + } + @AsyncTest("Davenport.exists with selector") @Timeout(5000) public async existsWithSelectorTest() { @@ -212,7 +250,11 @@ export class DavenportTestFixture { foo: 4, hello: uuid, }) - const exists = await client.existsBySelector(uuid, "hello"); + const exists = await client.existsBySelector({ + hello: { + $eq: uuid + } + }); Expect(exists).toBe(true); }