1
0
Fork 0
mirror of synced 2024-09-29 16:51:33 +13:00

Getting basic pouch replacement working.

This commit is contained in:
mike12345567 2022-11-08 16:32:13 +00:00
parent 3014558803
commit b89588af51
3 changed files with 69 additions and 43 deletions

View file

@ -2,8 +2,7 @@ import Nano from "nano"
import { AnyDocument } from "@budibase/types" import { AnyDocument } from "@budibase/types"
import { getCouchInfo } from "./couch" import { getCouchInfo } from "./couch"
import { directCouchCall } from "./utils" import { directCouchCall } from "./utils"
import { ReadStream, WriteStream } from "fs" import { getPouchDB } from "../db"
import { dangerousGetDB } from "../db"
export type PouchLikeOpts = { export type PouchLikeOpts = {
skip_setup?: boolean skip_setup?: boolean
@ -20,10 +19,6 @@ export type QueryOpts = {
keys?: string[] keys?: string[]
} }
export type DumpOpts = {
filter?: (doc: AnyDocument) => boolean
}
export class PouchLike { export class PouchLike {
public readonly name: string public readonly name: string
private static nano: Nano.ServerScope private static nano: Nano.ServerScope
@ -32,13 +27,21 @@ export class PouchLike {
constructor(dbName: string, opts?: PouchLikeOpts) { constructor(dbName: string, opts?: PouchLikeOpts) {
this.name = dbName this.name = dbName
this.pouchOpts = opts || {} this.pouchOpts = opts || {}
if (!PouchLike.nano) {
PouchLike.init()
}
} }
static init() { static init() {
const couchInfo = getCouchInfo() const couchInfo = getCouchInfo()
this.nano = Nano({ PouchLike.nano = Nano({
url: couchInfo.url, url: couchInfo.url,
cookie: couchInfo.cookie, requestDefaults: {
headers: {
Authorization: couchInfo.cookie,
},
},
parseUrl: false,
}) })
} }
@ -56,16 +59,30 @@ export class PouchLike {
return PouchLike.nano.db.use(this.name) return PouchLike.nano.db.use(this.name)
} }
async info() {} private async updateOutput(fnc: any) {
try {
return await fnc()
} catch (err: any) {
if (err.statusCode) {
err.status = err.statusCode
}
throw err
}
}
async info() {
const db = PouchLike.nano.db.use(this.name)
return db.info()
}
async get(id: string) { async get(id: string) {
const db = await this.checkSetup() const db = await this.checkSetup()
return await db.get(id) return this.updateOutput(() => db.get(id))
} }
async remove(id: string, rev: string) { async remove(id: string, rev: string) {
const db = await this.checkSetup() const db = await this.checkSetup()
return await db.destroy(id, rev) return this.updateOutput(() => db.destroy(id, rev))
} }
async put(document: AnyDocument) { async put(document: AnyDocument) {
@ -73,23 +90,23 @@ export class PouchLike {
throw new Error("Cannot store document without _id field.") throw new Error("Cannot store document without _id field.")
} }
const db = await this.checkSetup() const db = await this.checkSetup()
return await db.insert(document) return this.updateOutput(() => db.insert(document))
} }
async bulkDocs(documents: AnyDocument[]) { async bulkDocs(documents: AnyDocument[]) {
const db = await this.checkSetup() const db = await this.checkSetup()
return await db.bulk({ docs: documents }) return this.updateOutput(() => db.bulk({ docs: documents }))
} }
async allDocs(params: QueryOpts) { async allDocs(params: QueryOpts) {
const db = await this.checkSetup() const db = await this.checkSetup()
return await db.fetch({ keys: [] }, params) return this.updateOutput(() => db.list(params))
} }
async query(viewName: string, params: QueryOpts) { async query(viewName: string, params: QueryOpts) {
const db = await this.checkSetup() const db = await this.checkSetup()
const [database, view] = viewName.split("/") const [database, view] = viewName.split("/")
return await db.view(database, view, params) return this.updateOutput(() => db.view(database, view, params))
} }
async destroy() { async destroy() {
@ -97,37 +114,47 @@ export class PouchLike {
await PouchLike.nano.db.destroy(this.name) await PouchLike.nano.db.destroy(this.name)
} catch (err: any) { } catch (err: any) {
// didn't exist, don't worry // didn't exist, don't worry
if (err.status === 404) { if (err.statusCode === 404) {
return return
} else { } else {
throw err throw { ...err, status: err.statusCode }
} }
} }
} }
async compact() { async compact() {
const db = await this.checkSetup() const db = await this.checkSetup()
return await db.compact() return this.updateOutput(() => db.compact())
} }
// utilise PouchDB for this private doWithPouchDB(func: string) {
async dump(stream: WriteStream, params: DumpOpts) { const dbName = this.name
const pouch = dangerousGetDB(this.name) return async (args: any[]) => {
// @ts-ignore const pouch = getPouchDB(dbName)
return pouch.dump(stream, params) // @ts-ignore
return pouch[func](...args)
}
} }
// utilise PouchDB for this // All below functions are in-frequently called, just utilise PouchDB
async load(stream: ReadStream) { // for them as it implements them better than we can
const pouch = dangerousGetDB(this.name) async dump(...args: any[]) {
// @ts-ignore return this.doWithPouchDB("dump")(args)
return pouch.load(stream)
} }
// pouch specific functions - indexes come from the pouchdb-find library async load(...args: any[]) {
async createIndex() {} return this.doWithPouchDB("load")(args)
}
async deleteIndex() {} async createIndex(...args: any[]) {
return this.doWithPouchDB("createIndex")(args)
}
async getIndexes() {} async deleteIndex(...args: any[]) {
return this.doWithPouchDB("createIndex")(args)
}
async getIndexes(...args: any[]) {
return this.doWithPouchDB("createIndex")(args)
}
} }

View file

@ -2,6 +2,7 @@ import * as pouch from "./pouch"
import env from "../environment" import env from "../environment"
import { PouchOptions, CouchFindOptions } from "@budibase/types" import { PouchOptions, CouchFindOptions } from "@budibase/types"
import PouchDB from "pouchdb" import PouchDB from "pouchdb"
import { PouchLike } from "../couch"
import { directCouchQuery } from "../couch" import { directCouchQuery } from "../couch"
export { directCouchQuery } from "../couch" export { directCouchQuery } from "../couch"
@ -38,10 +39,7 @@ export async function init(opts?: PouchOptions) {
initialised = true initialised = true
} }
// NOTE: THIS IS A DANGEROUS FUNCTION - USE WITH CAUTION export function getPouchDB(dbName: string, opts?: any): PouchDB.Database {
// this function is prone to leaks, should only be used
// in situations that using the function doWithDB does not work
export function dangerousGetDB(dbName: string, opts?: any): PouchDB.Database {
checkInitialised() checkInitialised()
if (env.isTest()) { if (env.isTest()) {
dbList.add(dbName) dbList.add(dbName)
@ -55,6 +53,13 @@ export function dangerousGetDB(dbName: string, opts?: any): PouchDB.Database {
return db return db
} }
// NOTE: THIS IS A DANGEROUS FUNCTION - USE WITH CAUTION
// this function is prone to leaks, should only be used
// in situations that using the function doWithDB does not work
export function dangerousGetDB(dbName: string, opts?: any): PouchLike {
return new PouchLike(dbName, opts)
}
// use this function if you have called dangerousGetDB - close // use this function if you have called dangerousGetDB - close
// the databases you've opened once finished // the databases you've opened once finished
export async function closeDB(db: PouchDB.Database) { export async function closeDB(db: PouchDB.Database) {
@ -79,11 +84,7 @@ export async function doWithDB(dbName: string, cb: any, opts = {}) {
const db = dangerousGetDB(dbName, opts) const db = dangerousGetDB(dbName, opts)
// need this to be async so that we can correctly close DB after all // need this to be async so that we can correctly close DB after all
// async operations have been completed // async operations have been completed
try { return await cb(db)
return await cb(db)
} finally {
await closeDB(db)
}
} }
export function allDbs() { export function allDbs() {

View file

@ -66,7 +66,6 @@ export const getPouch = (opts: any = {}) => {
const inMemory = require("pouchdb-adapter-memory") const inMemory = require("pouchdb-adapter-memory")
PouchDB.plugin(inMemory) PouchDB.plugin(inMemory)
POUCH_DB_DEFAULTS = { POUCH_DB_DEFAULTS = {
prefix: undefined,
// @ts-ignore // @ts-ignore
adapter: "memory", adapter: "memory",
} }
@ -74,7 +73,6 @@ export const getPouch = (opts: any = {}) => {
if (opts.onDisk) { if (opts.onDisk) {
POUCH_DB_DEFAULTS = { POUCH_DB_DEFAULTS = {
prefix: undefined,
// @ts-ignore // @ts-ignore
adapter: "leveldb", adapter: "leveldb",
} }