From 7c1a364c68f2bb4750e986053d5c04ae7ddce50e Mon Sep 17 00:00:00 2001
From: Jure Triglav <juretriglav@gmail.com>
Date: Thu, 3 Jan 2019 18:54:35 +0100
Subject: [PATCH] feat: introduce @pubsweet/models package

PubSweet model components are now required from the new @pubsweet/models package. This is to avoid
circular dependencies that previously occured with pubsweet-server's many functionalities (had db,
models and api). The new structure is: @pubsweet/models for models; @pubsweet/db-manager for all db
related things; pubsweet-server for API.
---
 packages/base-model/package.json              |  1 +
 packages/base-model/src/index.js              |  3 +-
 packages/cli/cli/migrate.js                   |  3 +-
 packages/cli/cli/setupdb.js                   |  3 +-
 .../model-collection/src/api_collections.js   |  3 +-
 .../model-collection/src/collection.js        |  8 +-
 .../model-fragment/src/api_fragments.js       |  6 +-
 .../components/model-user/src/api_users.js    |  2 +-
 packages/components/model-user/src/user.js    |  3 +-
 .../xpub-review-server/src/reviewBackend.js   |  7 +-
 .../src/reviewBackend.test.js                 | 80 ++++++++--------
 packages/db-manager/package.json              |  2 +-
 .../db-manager/src/commands/add-collection.js |  3 +-
 .../db-manager/src/commands/add-fragment.js   |  3 +-
 packages/db-manager/src/commands/add-user.js  |  2 +-
 .../db-manager/src/commands/create-tables.js  |  2 +-
 packages/{server => db-manager}/src/db.js     |  0
 packages/db-manager/src/helpers/db-exists.js  |  2 +-
 packages/db-manager/src/helpers/umzug.js      |  2 +-
 .../db-manager/src/helpers/umzugStorage.js    |  2 +-
 packages/db-manager/src/index.js              | 17 ++--
 .../test/commands/add-collection.test.js      |  4 +-
 .../test/commands/add-fragment.test.js        |  4 +-
 .../db-manager/test/commands/add-user.test.js |  3 +-
 .../db-manager/test/commands/setup-db.test.js |  2 +-
 packages/models/README.md                     |  7 ++
 packages/models/config/test.js                | 31 +++++++
 packages/models/package.json                  | 18 ++++
 .../src/models => models/src}/index.js        |  0
 packages/server/package.json                  |  1 -
 packages/server/src/app.js                    |  5 +-
 packages/server/src/connectors/index.js       |  8 +-
 packages/server/src/errors/index.js           |  4 +
 packages/server/src/helpers/authsome.js       |  2 +-
 packages/server/src/index.js                  |  6 --
 packages/server/src/jobs/index.js             |  2 +-
 packages/server/src/setup-base.js             |  2 +-
 packages/server/test/api_admin_test.js        |  2 +-
 .../server/test/api_authenticated_test.js     |  2 +-
 packages/server/test/api_teams_test.js        |  3 +-
 .../server/test/api_unauthenticated_test.js   |  2 +-
 packages/server/test/helpers/db_cleaner.js    |  3 +-
 packages/server/test/helpers/fragment.js      |  2 +-
 packages/server/test/model_test.js            |  2 +-
 packages/server/test/teams_test.js            |  2 +-
 packages/ui/package.json                      |  1 -
 yarn.lock                                     | 93 ++++++++++---------
 47 files changed, 207 insertions(+), 158 deletions(-)
 rename packages/{server => db-manager}/src/db.js (100%)
 create mode 100644 packages/models/README.md
 create mode 100644 packages/models/config/test.js
 create mode 100644 packages/models/package.json
 rename packages/{server/src/models => models/src}/index.js (100%)
 create mode 100644 packages/server/src/errors/index.js

diff --git a/packages/base-model/package.json b/packages/base-model/package.json
index eb34d1d62..648c57a8b 100644
--- a/packages/base-model/package.json
+++ b/packages/base-model/package.json
@@ -10,6 +10,7 @@
   "license": "MIT",
   "dependencies": {
     "objection": "^1.2.3",
+    "knex": "^0.16.3",
     "pubsweet-server": "^10.1.4"
   },
   "publishConfig": {
diff --git a/packages/base-model/src/index.js b/packages/base-model/src/index.js
index 6b74a9c00..0fecd5079 100644
--- a/packages/base-model/src/index.js
+++ b/packages/base-model/src/index.js
@@ -1,7 +1,8 @@
 const uuid = require('uuid')
 const { Model, transaction } = require('objection')
 const logger = require('@pubsweet/logger')
-const { db, NotFoundError } = require('pubsweet-server')
+const { NotFoundError } = require('pubsweet-server/src/errors')
+const db = require('@pubsweet/db-manager/src/db')
 const { merge } = require('lodash')
 const config = require('config')
 
diff --git a/packages/cli/cli/migrate.js b/packages/cli/cli/migrate.js
index dfdd31a43..828136876 100644
--- a/packages/cli/cli/migrate.js
+++ b/packages/cli/cli/migrate.js
@@ -1,6 +1,5 @@
 const program = require('commander')
-const { db } = require('pubsweet-server')
-const { migrate } = require('@pubsweet/db-manager')
+const { db, migrate } = require('@pubsweet/db-manager')
 
 module.exports = async (commandArguments = process.argv) => {
   const options = program.parse(commandArguments)
diff --git a/packages/cli/cli/setupdb.js b/packages/cli/cli/setupdb.js
index 46087d5c5..fec275774 100644
--- a/packages/cli/cli/setupdb.js
+++ b/packages/cli/cli/setupdb.js
@@ -1,7 +1,6 @@
 const program = require('commander')
 const properties = require('../src/schemas').db
-const { setupDb } = require('@pubsweet/db-manager')
-const db = require('pubsweet-server/src/db')
+const { db, setupDb } = require('@pubsweet/db-manager')
 const config = require('config')
 const { some, forEach } = require('lodash')
 const runPrompt = require('../src/run-prompt')
diff --git a/packages/components/model-collection/src/api_collections.js b/packages/components/model-collection/src/api_collections.js
index 5858cf845..778d5e3e9 100644
--- a/packages/components/model-collection/src/api_collections.js
+++ b/packages/components/model-collection/src/api_collections.js
@@ -19,8 +19,7 @@ const authBearerAndPublic = passport.authenticate(['bearer', 'anonymous'], {
 })
 
 const CollectionsAPI = app => {
-  const { Collection, Team } = require('pubsweet-server/src/models')
-  const { model: User } = require('@pubsweet/model-user')
+  const { User, Collection, Team } = require('@pubsweet/models')
 
   // List collections
   app.get('/api/collections', authBearerAndPublic, async (req, res, next) => {
diff --git a/packages/components/model-collection/src/collection.js b/packages/components/model-collection/src/collection.js
index ba4cee2f3..79917a29a 100644
--- a/packages/components/model-collection/src/collection.js
+++ b/packages/components/model-collection/src/collection.js
@@ -34,7 +34,7 @@ class Collection extends BaseModel {
   }
 
   async delete() {
-    const { model: Team } = require('@pubsweet/model-team')
+    const { Team } = require('@pubsweet/models')
     await Team.deleteAssociated(this.type, this.id)
     return super.delete()
   }
@@ -42,7 +42,8 @@ class Collection extends BaseModel {
   // Gets fragments in a collection, supports filtering by function e.g.
   // collection.getFragments({filter: fragment => {Authorize.can(req.user, 'read', fragment)})
   getFragments(options) {
-    const { Fragment } = require('pubsweet-server/src/models')
+    const { Fragment } = require('@pubsweet/models')
+
     options = options || {}
     options.filter = options.filter || (() => Promise.resolve(true))
 
@@ -63,7 +64,8 @@ class Collection extends BaseModel {
   }
 
   addFragment(fragment) {
-    const { Fragment } = require('pubsweet-server/src/models')
+    const { Fragment } = require('@pubsweet/models')
+
     this.fragments = this.fragments.map(fragment => {
       if (typeof fragment === 'object') {
         return fragment
diff --git a/packages/components/model-fragment/src/api_fragments.js b/packages/components/model-fragment/src/api_fragments.js
index 86e2fd9c5..b228bef4f 100644
--- a/packages/components/model-fragment/src/api_fragments.js
+++ b/packages/components/model-fragment/src/api_fragments.js
@@ -23,11 +23,9 @@ const authBearerAndPublic = passport.authenticate(['bearer', 'anonymous'], {
 const FragmentsAPI = app => {
   const authsome = require('pubsweet-server/src/helpers/authsome')
 
-  const { AuthorizationError } = require('pubsweet-server')
+  const { AuthorizationError } = require('pubsweet-server/src/errors')
 
-  const { model: Team } = require('@pubsweet/model-team')
-  const { model: User } = require('@pubsweet/model-user')
-  const { Fragment, Collection } = require('pubsweet-server/src/models')
+  const { Team, User, Fragment, Collection } = require('@pubsweet/models')
 
   // Create a fragment and update the collection with the fragment
   app.post(
diff --git a/packages/components/model-user/src/api_users.js b/packages/components/model-user/src/api_users.js
index df6f2d3cd..4a5f37540 100644
--- a/packages/components/model-user/src/api_users.js
+++ b/packages/components/model-user/src/api_users.js
@@ -11,7 +11,7 @@ const authentication = require('./authentication')
 
 const UsersAPI = app => {
   const User = require('./user')
-  const { ValidationError } = require('pubsweet-server')
+  const { ValidationError } = require('pubsweet-server/src/errors')
 
   const {
     util: {
diff --git a/packages/components/model-user/src/user.js b/packages/components/model-user/src/user.js
index 169814229..ea7745042 100644
--- a/packages/components/model-user/src/user.js
+++ b/packages/components/model-user/src/user.js
@@ -1,6 +1,5 @@
 const BaseModel = require('@pubsweet/base-model')
 const bcrypt = require('bcrypt')
-// const omit = require('lodash/omit')
 const pick = require('lodash/pick')
 const config = require('config')
 
@@ -83,7 +82,7 @@ class User extends BaseModel {
   }
 
   static async isUniq(user) {
-    const { ConflictError } = require('pubsweet-server')
+    const { ConflictError } = require('pubsweet-server/src/errors')
 
     let result
 
diff --git a/packages/components/xpub-review-server/src/reviewBackend.js b/packages/components/xpub-review-server/src/reviewBackend.js
index 977cc518e..4d5814b9d 100644
--- a/packages/components/xpub-review-server/src/reviewBackend.js
+++ b/packages/components/xpub-review-server/src/reviewBackend.js
@@ -4,11 +4,8 @@ const passport = require('passport')
 const logger = require('@pubsweet/logger')
 const emailer = require('@pubsweet/component-send-email')
 const {
-  User,
-  Team,
-  Fragment,
-  Collection,
-} = require('pubsweet-server/src/models')
+  models: { User, Fragment, Team, Collection },
+} = require('@pubsweet/db-manager')
 const authsome = require('pubsweet-server/src/helpers/authsome')
 const AuthorizationError = require('pubsweet-server/src/errors/AuthorizationError')
 
diff --git a/packages/components/xpub-review-server/src/reviewBackend.test.js b/packages/components/xpub-review-server/src/reviewBackend.test.js
index d5c1b2458..bd0539fa3 100644
--- a/packages/components/xpub-review-server/src/reviewBackend.test.js
+++ b/packages/components/xpub-review-server/src/reviewBackend.test.js
@@ -10,47 +10,49 @@ jest.mock('@pubsweet/component-send-email', () => ({
   send: jest.fn().mockImplementation(() => Promise.resolve({})),
 }))
 
-jest.mock('pubsweet-server/src/models', () => ({
-  Team: () => ({
-    find: jest.fn(() => ({
-      id: '9555530a-ca92-4e74-a48c-b21ccc109ca8',
-      teams: ['08888b14-8b64-420d-898f-b2bdd9fbd57c'],
-      email: 'author@example.org',
-    })),
-    save: () => {},
-  }),
-  User: {
-    find: jest.fn(() => ({
-      id: '9555530a-ca92-4e74-a48c-b21ccc109ca8',
-      teams: ['08888b14-8b64-420d-898f-b2bdd9fbd57c'],
-      email: 'author@example.org',
+jest.mock('@pubsweet/db-manager', () => ({
+  models: {
+    Team: () => ({
+      find: jest.fn(() => ({
+        id: '9555530a-ca92-4e74-a48c-b21ccc109ca8',
+        teams: ['08888b14-8b64-420d-898f-b2bdd9fbd57c'],
+        email: 'author@example.org',
+      })),
       save: () => {},
-    })),
-  },
-  Fragment: {
-    find: jest.fn(() => ({
-      version: 1,
-      owners: [{}],
-      metadata: {
-        title: 'title',
-        abstract: 'abstract',
-      },
-      updateProperties(update) {
-        Object.assign(this, update)
-      },
-      save: () => {},
-    })),
-  },
-  Collection: {
-    find: jest.fn(() => ({
-      updateProperties: () => ({}),
-      reviewers: [
-        {
-          user: '9555530a-ca92-4e74-a48c-b21ccc109ca8',
+    }),
+    User: {
+      find: jest.fn(() => ({
+        id: '9555530a-ca92-4e74-a48c-b21ccc109ca8',
+        teams: ['08888b14-8b64-420d-898f-b2bdd9fbd57c'],
+        email: 'author@example.org',
+        save: () => {},
+      })),
+    },
+    Fragment: {
+      find: jest.fn(() => ({
+        version: 1,
+        owners: [{}],
+        metadata: {
+          title: 'title',
+          abstract: 'abstract',
         },
-      ],
-      save: () => {},
-    })),
+        updateProperties(update) {
+          Object.assign(this, update)
+        },
+        save: () => {},
+      })),
+    },
+    Collection: {
+      find: jest.fn(() => ({
+        updateProperties: () => ({}),
+        reviewers: [
+          {
+            user: '9555530a-ca92-4e74-a48c-b21ccc109ca8',
+          },
+        ],
+        save: () => {},
+      })),
+    },
   },
 }))
 
diff --git a/packages/db-manager/package.json b/packages/db-manager/package.json
index acb2b79df..f352ff9bc 100644
--- a/packages/db-manager/package.json
+++ b/packages/db-manager/package.json
@@ -32,7 +32,7 @@
     "isomorphic-fetch": "^2.2.1",
     "joi": "^14.3.0",
     "pg": "^7.4.1",
-    "pubsweet-server": "^10.1.4",
+    "objection": "^1.3.0",
     "tmp": "^0.0.33",
     "umzug": "^2.1.0"
   }
diff --git a/packages/db-manager/src/commands/add-collection.js b/packages/db-manager/src/commands/add-collection.js
index 47ad2c7a7..a66223025 100644
--- a/packages/db-manager/src/commands/add-collection.js
+++ b/packages/db-manager/src/commands/add-collection.js
@@ -1,8 +1,7 @@
 const logger = require('@pubsweet/logger')
 
 module.exports = async (collectionData, fragment = null) => {
-  const { model: User } = require('@pubsweet/model-user')
-  const { Collection } = require('pubsweet-server/src/models')
+  const { User, Collection } = require('@pubsweet/models')
 
   logger.info('Creating collection')
 
diff --git a/packages/db-manager/src/commands/add-fragment.js b/packages/db-manager/src/commands/add-fragment.js
index 235997b1c..c21c7ca4d 100644
--- a/packages/db-manager/src/commands/add-fragment.js
+++ b/packages/db-manager/src/commands/add-fragment.js
@@ -1,8 +1,7 @@
 const logger = require('@pubsweet/logger')
 
 module.exports = async fragmentData => {
-  const { Fragment } = require('pubsweet-server/src/models')
-  const { model: User } = require('@pubsweet/model-user')
+  const { Fragment, User } = require('@pubsweet/models')
 
   logger.info('Creating fragment')
 
diff --git a/packages/db-manager/src/commands/add-user.js b/packages/db-manager/src/commands/add-user.js
index 1b4f4c8a9..cac6aad61 100644
--- a/packages/db-manager/src/commands/add-user.js
+++ b/packages/db-manager/src/commands/add-user.js
@@ -1,5 +1,5 @@
 const logger = require('@pubsweet/logger')
-const { Collection, User } = require('pubsweet-server/src/models')
+const { Collection, User } = require('@pubsweet/models')
 const { validateUser } = require('../validations')
 
 const addAdminOwnerToAllCollections = async user => {
diff --git a/packages/db-manager/src/commands/create-tables.js b/packages/db-manager/src/commands/create-tables.js
index 1747a765d..3f32c7ec4 100644
--- a/packages/db-manager/src/commands/create-tables.js
+++ b/packages/db-manager/src/commands/create-tables.js
@@ -1,5 +1,5 @@
 const logger = require('@pubsweet/logger')
-const db = require('pubsweet-server/src/db')
+const db = require('../db')
 const migrate = require('./migrate')
 
 const createTables = async clobber => {
diff --git a/packages/server/src/db.js b/packages/db-manager/src/db.js
similarity index 100%
rename from packages/server/src/db.js
rename to packages/db-manager/src/db.js
diff --git a/packages/db-manager/src/helpers/db-exists.js b/packages/db-manager/src/helpers/db-exists.js
index d1eb6dcd1..ef30f16d6 100644
--- a/packages/db-manager/src/helpers/db-exists.js
+++ b/packages/db-manager/src/helpers/db-exists.js
@@ -1,4 +1,4 @@
-const db = require('pubsweet-server/src/db')
+const db = require('../db')
 const logger = require('@pubsweet/logger')
 
 module.exports = async () => {
diff --git a/packages/db-manager/src/helpers/umzug.js b/packages/db-manager/src/helpers/umzug.js
index 55e4463f6..26763b464 100644
--- a/packages/db-manager/src/helpers/umzug.js
+++ b/packages/db-manager/src/helpers/umzug.js
@@ -1,5 +1,5 @@
 const logger = require('@pubsweet/logger')
-const db = require('pubsweet-server/src/db')
+const db = require('../db')
 const Umzug = require('umzug')
 const fs = require('fs-extra')
 const path = require('path')
diff --git a/packages/db-manager/src/helpers/umzugStorage.js b/packages/db-manager/src/helpers/umzugStorage.js
index a55355e76..0d7450505 100644
--- a/packages/db-manager/src/helpers/umzugStorage.js
+++ b/packages/db-manager/src/helpers/umzugStorage.js
@@ -1,4 +1,4 @@
-const db = require('pubsweet-server/src/db')
+const db = require('../db')
 
 // umzug storage adapter
 module.exports = {
diff --git a/packages/db-manager/src/index.js b/packages/db-manager/src/index.js
index 2007b1825..e817214f6 100644
--- a/packages/db-manager/src/index.js
+++ b/packages/db-manager/src/index.js
@@ -1,9 +1,8 @@
-module.exports = {
-  createTables: require('./commands/create-tables'),
-  setupDb: require('./commands/setup-db'),
-  migrate: require('./commands/migrate'),
-  addUser: require('./commands/add-user'),
-  addCollection: require('./commands/add-collection'),
-  addFragment: require('./commands/add-fragment'),
-  dbExists: require('./helpers/db-exists'),
-}
+module.exports.db = require('./db')
+module.exports.createTables = require('./commands/create-tables')
+module.exports.setupDb = require('./commands/setup-db')
+module.exports.migrate = require('./commands/migrate')
+module.exports.addUser = require('./commands/add-user')
+module.exports.addCollection = require('./commands/add-collection')
+module.exports.addFragment = require('./commands/add-fragment')
+module.exports.dbExists = require('./helpers/db-exists')
diff --git a/packages/db-manager/test/commands/add-collection.test.js b/packages/db-manager/test/commands/add-collection.test.js
index 0201c77f5..d4ae308e8 100644
--- a/packages/db-manager/test/commands/add-collection.test.js
+++ b/packages/db-manager/test/commands/add-collection.test.js
@@ -1,6 +1,6 @@
 const { addCollection, createTables } = require('../../src')
-const { Collection, Fragment } = require('pubsweet-server/src/models')
-const { model: User } = require('@pubsweet/model-user')
+
+const { Collection, Fragment, User } = require('@pubsweet/models')
 
 describe('add-collection', () => {
   beforeEach(() => createTables(true))
diff --git a/packages/db-manager/test/commands/add-fragment.test.js b/packages/db-manager/test/commands/add-fragment.test.js
index d0babb4b6..eb6298a32 100644
--- a/packages/db-manager/test/commands/add-fragment.test.js
+++ b/packages/db-manager/test/commands/add-fragment.test.js
@@ -1,6 +1,6 @@
 const { addFragment, createTables } = require('../../src')
-const { model: Fragment } = require('@pubsweet/model-fragment')
-const { model: User } = require('@pubsweet/model-user')
+
+const { Fragment, User } = require('@pubsweet/models')
 
 describe('add-fragment', () => {
   beforeEach(() => createTables(true))
diff --git a/packages/db-manager/test/commands/add-user.test.js b/packages/db-manager/test/commands/add-user.test.js
index de217ab8e..6322dee2d 100644
--- a/packages/db-manager/test/commands/add-user.test.js
+++ b/packages/db-manager/test/commands/add-user.test.js
@@ -1,6 +1,7 @@
-const { model: User } = require('@pubsweet/model-user')
 const { addUser, createTables } = require('../../src/')
 
+const { User } = require('@pubsweet/models')
+
 const nonAdminUser = {
   username: 'nonAdminUsername',
   email: 'nonAdmin@example.com',
diff --git a/packages/db-manager/test/commands/setup-db.test.js b/packages/db-manager/test/commands/setup-db.test.js
index 5bef00bf8..ab8f5c64e 100644
--- a/packages/db-manager/test/commands/setup-db.test.js
+++ b/packages/db-manager/test/commands/setup-db.test.js
@@ -1,5 +1,5 @@
-const { model: User } = require('@pubsweet/model-user')
 const { setupDb } = require('../../src')
+const { User } = require('@pubsweet/models')
 
 describe('setup-db', () => {
   it('creates the database and an admin user', async () => {
diff --git a/packages/models/README.md b/packages/models/README.md
new file mode 100644
index 000000000..ec5eb1c3d
--- /dev/null
+++ b/packages/models/README.md
@@ -0,0 +1,7 @@
+# Models
+
+A package that connects all model components together, so that you can use them elsewhere with e.g.
+
+```
+const { User } = require('@pubsweet/models')
+```
diff --git a/packages/models/config/test.js b/packages/models/config/test.js
new file mode 100644
index 000000000..57ffa063a
--- /dev/null
+++ b/packages/models/config/test.js
@@ -0,0 +1,31 @@
+const path = require('path')
+
+module.exports = {
+  'pubsweet-server': {
+    db: {
+      // temporary database name set by jest-environment-db
+      database: global.__testDbName || 'test',
+    },
+    pool: { min: 0, max: 10, idleTimeoutMillis: 1000 },
+    enableExperimentalGraphql: true,
+    port: 4000,
+    secret: 'test',
+    sse: false,
+    uploads: 'uploads',
+  },
+  authsome: {
+    mode: path.resolve(__dirname, '..', 'test', 'helpers', 'authsome_mode'),
+    teams: {
+      teamTest: {
+        name: 'Contributors',
+      },
+    },
+  },
+  schema: {
+    Manuscript: {
+      properties: {
+        configField: { type: 'string' },
+      },
+    },
+  },
+}
diff --git a/packages/models/package.json b/packages/models/package.json
new file mode 100644
index 000000000..62dbf46ec
--- /dev/null
+++ b/packages/models/package.json
@@ -0,0 +1,18 @@
+{
+  "name": "@pubsweet/models",
+  "version": "0.0.1",
+  "description": "A simple package that brings models together",
+  "main": "src/index.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "author": "Adam Hyde",
+  "license": "MIT",
+  "dependencies": {
+    "objection": "^1.2.3",
+    "pubsweet-server": "^10.1.4"
+  },
+  "publishConfig": {
+    "access": "public"
+  }
+}
diff --git a/packages/server/src/models/index.js b/packages/models/src/index.js
similarity index 100%
rename from packages/server/src/models/index.js
rename to packages/models/src/index.js
diff --git a/packages/server/package.json b/packages/server/package.json
index cdbdf9527..aab518700 100644
--- a/packages/server/package.json
+++ b/packages/server/package.json
@@ -31,7 +31,6 @@
     "http-status-codes": "^1.0.6",
     "joi": "^14.3.0",
     "jsonwebtoken": "^8.4.0",
-    "knex": "^0.15.2",
     "lodash": "^4.0.0",
     "minimist": "^1.2.0",
     "morgan": "^1.8.2",
diff --git a/packages/server/src/app.js b/packages/server/src/app.js
index 7b4cb34ee..a232d442d 100644
--- a/packages/server/src/app.js
+++ b/packages/server/src/app.js
@@ -13,8 +13,6 @@ const passport = require('passport')
 const graphqlApi = require('./graphql/routes')
 const index = require('./routes/index')
 const api = require('./routes/api')
-const models = require('./models')
-const authsome = require('./helpers/authsome')
 const logger = require('@pubsweet/logger')
 const sse = require('pubsweet-sse')
 
@@ -25,6 +23,9 @@ const registerComponents = require('./register-components')
 const configureApp = app => {
   global.versions = {}
 
+  const models = require('@pubsweet/models')
+  const authsome = require('./helpers/authsome')
+
   app.locals.models = models
 
   app.use(bodyParser.json({ limit: '50mb' }))
diff --git a/packages/server/src/connectors/index.js b/packages/server/src/connectors/index.js
index f19a2d830..89b41739e 100644
--- a/packages/server/src/connectors/index.js
+++ b/packages/server/src/connectors/index.js
@@ -1,17 +1,11 @@
 const config = require('config')
 
 const connector = require('./connector')
-const models = require('../models')
 
 const requireRelative = m =>
   require(require.resolve(m, { paths: [process.cwd()] }))
 
-const connectors = {
-  Collection: connector('Collection', models.Collection),
-  Fragment: connector('Fragment', models.Fragment),
-  Team: connector('Team', models.Team),
-  User: connector('User', models.User),
-}
+const connectors = {}
 
 // merge in component connectors, recursively
 function getConnectorsRecursively(componentName) {
diff --git a/packages/server/src/errors/index.js b/packages/server/src/errors/index.js
new file mode 100644
index 000000000..c7d9cea6b
--- /dev/null
+++ b/packages/server/src/errors/index.js
@@ -0,0 +1,4 @@
+module.exports.NotFoundError = require('./NotFoundError')
+module.exports.ConflictError = require('./ConflictError')
+module.exports.ValidationError = require('./ValidationError')
+module.exports.AuthorizationError = require('./AuthorizationError')
diff --git a/packages/server/src/helpers/authsome.js b/packages/server/src/helpers/authsome.js
index 5495f74b8..f5f23abef 100644
--- a/packages/server/src/helpers/authsome.js
+++ b/packages/server/src/helpers/authsome.js
@@ -3,7 +3,7 @@ const Authsome = require('authsome')
 
 const mode = require(config.get('authsome.mode'))
 
-const models = require('../models')
+const models = require('@pubsweet/models')
 
 // be lenient with custom/extended data models based on BaseModel
 // and allow them through to authsome in their entirety. If you use this
diff --git a/packages/server/src/index.js b/packages/server/src/index.js
index 0fb3d68af..b83c94ac9 100644
--- a/packages/server/src/index.js
+++ b/packages/server/src/index.js
@@ -1,10 +1,4 @@
-module.exports.db = require('./db')
-
 module.exports.pubsubManager = require('./graphql/pubsub')
-module.exports.NotFoundError = require('./errors/NotFoundError')
-module.exports.ConflictError = require('./errors/ConflictError')
-module.exports.ValidationError = require('./errors/ValidationError')
-module.exports.AuthorizationError = require('./errors/AuthorizationError')
 
 module.exports.startServer = require('./start-server')
 
diff --git a/packages/server/src/jobs/index.js b/packages/server/src/jobs/index.js
index 76bb1a058..5246b78fa 100644
--- a/packages/server/src/jobs/index.js
+++ b/packages/server/src/jobs/index.js
@@ -2,7 +2,7 @@
 const PgBoss = require('pg-boss')
 const logger = require('@pubsweet/logger')
 
-const db = require('../db')
+const db = require('@pubsweet/db-manager/src/db')
 
 const dbAdapter = {
   executeSql: (sql, parameters = []) => {
diff --git a/packages/server/src/setup-base.js b/packages/server/src/setup-base.js
index 731939d38..d18b3297c 100644
--- a/packages/server/src/setup-base.js
+++ b/packages/server/src/setup-base.js
@@ -2,7 +2,7 @@ const logger = require('@pubsweet/logger')
 
 class Setup {
   static async setup(user, collection) {
-    const { Collection, User } = require('pubsweet-server/src/models')
+    const { Collection, User } = require('@pubsweet/models')
 
     logger.info('Starting setup')
 
diff --git a/packages/server/test/api_admin_test.js b/packages/server/test/api_admin_test.js
index 471301424..b47727d07 100644
--- a/packages/server/test/api_admin_test.js
+++ b/packages/server/test/api_admin_test.js
@@ -4,7 +4,7 @@ const createBasicCollection = require('./helpers/basic_collection')
 const cleanDB = require('./helpers/db_cleaner')
 const fixtures = require('./fixtures/fixtures')
 
-const { User, Fragment } = require('../src/models')
+const { Fragment, User } = require('@pubsweet/models')
 
 const api = require('./helpers/api')
 
diff --git a/packages/server/test/api_authenticated_test.js b/packages/server/test/api_authenticated_test.js
index c23630454..0bc84dbef 100644
--- a/packages/server/test/api_authenticated_test.js
+++ b/packages/server/test/api_authenticated_test.js
@@ -6,7 +6,7 @@ const api = require('./helpers/api')
 const setTeamForCollection = require('./helpers/set_team')
 const fixtures = require('./fixtures/fixtures')
 
-const { Fragment, User } = require('../src/models')
+const { Fragment, User } = require('@pubsweet/models')
 
 describe('authenticated api', () => {
   let otherUser
diff --git a/packages/server/test/api_teams_test.js b/packages/server/test/api_teams_test.js
index 0b8b6f7a7..e5f341a96 100644
--- a/packages/server/test/api_teams_test.js
+++ b/packages/server/test/api_teams_test.js
@@ -1,7 +1,8 @@
 const STATUS = require('http-status-codes')
 const cloneDeep = require('lodash/cloneDeep')
 
-const { Collection, User, Team } = require('../src/models')
+const { Collection, User, Team } = require('@pubsweet/models')
+
 const cleanDB = require('./helpers/db_cleaner')
 const fixtures = require('./fixtures/fixtures')
 
diff --git a/packages/server/test/api_unauthenticated_test.js b/packages/server/test/api_unauthenticated_test.js
index dc425656b..6d2300005 100644
--- a/packages/server/test/api_unauthenticated_test.js
+++ b/packages/server/test/api_unauthenticated_test.js
@@ -4,7 +4,7 @@ const api = require('./helpers/api')
 const createBasicCollection = require('./helpers/basic_collection')
 const createFragment = require('./helpers/fragment')
 const cleanDB = require('./helpers/db_cleaner')
-const { Collection } = require('../src/models')
+const { Collection } = require('@pubsweet/models')
 
 describe('unauthenticated/public api', () => {
   let fragment
diff --git a/packages/server/test/helpers/db_cleaner.js b/packages/server/test/helpers/db_cleaner.js
index d029ceab1..455d631f2 100644
--- a/packages/server/test/helpers/db_cleaner.js
+++ b/packages/server/test/helpers/db_cleaner.js
@@ -1,6 +1,5 @@
-const db = require('../../src/db')
+const { db, migrate } = require('@pubsweet/db-manager')
 const logger = require('@pubsweet/logger')
-const { migrate } = require('@pubsweet/db-manager')
 
 const dbCleaner = async () => {
   await db.raw('DROP SCHEMA public CASCADE;')
diff --git a/packages/server/test/helpers/fragment.js b/packages/server/test/helpers/fragment.js
index 96f05e798..0c73f806f 100644
--- a/packages/server/test/helpers/fragment.js
+++ b/packages/server/test/helpers/fragment.js
@@ -1,5 +1,5 @@
 const fixtures = require('../fixtures/fixtures')
-const { Fragment } = require('../../src/models')
+const { Fragment } = require('@pubsweet/models')
 const assign = require('lodash/assign')
 
 module.exports = (opts, collection) => {
diff --git a/packages/server/test/model_test.js b/packages/server/test/model_test.js
index 06902854a..e082fb061 100644
--- a/packages/server/test/model_test.js
+++ b/packages/server/test/model_test.js
@@ -1,5 +1,5 @@
 const STATUS = require('http-status-codes')
-const { Fragment, Collection } = require('../src/models')
+const { Fragment, Collection } = require('@pubsweet/models')
 const { model: User } = require('@pubsweet/model-user')
 const dbCleaner = require('./helpers/db_cleaner')
 const fixtures = require('./fixtures/fixtures')
diff --git a/packages/server/test/teams_test.js b/packages/server/test/teams_test.js
index ca2e4bc18..77113a07d 100644
--- a/packages/server/test/teams_test.js
+++ b/packages/server/test/teams_test.js
@@ -1,4 +1,4 @@
-const { Fragment, User, Collection, Team } = require('../src/models')
+const { Fragment, User, Collection, Team } = require('@pubsweet/models')
 const dbCleaner = require('./helpers/db_cleaner')
 const fixtures = require('./fixtures/fixtures')
 
diff --git a/packages/ui/package.json b/packages/ui/package.json
index ae0a659b5..e6c194002 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -36,7 +36,6 @@
     "styled-components": "^4.1.1"
   },
   "devDependencies": {
-    "@pubsweet/styleguide": "^4.0.3",
     "babel-core": "^6.26.0",
     "babel-loader": "^7.1.2",
     "babel-preset-env": "^1.6.0",
diff --git a/yarn.lock b/yarn.lock
index c4715881c..9cbe46841 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -135,6 +135,14 @@
   resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.1.6.tgz#16e97aca1ec1062324a01c5a6a7d0df8dd189854"
   integrity sha512-dWP6LJm9nKT6ALaa+bnL247GHHMWir3vSlZ2+IHgHgktZQx0L3Uvq2uAWcuzIe+fujRsYWBW2q622C5UvGK9iQ==
 
+"@babel/polyfill@^7.0.0":
+  version "7.2.3"
+  resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.2.3.tgz#277fe900281d6874ab82332c90482621cbea2575"
+  integrity sha512-XG854errfwBkrnWV9dDmSSa8ueTciFUMcC47Mn9obkfLipRKaQL4o33YRsNk0IEep1WXMvr1hGz8DQbSQC2tPQ==
+  dependencies:
+    core-js "^2.5.7"
+    regenerator-runtime "^0.12.0"
+
 "@babel/runtime-corejs2@^7.0.0":
   version "7.1.5"
   resolved "https://registry.yarnpkg.com/@babel/runtime-corejs2/-/runtime-corejs2-7.1.5.tgz#ec8341c9aec71d1139c985327314739d66b204a0"
@@ -1012,6 +1020,11 @@
   resolved "https://registry.yarnpkg.com/@types/async/-/async-2.0.50.tgz#117540e026d64e1846093abbd5adc7e27fda7bcb"
   integrity sha512-VMhZMMQgV1zsR+lX/0IBfAk+8Eb7dPVMWiQGFAt3qjo5x7Ml6b77jUo0e1C3ToD+XRDXqtrfw+6AB0uUsPEr3Q==
 
+"@types/bluebird@^3.5.25":
+  version "3.5.25"
+  resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.25.tgz#59188b871208092e37767e4b3d80c3b3eaae43bd"
+  integrity sha512-yfhIBix+AIFTmYGtkC0Bi+XGjSkOINykqKvO/Wqdz/DuXlAKK7HmhLAXdPIGsV4xzKcL3ev/zYc4yLNo+OvGaw==
+
 "@types/node@*":
   version "10.12.10"
   resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.10.tgz#4fa76e6598b7de3f0cb6ec3abacc4f59e5b3a2ce"
@@ -3466,15 +3479,6 @@ chalk@2.3.1:
     escape-string-regexp "^1.0.5"
     supports-color "^5.2.0"
 
-chalk@2.3.2:
-  version "2.3.2"
-  resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65"
-  integrity sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==
-  dependencies:
-    ansi-styles "^3.2.1"
-    escape-string-regexp "^1.0.5"
-    supports-color "^5.3.0"
-
 chalk@2.4.1, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.1:
   version "2.4.1"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e"
@@ -3913,7 +3917,7 @@ combined-stream@^1.0.5, combined-stream@^1.0.6, combined-stream@~1.0.6:
   dependencies:
     delayed-stream "~1.0.0"
 
-commander@^2.11.0, commander@^2.16.0, commander@^2.19.0, commander@^2.9.0:
+commander@^2.11.0, commander@^2.19.0, commander@^2.9.0:
   version "2.19.0"
   resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
   integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
@@ -4679,6 +4683,13 @@ debug@3.1.0, debug@=3.1.0:
   dependencies:
     ms "2.0.0"
 
+debug@4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.0.tgz#373687bffa678b38b1cd91f861b63850035ddc87"
+  integrity sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==
+  dependencies:
+    ms "^2.1.1"
+
 debug@^3.0.0, debug@^3.1.0, debug@^3.2.5:
   version "3.2.6"
   resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
@@ -6439,9 +6450,9 @@ findup@^0.1.5:
     commander "~2.1.0"
 
 fined@^1.0.1:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/fined/-/fined-1.1.0.tgz#b37dc844b76a2f5e7081e884f7c0ae344f153476"
-  integrity sha1-s33IRLdqL15wgeiE98CuNE8VNHY=
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/fined/-/fined-1.1.1.tgz#95d88ff329123dd1a6950fdfcd321f746271e01f"
+  integrity sha512-jQp949ZmEbiYHk3gkbdtpJ0G1+kgtLQBNdP5edFP7Fh+WAYceLQz6yO1SBj72Xkg8GVyTB3bBzAYrHJVh5Xd5g==
   dependencies:
     expand-tilde "^2.0.2"
     is-plain-object "^2.0.3"
@@ -6450,9 +6461,9 @@ fined@^1.0.1:
     parse-filepath "^1.0.1"
 
 flagged-respawn@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.0.tgz#4e79ae9b2eb38bf86b3bb56bf3e0a56aa5fcabd7"
-  integrity sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.1.tgz#e7de6f1279ddd9ca9aac8a5971d618606b3aab41"
+  integrity sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==
 
 flat-cache@^1.2.1:
   version "1.3.4"
@@ -9107,20 +9118,21 @@ kleur@^2.0.1:
   resolved "https://registry.yarnpkg.com/kleur/-/kleur-2.0.2.tgz#b704f4944d95e255d038f0cb05fb8a602c55a300"
   integrity sha512-77XF9iTllATmG9lSlIv0qdQ2BQ/h9t0bJllHlbvsQ0zUWfU7Yi0S8L5JXzPZgkefIiajLmBJJ4BsMJmqcf7oxQ==
 
-knex@^0.15.2:
-  version "0.15.2"
-  resolved "https://registry.yarnpkg.com/knex/-/knex-0.15.2.tgz#6059b87489605f4cc87599a6d2a9d265709e9340"
-  integrity sha1-YFm4dIlgX0zIdZmm0qnSZXCek0A=
+knex@^0.16.3:
+  version "0.16.3"
+  resolved "https://registry.yarnpkg.com/knex/-/knex-0.16.3.tgz#ca9effd4973655f42b42132b9019b0bc6bd20644"
+  integrity sha512-jGTOBW8b7exaBPfCKJSlv5q320IvWw9hEdtnURtbb0k3HusfZrR4UYiEewem8Nl7VqJILoCj99SjCK3W54UNPg==
   dependencies:
-    babel-runtime "^6.26.0"
-    bluebird "^3.5.1"
-    chalk "2.3.2"
-    commander "^2.16.0"
-    debug "3.1.0"
+    "@babel/polyfill" "^7.0.0"
+    "@types/bluebird" "^3.5.25"
+    bluebird "^3.5.3"
+    chalk "2.4.1"
+    commander "^2.19.0"
+    debug "4.1.0"
     inherits "~2.0.3"
     interpret "^1.1.0"
     liftoff "2.5.0"
-    lodash "^4.17.10"
+    lodash "^4.17.11"
     minimist "1.2.0"
     mkdirp "^0.5.1"
     pg-connection-string "2.0.0"
@@ -11348,7 +11360,7 @@ path-key@^2.0.0, path-key@^2.0.1:
   resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
   integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
 
-path-parse@^1.0.5:
+path-parse@^1.0.5, path-parse@^1.0.6:
   version "1.0.6"
   resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
   integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
@@ -13510,13 +13522,20 @@ resolve@1.1.7:
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
   integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=
 
-resolve@^1.1.6, resolve@^1.1.7, resolve@^1.3.3, resolve@^1.5.0, resolve@^1.6.0:
+resolve@^1.1.6, resolve@^1.3.3, resolve@^1.5.0, resolve@^1.6.0:
   version "1.8.1"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26"
   integrity sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==
   dependencies:
     path-parse "^1.0.5"
 
+resolve@^1.1.7:
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.9.0.tgz#a14c6fdfa8f92a7df1d996cb7105fa744658ea06"
+  integrity sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==
+  dependencies:
+    path-parse "^1.0.6"
+
 restore-cursor@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541"
@@ -14254,11 +14273,6 @@ stack-utils@^1.0.1:
   resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8"
   integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==
 
-stackback@0.0.2:
-  version "0.0.2"
-  resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b"
-  integrity sha1-Gsig2Ug4SNFpXkGLbQMaPDzmjjs=
-
 staged-git-files@1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/staged-git-files/-/staged-git-files-1.0.0.tgz#cdb847837c1fcc52c08a872d4883cc0877668a80"
@@ -15561,9 +15575,9 @@ v8flags@^2.1.1:
     user-home "^1.1.1"
 
 v8flags@^3.1.1:
-  version "3.1.1"
-  resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.1.1.tgz#42259a1461c08397e37fe1d4f1cfb59cad85a053"
-  integrity sha512-iw/1ViSEaff8NJ3HLyEjawk/8hjJib3E7pvG4pddVXfUg1983s3VGsiClDjhK64MQVDGqc1Q8r18S4VKQZS9EQ==
+  version "3.1.2"
+  resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.1.2.tgz#fc5cd0c227428181e6c29b2992e4f8f1da5e0c9f"
+  integrity sha512-MtivA7GF24yMPte9Rp/BWGCYQNaUj86zeYxV/x2RRJMKagImbbv3u8iJC57lNhWLPcGLJmHcHmFWkNsplbbLWw==
   dependencies:
     homedir-polyfill "^1.0.1"
 
@@ -15973,13 +15987,6 @@ which@1, which@^1.2.10, which@^1.2.12, which@^1.2.14, which@^1.2.9, which@^1.3.0
   dependencies:
     isexe "^2.0.0"
 
-why-is-node-running@^2.0.3:
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.0.3.tgz#86619c2861405d3509f55268684fc85e7f4ce145"
-  integrity sha512-XmzbFN2T859avcs5qAsiiK1iu0nUpSUXRgiGsoHPcNijxhIlp1bPQWQk6ANUljDWqBtAbIR2jF1HxR0y2l2kCA==
-  dependencies:
-    stackback "0.0.2"
-
 wide-align@^1.1.0:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
-- 
GitLab