这是我几个月来一直在思考的一个问题:
我正在寻找一种优雅、一致的方式来初始化表,第一次创建表时,使用feathin foams-knex
我正在使用feathers.js(5.0.5)+feathers-knex(8.0.1)+knex(2.4.2) 请注意,我已经用羽毛版本 4 解决了我的问题
我有一个由提供的生成器生成的服务:
...
const { Rootdir } = require('./rootdir.class');
const createModel = require('../../models/rootdir.model');
const hooks = require('./rootdir.hooks');
module.exports = function (app) {
const options = {
// id: 'id', // Optional
Model: createModel(app),
paginate: app.get('paginate')
};
app.use('/rootdir', new Rootdir(options, app));
const service = app.service('rootdir');
service.hooks(hooks);
}
rootdir.model.js 看起来像:
module.exports = function (app) {
const db = app.get('knexClient');
const tableName = 'rootdir';
db.schema.hasTable(tableName).then(exists => {
if (!exists) {
db.schema.createTable(tableName, table => {
table.string('id').primary();
table.string('dir');
})
.then(() => {
debug(`Created ${tableName} table`)
app.emit(`table.${tableName}.created`)
})
.catch(e => console.error(`Error creating ${tableName} table`, e));
}
// At this point the table is not yet created!
});
return db;
};
rootdir.class.js 中没有什么特别的 - 只是生成器发出的标准内容:
const { Service } = require('feathers-knex');
exports.Rootdir = class Rootdir extends Service {
constructor(options) {
super({
...options,
name: 'rootdir'
});
}
};
我需要初始化 - 即预加载一些数据 - 第一次创建表“rootdir”时。 这必须在创建服务之后但在处理第一个请求之前发生。 因此,当它遇到我的“初始化”代码时,需要完全解决承诺 db.schema.hasTable(db.schema.createTable(...)) 。
我发现解决这个问题的唯一方法是:
app.on('table.rootdir.created' , async () => {
await populateRootdirTable()
})
但是,我觉得应该有一种方法可以拦截以下时刻:
我尝试过的:
我希望 createModel 可以返回一个承诺,然后该承诺将在服务中的“某个地方”得到解决。但不,服务需要“初始化的 knex 对象”作为“模型”属性。 因此,如果我尝试传递一个承诺而不是对 knex 的引用,代码就会失败。
我尝试将初始化代码放入应用程序设置挂钩中:
app.hooks({
setup: [
async function setupHook(context,next) {
debug("setup hook called (before)");
await next();
const rootdirService = context.app.service('rootdir');
const ret = await rootdirService.find({
query: {
$limit: 0
}
});
console.log("ret:",ret);
}
],
teardown: []
}
)
但是当代码到达钩子时,即使服务存在,表还没有创建 (只是为了正确性:它在您第二次启动应用程序时确实存在,因为那时该表已经创建;但第一次失败)
我应该把这个“初始化”代码放在哪里?我应该如何触发它? 或者说,我的想法完全错误吗?
由于您使用的是 SQL,表创建和数据初始化是通过 迁移文件 完成的。在普通的 Feathers 5 应用程序中,您可以使用以下命令运行迁移:
npm run migrate
指南中显示了如何创建迁移的示例。 创建表后,在迁移中您还可以通过导入来使用
app
对象:
import type { Knex } from 'knex'
import { app } from '../src/app'
export async function up(knex: Knex): Promise<void> {
// create tables or make changes
app.service('users').create(/* create admin user here */)
}