hapipal / boilerplate

A friendly, proven starting place for your next hapi plugin or deployment
https://hapipal.com
183 stars 27 forks source link

Cannot migrate/rollback in tests #57

Closed ozum closed 6 years ago

ozum commented 6 years ago

Hi,

I created a project using boilerplate and schwifty. When I try to use server.knex().migrate in test file, it is looking project/migrations instead of project/lib/migrations and I got following error:

ENOENT: no such file or directory, scandir '.....project/migrations

test/01-test.js

const Code = require("code");
const Lab = require("lab");
const Server = require("../server");
const Package = require("../package.json");

const { describe, it, beforeEach, before } = (exports.lab = Lab.script());
const { expect } = Code;

let server;

before(async () => {
  server = await Server.deployment();
});

beforeEach(async () => {
  const knex = await server.knex();
  await knex.migrate.rollback();
  await knex.migrate.latest();
  await knex.seed.run();
});

describe("Deployment", () => {
  it("registers the main plugin.", async () => {
    expect(server.registrations[Package.name]).to.exist();
  });
});

lib/plugins/schwifty There is no lib like it is swallowed: Produces ENOENT: no such file or directory, scandir '.....project/migrations

module.exports = {
  plugins: {
    options: {
      migrationsDir: `${__dirname}/../migrations`,
    },
  },
};

Additional notes:

Thanks

ozum commented 6 years ago

Currently I solved it by adding options.$base.knex.migrations.directory key of schwifty plugin inserver/manifest.js.

I'm not sure if this is a suggested method, because migrations directory is defined in two places now:

Some opinion would be great.

devinivy commented 6 years ago

Good question! First, the reason that the migrationsDir is defined within the plugin is because schwifty allows you to have multiple plugins, each with different migrations directories, using the same knex instance. So, a single knex instance can't necessarily capture all that information.

Luckily you can pass a directory right to those two functions: knex.migrate.latest({ directory }) and knex.migrate.rollback({ directory }). I suggest doing that in your tests rather than duplicating the configuration both places. If you do want to configure the migrations directory on the knex instance, then also pass the directory to your app as a plugin option (within the manifest) so you can configure it in lib/plugins/schwifty.js. That way, the directory configuration is at least centralized in the manifest.

ozum commented 6 years ago

@devinivy
By the way, I assumed server/manifest.js configuration is used if module is used as server/app. If we use module as a hapi plugin it is not used. Am I correct?

devinivy commented 6 years ago

Yeah, exactly :) The contents of lib/ should be able to travel to other app/servers without any issue. We even have an article about this idea of server/plugin separation.

ozum commented 6 years ago

Thanks.

schwifty allows you to have multiple plugins, each with different migrations directories, using the same knex instance

I also read about this in schwifty API. However, it is not so clear and does not sampled in articles of hapipal. Could you give a simple example how to setup this?

devinivy commented 6 years ago

Both the root server (server/) and the application plugin (lib/) register schwifty.

The root server's schwifty configuration defines a knex instance for the root server. That knex instance is inherited by your application plugin, simply because your plugin does not define its own knex instance (as explained in these docs). Any other plugin on your server that doesn't configure a knex instance will also "inherit" the root server's knex instance. In this way, many application plugins on one server may share the same knex instance.

Your application plugin registers schwifty as well, using the file lib/plugins/schwifty.js. In that file schwifty is configured with a migrationsDir. This is the migrations directory only for your application plugin. Another plugin may also register schwifty and specify its own migrationsDir. In short, each plugin may have its own migrationsDir by registering schwifty and passing a different migrations directory configuration.

Every time a plugin registers schwifty, that plugin is setting schwifty configuration for itself. Schwifty takes full advantage of hapi's advanced plugin features to enforce plugin boundaries, which is in line with the way this boilerplate keeps plugin and server separated. In short, two plugins created with schwifty and the boilerplate should be able to be deployed together (both registered on the same server) without making any significant changes to application code :)

ozum commented 6 years ago

A-ha. Thanks for clarification and your time.

devinivy commented 6 years ago

You're welcome! As always, feel free to suggest improvements to documentation 👍