ThomasReggi
ThomasReggi

Reputation: 59365

Modular way to import object instances

I'm looking for a way to define object instances in javascript files, like this.

Below's content is in a file serviceKnex.js.

import Knex from 'knex'

var knex = Knex({
  client: 'mysql',
  connection: {
    host     : '127.0.0.1',
    user     : 'your_database_user',
    password : 'your_database_password',
    database : 'myapp_test'
  },
  migrations: {
    tableName: 'migrations'
  }
})

export default knex

Then be able to import serviceKnex.js and use it directly in a function like this.

import serviceKnex from '../serviceKnex'

export async function createItem () {
  return serviceKnex('table')
    .insert({'hello', 'world'})
}

However, I'd like to make the above code a npm module, that can ideally receive serviceKnex the object as an argument. I still want a consumer of this function to be able to alter which knex object instance they are using.

Is there any way to allow a simple modular, swappable interface for importing and using global object instances?

I'm trying to prevent myself from writing functions like this, that pass in the knex object.

export async function createItem (knex) {
  return knex('table')
    .insert({'hello', 'world'})
}

Upvotes: 3

Views: 697

Answers (2)

m-a-r-c-e-l-i-n-o
m-a-r-c-e-l-i-n-o

Reputation: 2672

Have you considered prototypical inheritance? Similar to how jQuery is built, something along the lines of:

function serviceKnex (knexInstance) {
  return new init(knexInstance)
}

function init (knexInstance) {
  this.instance = knexInstance
  return this
}

init.prototype = {
  createItem () {
    return this.instance('table').insert({'hello', 'world'})
  }
}

export default serviceKnex

Then your users would be able to work with different instances.

import Knex from 'knex'
import serviceKnex from 'serviceKnex'

const knexOne = Knex({})
const knexTwo = Knex({})

const serviceKnexOne = serviceKnex(knexOne)
const serviceKnexTwo = serviceKnex(knexTwo)

serviceKnexOne.createItem()
serviceKnexTwo.createItem()

EDIT: Or with ES6 classes as this answer points out.

Upvotes: 1

Originato
Originato

Reputation: 346

You could create a wrapper class which takes serviceKnex as an argument in the constructor, and additionally provides a setKnex() method.

Example:

export default class DatabaseClass {
    constructor(serviceKnex) {
        this.serviceKnex = serviceKnex;
    }

    setKnex(knexService) {
        this.serviceKnex = serviceKnex;
    }

    async createItem() {
        return this.serviceKnex('table')
            .insert({'hello', 'world'});
    }
}

Then you would use it like this:

import serviceKnex from '../serviceKnex';
import DatabaseClass from 'database-class';

var dbObject = new DatabaseClass(knexService);
dbObject.createItem();

If you don't want to use classes you can add a setter function in the NPM module code which modifies the global variable, but I personally prefer the wrapper class approach.

Upvotes: 2

Related Questions