Skip to content

Commit

Permalink
feat: add option to getTestDatabase to pass TypeORM config object (#7)
Browse files Browse the repository at this point in the history
This feature supports projects that use a TypeScript `ormconfig.ts` file. Currently originate-scripts is not able to read TypeORM configuration from TypeScript modules which is required to get `getTestDatabase` to run migrations for you. If you use a TypeScript configuration module then you can import it in your test, and pass the exported value to `getTestDatabase`. For example:

```ts
const { stop } = await getTestDatabase({
  // We use a callback to delay evaluating `ormconfig` until after
  // `process.env.DATABASE_URL` is set by `getTestDatabase`.
  typeormConfig: async () => (await import('../../ormconfig')).default,
})
```

Note that it is important to delay evaluating `ormconfig.ts` until **after** `getTestDatabase` has set the `process.env.DATABASE_URL` environment variable. The example above demonstrates using the `await` operator to import configuration in a callback.

To make that example work your `ormconfig.ts` module should export its configuration object as the default export using `export default config`.
  • Loading branch information
Jesse Hallett authored Apr 13, 2022
1 parent 3669a79 commit 4629a38
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 16 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@
"semantic-release": "^17.3.0",
"ts-jest": "^26.4.4",
"ts-node": "^9.1.1",
"typescript": "^4.1.3"
"typescript": "^4.6.3"
},
"peerDependencies": {
"@nestjs/common": ">=7.6.0",
"supertest": ">=4.0.0",
"typeorm": ">=0.2.29"
"typeorm": "^0.2.29"
}
}
30 changes: 25 additions & 5 deletions src/getTestDatabase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
Config,
startPostgresContainer,
} from "@originate/docker-await-postgres";
import { createConnection } from "typeorm";
import type { ConnectionOptions } from "typeorm";

export interface Options {
/**
Expand All @@ -14,6 +14,17 @@ export interface Options {
* If true, connect and run migrations according to configuration in `ormconfig.js`
*/
runMigrations?: boolean;

/**
* Configuration options for TypeORM. TypeORM is invoked if `runMigrations` is
* set to `true`. If this configuration is not provided then configuration will
* be read from `ormconfig.js` instead.
*
* originate-scripts is currently unable to load TypeScript ormconfig modules.
* If you use TypeScript for your TypeORM configuration then source your
* `ormconfig.ts` file, and pass the exported object as `typeormConfig` here.
*/
typeormConfig?: () => Promise<ConnectionOptions>;
}

/**
Expand All @@ -23,11 +34,13 @@ export interface Options {
*
* @param options.image Docker image to run; e.g. `"postgres:12"` (default: "postgres:latest")
* @param options.runMigrations If true, connect and run migrations according to configuration in `ormconfig.js` (default: true)
* @param options.typeormConfig Async callback that returns configuration options for TypeORM. If you use an `ormconfig.ts` file you should import it in the callback using the `import` operator so that configuration is evaluated *after* `process.env.DATABASE_URL` is set. If not set config for migrations will be read from `ormconfig.js`.
*/
export async function getTestDatabase({
image = "postgres:latest",
runMigrations = true,
}: Options): Promise<{
typeormConfig,
}: Options = {}): Promise<{
stop: () => Promise<void>;
}> {
const config: Config = {
Expand All @@ -41,10 +54,17 @@ export async function getTestDatabase({
process.env.DATABASE_URL = `postgres://${config.user}:${config.password}@localhost:${port}/${config.database}`;

if (runMigrations) {
const conn = await createConnection();
await conn.runMigrations();
await conn.close();
await runTypeormMigrations(await typeormConfig?.());
}

return { stop };
}

async function runTypeormMigrations(typeormConfig?: ConnectionOptions) {
const typeorm = await import("typeorm");
const conn = typeormConfig
? await typeorm.createConnection(typeormConfig)
: await typeorm.createConnection();
await conn.runMigrations();
await conn.close();
}
8 changes: 4 additions & 4 deletions src/originate-scripts/commands/dbStart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,18 @@ async function createContainer(opts: {
Tty: false,
});
} catch (err) {
throw new Error(
`failed to create a new database container: ${err.message}`
);
const message = err instanceof Error ? err.message : "";
throw new Error(`failed to create a new database container: ${message}`);
}
}

async function startNew(container: Dockerode.Container): Promise<void> {
try {
await container.start();
} catch (err) {
const message = err instanceof Error ? err.message : "";
throw new Error(
`created a new container, but there was an error starting it: ${err.message}`
`created a new container, but there was an error starting it: ${message}`
);
}
}
3 changes: 2 additions & 1 deletion src/originate-scripts/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ export function databasePort(): string {
const url = new URL(env.DATABASE_URL);
return url.port || "5432";
} catch (err) {
const message = err instanceof Error ? err.message : "";
throw new Error(
`there was an error reading database information from your DATABASE_URL environment variable: ${err.message}`
`there was an error reading database information from your DATABASE_URL environment variable: ${message}`
);
}
}
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7196,10 +7196,10 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=

typescript@^4.1.3:
version "4.1.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7"
integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==
typescript@^4.6.3:
version "4.6.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.3.tgz#eefeafa6afdd31d725584c67a0eaba80f6fc6c6c"
integrity sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==

uglify-js@^3.1.4:
version "3.12.3"
Expand Down

0 comments on commit 4629a38

Please sign in to comment.