如何在 TypeScript 中使用不同的 Bookshelf.js 连接动态创建 [有关系] 的模型?

How can I create models on the fly [that have relations] using different Bookshelf.js connections in TypeScript?

我每个客户端都有单独的 MySQL 数据库,每个数据库都有相同的表,因此模式和模型在客户端之间是相同的。我正在使用书架在打字稿中编写我的 nodejs 应用程序来创建模型。我已经安装了 knex 和 bookshelf 节点模块及其环境类型。

我有一个创建客户端连接的脚本...

/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'
            }
        }));
    }
}

我有两个相互关联的模型...

/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();
}

我想我会像这样使用它...

/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));

我找到了一个可行的解决方案,但它很快就会变得非常复杂,因为每个模型都在一个文件中定义...

您可以在客户端 class 中定义每个模型 class,其中构造函数不包括书架连接。这样类型定义就可以使用了。

/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));