如何最好地在Loopback 4应用程序中包含一次性脚本?

时间:2019-06-07 13:23:04

标签: node.js loopbackjs

我很困惑如何将一次性脚本作为Loopback 4项目的一部分运行,该项目为旧记录填充了一个值。例如。我想在用户记录中包括createdAt字段,并根据每个用户在系统中发布的第一条帖子的时间戳填写旧记录。

我尝试创建一个只运行一次才能更新所有这些记录的组件。

export class OneTimeComponent implements Component {
    constructor(
      @repository(UserRepository)
      public userRepository : UserRepository,
    ){
      this.start()
    }

    async start(){
      const users = await this.userRepository.find();

      users.forEach( user => {
        // find first post for user
        // get date 
        // update user.createdAt with date
      })
    }

}

export async function run(args: string[]) {
  const app = new BlogApiApplication();

  app.component(OneTimeComponent);

  await app.boot();

  // Connectors usually keep a pool of opened connections,
  // this keeps the process running even after all work is done.
  // We need to exit explicitly.
  process.exit(0);
}

run(process.argv).catch(err => {
  console.error('Cannot run this', err);
  process.exit(1);
});

如果我运行app.start(),则脚本将尝试通过启动应用程序来运行,然后我得到一个错误消息,指出该地址正在使用中-显然是因为有2个应用程序正在运行。

然后我将使用打包脚本将此文件命名。

要访问存储库,这是否需要启动脚本?还是其他?

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

  

如何在Loopback 4项目中运行一次性脚本,该项目为旧记录填充值。例如。我想在用户记录中包含createdAt字段,并根据每个用户在系统中发布的第一条帖子的时间戳填写旧记录。

我个人将这些更改作为数据库模式迁移的一部分,请参阅LoopBack文档中的Database Migrations

大多数LoopBack连接器足够聪明,可以将createdAt字段添加到User表中(如果尚不存在)。填充值留给您实现。

引用Implement additional migration steps

  

在某些情况下,应用程序可能需要定义其他架构约束或使用预定义的模型实例为数据库添加种子。这可以通过重写mixin提供的migrateSchema方法来实现。

     

以下示例显示了如何在我们的Todo示例应用程序中执行此操作。

/** FILE: src/application.ts **/
import {TodoRepository} from './repositories';
// skipped: other imports

export class TodoListApplication extends BootMixin(
  ServiceMixin(RepositoryMixin(RestApplication)),
) {
  // skipped: the constructor, etc.

  async migrateSchema(options?: SchemaMigrationOptions) {
    // 1. Run migration scripts provided by connectors
    await super.migrateSchema(options);

    // 2. Make further changes. When creating predefined model instances,
    // handle the case when these instances already exist.
    const todoRepo = await this.getRepository(TodoRepository);
    const found = await todoRepo.findOne({where: {title: 'welcome'}});
    if (found) {
      todoRepo.updateById(found.id, {isComplete: false});
    } else {
      await todoRepo.create({title: 'welcome', isComplete: false});
    }
  }
}
  

我尝试创建一个仅运行一次即可更新所有这些记录的组件。   (...)   要访问存储库,这是否需要启动脚本?还是其他?

如果您不想通过运行npm run migrate显式迁移数据库架构和数据,则可以将应用程序修改为作为导出的autoMigrate函数的一部分自动调用main

引用Auto-update database at start

  

要在应用程序启动时自动更新数据库架构,请修改主脚本以在应用程序启动(所有存储库均已注册)之后但实际启动之前执行app.migrateSchema()

/** FILE: src/index.ts **/

export async function main(options: ApplicationConfig = {}) {
  const app = new TodoListApplication(options);
  await app.boot();
  await app.migrateSchema();
  await app.start();

  const url = app.restServer.url;
  console.log(`Server is running at ${url}`);

  return app;
}

最后一个选择是利用生命周期观察者(在LoopBack v3中也称为“启动脚本”)-请参见Life cycle events

  1. 通过运行lb4 observer(请参阅Life cycle observer generator)来折叠新的观察者。

  2. 修改观察者类的构造函数,以注入要使用的模型存储库。

  3. 修改start方法以执行所需的数据库更改。

相关问题