I have individual MySQL databases per client, each database has the same tables so the schemas and models are the same between clients. I am writing my nodejs application in typescript using bookshelf to create the models. I have installed the knex and bookshelf node modules along with their ambient typings.
I have a script to create a client connection...
/config/database.ts:
import * as Knex from 'knex';
import * as Bookshelf from 'bookshelf';
export module MySql {
const host = 'HOST';
const user = 'USER';
const password = 'PASSWORD';
export function createClientConnection(client: number) {
return Bookshelf(Knex({
client: 'mysql',
connection: {
host: host,
user: user,
password: password,
database: `client-${client}`,
charset: 'utf8'
}
}));
}
}
I have two models that relate to each other...
/models/campaign.ts:
import * as Bookshelf from 'bookshelf';
export function campaign(bookshelf: Bookshelf) {
class Campaign extends bookshelf.Model<Campaign> {
get tableName() { return 'campaigns'; }
versions() {
return this.hasMany(/*CampaignVersion*/);
}
}
return new Campaign();
}
/models/campaign-version.ts:
import * as Bookshelf from 'bookshelf';
export function campaignVersion(bookshelf: Bookshelf) {
class CampaignVersion extends bookshelf.Model<CampaignVersion> {
get tableName() { return 'campaign_versions'; }
campaign() {
return this.belongsTo(/*Campaign*/);
}
}
return new CampaignVersion();
}
And I thought I would use it like this...
/bin/app.ts:
import {MySql} from '../config/database';
import {campaign} from '../models/campaign';
var clientConnection = MySql.createClientConnection(1);
var Campaign = campaign(clientConnection);
Campaign.where('id', 1).fetch({withRelated: ['versions']}).then(campaign => console.log(campaign));
I have found a solution that works but it could soon become very convoluted as every model is defined in one file...
You can define each model class within a client class where the constructor excepts a bookshelf connection. This way the type definitions follow through to use.
/config/database.ts:
import * as Knex from 'knex';
import * as Bookshelf from 'bookshelf';
export module MySql {
const host = 'HOST';
const user = 'USER';
const password = 'PASSWORD';
export function createClientConnection(client: number) {
return Bookshelf(Knex({
client: 'mysql',
connection: {
host: host,
user: user,
password: password,
database: `client-${client}`,
charset: 'utf8'
}
}));
}
export class Client {
constructor(private _connection: Bookshelf) {}
get models() {
class Campaign extends this._connection.Model<Campaign> {
get tableName() { return 'campaigns'; }
versions() {
return this.hasMany(CampaignVersion);
}
}
class CampaignVersion extends this._connection.Model<CampaignVersion> {
get tableName() { return 'campaign_versions'; }
campaign() {
return this.belongsTo(Campaign);
}
}
return {
Campaign: Campaign,
CampaignVersion: CampaignVersion
};
}
}
}
/bin/app.ts:
import {MySql} from '../config/database';
var clientConnection = MySql.createClientConnection(1);
var client = new MySql.Client(clientConnection);
var campaign = new client.models.Campaign();
campaign.where('id', 1).fetch({withRelated: ['versions']}).then(campaign => console.log(campaign));