diff --git a/.circleci/config.yml b/.circleci/config.yml index 322960ef..0b026b27 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -28,5 +28,9 @@ jobs: steps: - checkout - install_deps + - run: yarn build - run: yarn test - run: yarn test:repl + - run: yarn lint:ci + - run: yarn type-check + diff --git a/.eslintrc b/.eslintrc index f271674e..731c6bee 100644 --- a/.eslintrc +++ b/.eslintrc @@ -4,8 +4,6 @@ "@shelf/eslint-config/typescript" ], "rules": { - "@typescript-eslint/no-var-requires": "off", - "no-console": "off", - "import/order": "off" + "@typescript-eslint/no-var-requires": "off" } } diff --git a/.gitignore b/.gitignore index b5a14b39..601563de 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ .idea/ coverage/ node_modules/ +lib/ temp yarn.lock *.log diff --git a/jest-preset.js b/jest-preset.js index 6e860782..e054a904 100644 --- a/jest-preset.js +++ b/jest-preset.js @@ -1,7 +1,3 @@ -const {resolve} = require('path'); +const preset = require('./lib').default; -module.exports = { - globalSetup: resolve(__dirname, './setup.js'), - globalTeardown: resolve(__dirname, './teardown.js'), - testEnvironment: resolve(__dirname, './environment.js'), -}; +module.exports = preset; diff --git a/package.json b/package.json index 1681fd4c..ba6102d8 100644 --- a/package.json +++ b/package.json @@ -17,21 +17,32 @@ "email": "vlad@shelf.io", "url": "shelf.io" }, + "files": [ + "jest-preset.js", + "lib/" + ], "scripts": { - "lint": "eslint . --fix --ext .js,.json,.ts --quiet", + "build": "rm -rf lib/ && yarn build:types && babel src --out-dir lib --ignore '**/*.test.ts' --extensions '.ts'", + "build:types": "tsc --emitDeclarationOnly --declaration --isolatedModules false --declarationDir lib", + "lint": "eslint . --ext .js,.ts,.json --fix", + "lint:ci": "eslint . --ext .js,.ts,.json", + "prepack": "yarn build", "test": "jest", - "test:repl": "MONGO_MEMORY_SERVER_FILE=jest-mongodb-config-repl.js jest" + "test:repl": "MONGO_MEMORY_SERVER_FILE=jest-mongodb-config-repl.js jest", + "type-check": "tsc --noEmit", + "type-check:watch": "npm run type-check -- --watch" }, "lint-staged": { "*.{html,md,yml}": [ - "prettier --write", - "git add" + "prettier --write" ], - "*.{js,json}": [ - "eslint --fix", - "git add" + "*.{ts,js,json}": [ + "eslint --fix" ] }, + "babel": { + "extends": "@shelf/babel-config/backend" + }, "prettier": "@shelf/prettier-config", "jest": { "preset": "./jest-preset.js" @@ -42,8 +53,14 @@ "uuid": "8.3.2" }, "devDependencies": { + "@babel/cli": "7.18.10", + "@babel/core": "7.18.10", + "@shelf/babel-config": "1.2.0", "@shelf/eslint-config": "2.18.0", "@shelf/prettier-config": "1.0.0", + "@shelf/tsconfig": "0.0.8", + "@types/jest": "28.1.6", + "@types/node": "16", "eslint": "8.22.0", "husky": "8.0.1", "jest": "28.1.3", diff --git a/environment.js b/src/environment.ts similarity index 54% rename from environment.js rename to src/environment.ts index 692119d9..8f827fea 100644 --- a/environment.js +++ b/src/environment.ts @@ -1,31 +1,35 @@ -const {TestEnvironment} = require('jest-environment-node'); -const path = require('path'); -const fs = require('fs'); +import {TestEnvironment} from 'jest-environment-node'; +import {join as pathJoin} from 'path'; +import {readFileSync} from 'fs'; +import type {EnvironmentContext} from '@jest/environment'; +import type {JestEnvironmentConfig} from '@jest/environment'; +import {MongoMemoryReplSet, MongoMemoryServer} from 'mongodb-memory-server'; +import {getMongodbMemoryOptions} from './helpers'; + const uuid = require('uuid'); -const {MongoMemoryServer, MongoMemoryReplSet} = require('mongodb-memory-server'); -const {getMongodbMemoryOptions} = require('./helpers'); +// eslint-disable-next-line import/order const debug = require('debug')('jest-mongodb:environment'); const cwd = process.cwd(); -const globalConfigPath = path.join(cwd, 'globalConfig.json'); +const globalConfigPath = pathJoin(cwd, 'globalConfig.json'); const options = getMongodbMemoryOptions(); const isReplSet = Boolean(options.replSet); debug(`isReplSet`, isReplSet); -let mongo = isReplSet ? new MongoMemoryReplSet(options) : new MongoMemoryServer(options); +const mongo = isReplSet ? new MongoMemoryReplSet(options) : new MongoMemoryServer(options); module.exports = class MongoEnvironment extends TestEnvironment { - constructor(config, context) { + constructor(config: JestEnvironmentConfig, context: EnvironmentContext) { super(config, context); } async setup() { debug('Setup MongoDB Test Environment'); - const globalConfig = JSON.parse(fs.readFileSync(globalConfigPath, 'utf-8')); + const globalConfig = JSON.parse(readFileSync(globalConfigPath, 'utf-8')); if (globalConfig.mongoUri) { this.global.__MONGO_URI__ = globalConfig.mongoUri; @@ -48,7 +52,9 @@ module.exports = class MongoEnvironment extends TestEnvironment { await super.teardown(); } + // @ts-ignore runScript(script) { + // @ts-ignore return super.runScript(script); } }; diff --git a/helpers.js b/src/helpers.ts similarity index 78% rename from helpers.js rename to src/helpers.ts index 4d284f7b..011b74a6 100644 --- a/helpers.js +++ b/src/helpers.ts @@ -1,9 +1,9 @@ -const {resolve} = require('path'); +import {resolve} from 'path'; const cwd = process.cwd(); const configFile = process.env.MONGO_MEMORY_SERVER_FILE || 'jest-mongodb-config.js'; -module.exports.getMongodbMemoryOptions = function () { +export function getMongodbMemoryOptions() { try { const {mongodbMemoryServerOptions} = require(resolve(cwd, configFile)); @@ -17,9 +17,9 @@ module.exports.getMongodbMemoryOptions = function () { instance: {}, }; } -}; +} -module.exports.getMongoURLEnvName = function () { +export function getMongoURLEnvName() { try { const {mongoURLEnvName} = require(resolve(cwd, configFile)); @@ -27,9 +27,9 @@ module.exports.getMongoURLEnvName = function () { } catch (e) { return 'MONGO_URL'; } -}; +} -module.exports.shouldUseSharedDBForAllJestWorkers = function () { +export function shouldUseSharedDBForAllJestWorkers() { try { const {useSharedDBForAllJestWorkers} = require(resolve(cwd, configFile)); @@ -41,4 +41,4 @@ module.exports.shouldUseSharedDBForAllJestWorkers = function () { } catch (e) { return true; } -}; +} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 00000000..a66f6723 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,9 @@ +import {resolve} from 'path'; + +export * from './types'; + +export default { + globalSetup: resolve(__dirname, './setup.js'), + globalTeardown: resolve(__dirname, './teardown.js'), + testEnvironment: resolve(__dirname, './environment.js'), +}; diff --git a/setup.js b/src/setup.ts similarity index 77% rename from setup.js rename to src/setup.ts index 6bb2fb38..beea462a 100644 --- a/setup.js +++ b/src/setup.ts @@ -1,12 +1,13 @@ /* eslint-disable multiline-ternary */ -const fs = require('fs'); -const {join} = require('path'); -const {MongoMemoryServer, MongoMemoryReplSet} = require('mongodb-memory-server'); -const { - getMongodbMemoryOptions, +import {writeFileSync} from 'fs'; +import {join} from 'path'; +import {MongoMemoryReplSet, MongoMemoryServer} from 'mongodb-memory-server'; +import { getMongoURLEnvName, + getMongodbMemoryOptions, shouldUseSharedDBForAllJestWorkers, -} = require('./helpers'); +} from './helpers'; +import type {Mongo} from './types'; const debug = require('debug')('jest-mongodb:setup'); const mongoMemoryServerOptions = getMongodbMemoryOptions(); @@ -14,7 +15,8 @@ const isReplSet = Boolean(mongoMemoryServerOptions.replSet); debug(`isReplSet ${isReplSet}`); -const mongo = isReplSet +// @ts-ignore +const mongo: Mongo = isReplSet ? new MongoMemoryReplSet(mongoMemoryServerOptions) : new MongoMemoryServer(mongoMemoryServerOptions); @@ -23,7 +25,7 @@ const globalConfigPath = join(cwd, 'globalConfig.json'); module.exports = async () => { const options = getMongodbMemoryOptions(); - const mongoConfig = {}; + const mongoConfig: {mongoUri?: string; mongoDBName?: string} = {}; debug(`shouldUseSharedDBForAllJestWorkers: ${shouldUseSharedDBForAllJestWorkers()}`); @@ -46,6 +48,6 @@ module.exports = async () => { mongoConfig.mongoDBName = options.instance.dbName; // Write global config to disk because all tests run in different contexts. - fs.writeFileSync(globalConfigPath, JSON.stringify(mongoConfig)); + writeFileSync(globalConfigPath, JSON.stringify(mongoConfig)); debug('Config is written'); }; diff --git a/teardown.js b/src/teardown.ts similarity index 80% rename from teardown.js rename to src/teardown.ts index 097eff8a..eeedc180 100644 --- a/teardown.js +++ b/src/teardown.ts @@ -1,6 +1,7 @@ +import {join} from 'path'; +import {unlink} from 'fs'; + const debug = require('debug')('jest-mongodb:teardown'); -const {join} = require('path'); -const fs = require('fs'); const cwd = process.cwd(); const globalConfigPath = join(cwd, 'globalConfig.json'); @@ -10,7 +11,7 @@ module.exports = async function () { if (global.__MONGOD__) { await global.__MONGOD__.stop(); } - fs.unlink(globalConfigPath, err => { + unlink(globalConfigPath, err => { if (err) { debug('Config could not be deleted'); diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 00000000..1ae5d4c9 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,10 @@ +/* eslint-disable */ +import { MongoMemoryReplSet, MongoMemoryServer } from "mongodb-memory-server"; + +declare global { + var __MONGOD__: Mongo; + var __MONGO_URI__: string; + var __MONGO_DB_NAME__: string +} + +export type Mongo = (MongoMemoryReplSet | MongoMemoryServer) & {isRunning: boolean} diff --git a/mongo-aggregate.test.js b/test/mongo-aggregate.test.ts similarity index 83% rename from mongo-aggregate.test.js rename to test/mongo-aggregate.test.ts index daec0a7c..a7c03623 100644 --- a/mongo-aggregate.test.js +++ b/test/mongo-aggregate.test.ts @@ -1,12 +1,16 @@ -const {MongoClient} = require('mongodb'); +import type {Db} from 'mongodb'; +import {MongoClient} from 'mongodb'; +import '../src/types'; describe('insert', () => { const uri = global.__MONGO_URI__; - let connection; - let db; + let connection: MongoClient; + let db: Db; beforeAll(async () => { + // @ts-ignore connection = await MongoClient.connect(uri, { + // @ts-ignore useNewUrlParser: true, useUnifiedTopology: true, }); diff --git a/mongo-insert.test.js b/test/mongo-insert.test.ts similarity index 82% rename from mongo-insert.test.js rename to test/mongo-insert.test.ts index 9808a87b..b42b80dc 100644 --- a/mongo-insert.test.js +++ b/test/mongo-insert.test.ts @@ -1,12 +1,16 @@ -const {MongoClient} = require('mongodb'); +import type {Db} from 'mongodb'; +import {MongoClient} from 'mongodb'; +import '../src/types'; describe('insert', () => { const uri = global.__MONGO_URI__; - let connection; - let db; + let connection: MongoClient; + let db: Db; beforeAll(async () => { + // @ts-ignore connection = await MongoClient.connect(uri, { + // @ts-ignore useNewUrlParser: true, useUnifiedTopology: true, }); @@ -21,7 +25,7 @@ describe('insert', () => { const users = db.collection('users'); const mockUser = {_id: 'some-user-id', name: 'John'}; - await users.insertOne(mockUser); + await users.insertOne(mockUser as any); const insertedUser = await users.findOne({_id: 'some-user-id'}); diff --git a/mongo-parallelism.test.js b/test/mongo-parallelism.test.ts similarity index 71% rename from mongo-parallelism.test.js rename to test/mongo-parallelism.test.ts index 845038b7..df3fce14 100644 --- a/mongo-parallelism.test.js +++ b/test/mongo-parallelism.test.ts @@ -1,13 +1,17 @@ -const {MongoClient} = require('mongodb'); -const {shouldUseSharedDBForAllJestWorkers} = require('./helpers'); +import type {Db} from 'mongodb'; +import {MongoClient} from 'mongodb'; +import '../src/types'; +import {shouldUseSharedDBForAllJestWorkers} from '../src/helpers'; describe('parallelism: first worker', () => { const uri = global.__MONGO_URI__; - let connection; - let db; + let connection: MongoClient; + let db: Db; beforeAll(async () => { + // @ts-ignore connection = await MongoClient.connect(uri, { + // @ts-ignore useNewUrlParser: true, useUnifiedTopology: true, }); diff --git a/mongo-parallelism2.test.js b/test/mongo-parallelism2.test.ts similarity index 72% rename from mongo-parallelism2.test.js rename to test/mongo-parallelism2.test.ts index 86042066..90e3ad83 100644 --- a/mongo-parallelism2.test.js +++ b/test/mongo-parallelism2.test.ts @@ -1,13 +1,17 @@ -const {MongoClient} = require('mongodb'); -const {shouldUseSharedDBForAllJestWorkers} = require('./helpers'); +import type {Db} from 'mongodb'; +import {MongoClient} from 'mongodb'; +import '../src/types'; +import {shouldUseSharedDBForAllJestWorkers} from '../src/helpers'; describe('parallelism: second worker', () => { const uri = global.__MONGO_URI__; - let connection; - let db; + let connection: MongoClient; + let db: Db; beforeAll(async () => { + // @ts-ignore connection = await MongoClient.connect(uri, { + // @ts-ignore useNewUrlParser: true, useUnifiedTopology: true, }); diff --git a/mongo-parallelism3.test.js b/test/mongo-parallelism3.test.ts similarity index 72% rename from mongo-parallelism3.test.js rename to test/mongo-parallelism3.test.ts index 0a970ec7..76239530 100644 --- a/mongo-parallelism3.test.js +++ b/test/mongo-parallelism3.test.ts @@ -1,13 +1,17 @@ -const {MongoClient} = require('mongodb'); -const {shouldUseSharedDBForAllJestWorkers} = require('./helpers'); +import type {Db} from 'mongodb'; +import {MongoClient} from 'mongodb'; +import '../src/types'; +import {shouldUseSharedDBForAllJestWorkers} from '../src/helpers'; describe('parallelism: third worker', () => { const uri = global.__MONGO_URI__; - let connection; - let db; + let connection: MongoClient; + let db: Db; beforeAll(async () => { + // @ts-ignore connection = await MongoClient.connect(uri, { + // @ts-ignore useNewUrlParser: true, useUnifiedTopology: true, }); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..5bbaf968 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "@shelf/tsconfig/backend", + "compilerOptions": { + "strict": true + }, + "exclude": ["node_modules"], + "include": ["src"] +}