Relational pouch methods aren't available in Angular Service

117 Views Asked by At

I'm trying to get relational-pouch working, I'm able to set the schema but when I call the save function I get the error TypeError: this.rel.save is not a function

This is the setup:

import PouchDB from 'pouchdb-browser'
import find from 'pouchdb-find'
import rel from 'relational-pouch'

@Injectable({
    providedIn: 'root'
})
export class PouchDBService {

    public base_db: PouchDB.Database
    public rel

    constructor() {
        PouchDB.plugin(find)
        PouchDB.plugin(rel)
        this.base_db = new PouchDB('Eeeek')
        this.rel = this.base_db.setSchema(schema)
        this.rel.save('project', {
            name: 'George R. R. Martin', id: 1, books: [6, 7]
        })
    }
}

When I try to call this.rel.find(id) it seems to be ignoring the relational-pouch definition and using the pouch-find definition. So this.rel.find(id) results in Error: you must provide search parameters to find()

but

            this.db.rel.find({
                selector: {
                    type: this.type
                }
            })

works.

The dependencies seem fine, I'm stumped, any help greatly appreciated.

Thanks.

ps. using angular 12.

1

There are 1 best solutions below

2
RamblinRose On BEST ANSWER

You're not using the rel field as advertised. From the type declaration rel is defined as

interface RelDatabase<Content extends {} = {}> extends Database<Content> {
   rel: RelDB;
}

so I don't understand how this code is compiling
It's compiling because rel is implied as any

   public base_db: PouchDB.Database
   public rel
    . . . 
   this.rel = this.base_db.setSchema(schema)
   this.rel.save('project', {
      name: 'George R. R. Martin', id: 1, books: [6, 7]
   })

This is a benefit of Typescript, and would've saved you a ton of wonder:

public rel: PouchDB.RelDatabase;

This is what you're looking for (kinda)

   this.rel = this.base_db.setSchema(schema)
   this.rel.rel.save('project', {
      name: 'George R. R. Martin', id: 1, books: [6, 7]
   })

But that's awful to read - I recommend

export class PouchDBService {
   // why have a service if these are public...
   private db: PouchDB.Database;
   private rdb: PouchDB.RelDatabase;

Anyway the major takeaway here is to use explicit types. This is demonstrably correct:

db: PouchDB.Database;
rdb: PouchDB.RelDatabase;

async demoRelDb(dbName: string): Promise<any> {
    PouchDB.plugin(find).plugin(rel);
    this.db = new PouchDB(dbName);  
    this.rdb = this.db.setSchema([
        { singular: "author", plural: "authors", relations: { books: { hasMany: "book" } } },
        { singular: "book", plural: "books", relations: { author: { belongsTo: "author" } } },
    ]);
    
    await this.rdb.rel.save("author", {
        name: "George R. R. Martin",
        id: 1,
        books: [6, 7],
    });         
    let result await this.rdb.rel.find("author", 1);
    console.log(JSON.stringify(doc, undefined, 3));
}

OK great now you should be on your way. However I am warning people away from using this plugin as it appears practically abandoned, and issue #125 is a showstopper.

Until some maintenance happens - there are 16 pull requests spanning 2 years - I would not use it. If anything search for a viable fork.