Commit d6b90baa authored by Jure's avatar Jure

Merge branch 'remove_add_and_remove' into 'master'

feat(cli): remove adding and removing components

Closes #449

See merge request !574
parents 5be108ee c12251eb
Pipeline #13051 passed with stages
in 14 minutes and 48 seconds
......@@ -2,21 +2,11 @@ Using a component is as simple as installing it, configuring it, and then includ
## Installing
Components can be installed using the PubSweet CLI:
Components can be installed using the yarn:
pubsweet add login
`yarn add pubsweet-component-login`
This installs the `pubsweet-component-login` package, and adds the component to the app config so PubSweet knows to load it.
Note that the CLI adds the `pubsweet-component-` prefix automatically if it's not already present.
You can also manually install components using npm or yarn:
npm install \--save pubsweet-component-login
yarn add pubsweet-component-login
If you do that, you'll need to also add the component manually to the list in `config/components.json`.
You can then add the component to the list in `config/components.json`.
## Configuring
......
......@@ -20,7 +20,7 @@
- [Building your app (`pubsweet build`)](#building-your-app-pubsweet-build)
- [Running your app](#running-your-app)
- [Managing your app](#managing-your-app)
- [Adding and removing components (`pubsweet add`, `pubsweet remove`)](#adding-and-removing-components-pubsweet-add-pubsweet-remove)
- [Adding and removing components](#adding-and-removing-components)
- [Adding a user to the database (`pubsweet adduser`)](#adding-a-user-to-the-database-pubsweet-adduser)
- [Contributing](#contributing)
- [Credits](#credits)
......@@ -106,8 +106,6 @@ Commands:
build build static assets for a pubsweet app
start start pubsweet server and backing services
server build static assets and start a pubsweet app
add add one or more components to a pubsweet app
remove remove one or more components from a pubsweet app
adduser add a user to the database for a pubsweet app
help [cmd] display help for [cmd]
......@@ -233,27 +231,11 @@ Ensure that the `NODE_ENV` environment variable is set to `production`.
## Managing your app
### Adding and removing components (`pubsweet add`, `pubsweet remove`)
### Adding and removing components
Components add pages, actions, and behaviors to pubsweet. There are many we have
bundled by default, and you can create your own. To learn more about components,
[read the documentation](https://pubsweet.org/docs/components).
Components add models, UI, APIs, jobs, and much more to PubSweet. There are a number in core (https://gitlab.coko.foundation/pubsweet/pubsweet/tree/master/components), and you can create your own.
Run `add` or `remove` within your app directory, followed by one or more
components, to add and remove components. These subcommands use `yarn` to add or
remove the components and updates the configuration for your app accordingly.
```bash
cd myappname
pubsweet add users-manager items-manager
pubsweet remove users-manager items-manager
```
Find all available components by typing:
```bash
pubsweet components
```
To add or remove a component, install it via `yarn add component-name` (or `yarn remove` to uninstall) and edit `config/components.json` in your app's directory accordingly.
### Adding a user to the database (`pubsweet adduser`)
......@@ -283,7 +265,7 @@ pubsweet adduser \
# Contributing
Please read our
[CONTRIBUTING](https://gitlab.coko.foundation/pubsweet/blob/master/CONTRIBUTING)
[CONTRIBUTING](https://gitlab.coko.foundation/pubsweet/pubsweet/blob/master/CONTRIBUTING)
guide.
# Credits
......@@ -292,7 +274,6 @@ guide.
<a href="https://gitlab.coko.foundation/pubsweet/pubsweet"><img src="https://gitlab.coko.foundation/pubsweet/pubsweet/raw/master/assets/rgb-medium.jpg" width="300" /></a>
PubSweet is part of the
[Collaborative Knowledge Foundation](https://coko.foundation) family.
PubSweet is part of [Collaborative Knowledge Foundation](https://coko.foundation).
<a href="https://coko.foundation"><img src="https://gitlab.coko.foundation/pubsweet/pubsweet/raw/master/assets/COKO_logo.jpg" width="300" /></a>
#!/usr/bin/env node
require('../cli/add')().catch(require('../src/error-exit'))
#!/usr/bin/env node
require('../cli/remove')().catch(require('../src/error-exit'))
const logger = require('@pubsweet/logger')
const colors = require('colors/safe')
const program = require('commander')
const _ = require('lodash')
const readCommand = async argsOverride => {
program.arguments('<components>').description(`Add component(s) to an app.
<components> - a space-separated list of one or more components.`)
return program.parse(argsOverride || process.argv)
}
module.exports = async argsOverride => {
const commandOpts = await readCommand(argsOverride)
const components = commandOpts.args
if (_.isEmpty(components)) {
const eg = colors.bold(`pubsweet add ${colors.italic('login signup blog')}`)
throw new Error(`You must specify one or more components, e.g. ${eg}`)
}
logger.info(`Installing ${components.length} components...`)
require('../src/package-management/').add(components)
logger.info(`Success: ${components.length} components installed`)
}
const logger = require('@pubsweet/logger')
const colors = require('colors/safe')
const program = require('commander')
const _ = require('lodash')
const readCommand = async argsOverride => {
program.arguments('<components>').description(`Remove component(s) in an app.
<components> - a space-separated list of one or more components.`)
return program.parse(argsOverride || process.argv)
}
module.exports = async argsOverride => {
const commandOpts = await readCommand(argsOverride)
const components = commandOpts.args
if (_.isEmpty(components)) {
const eg = colors.bold(
`pubsweet remove ${colors.italic('login signup blog')}`,
)
throw new Error(`You must specify one or more components, e.g. ${eg}`)
}
logger.info(`Removing ${components.length} components...`)
require('../src/package-management/').remove(components)
logger.info(`Success: ${components.length} components removed`)
}
jest.mock('child_process', () => ({ spawnSync: jest.fn() }))
jest.mock('fs-extra', () => {
const fs = require.requireActual('fs-extra')
fs.writeJsonSync = jest.fn()
fs.ensureFileSync = jest.fn()
return fs
})
jest.mock('../../src/package-management/helpers/', () => {
const helpers = require.requireActual('../../src/package-management/helpers/')
helpers.getDepsFromPackageJson = jest.fn()
return helpers
})
const spawnSpy = require('child_process').spawnSync
const fs = require('fs-extra')
const { getMockArgv } = require('../helpers/')
const runAdd = require('../../cli/add')
const readPkgSpy = require('../../src/package-management/helpers/')
.getDepsFromPackageJson
const writeSpy = fs.writeJsonSync
describe('add', () => {
beforeEach(() => {
jest.clearAllMocks()
})
it('requires a component', async () => {
await expect(runAdd(getMockArgv(''))).rejects.toBeInstanceOf(Error)
})
it('calls function to write new component into components.json with correct argument', async () => {
const componentName = 'test-widget'
const fullName = `pubsweet-component-${componentName}`
readPkgSpy
.mockImplementationOnce(() => ({}))
.mockImplementationOnce(() => ({ [fullName]: 'version' }))
await runAdd(getMockArgv({ args: componentName }))
const { calls } = writeSpy.mock
expect(calls).toHaveLength(1)
expect(calls[0][1]).toContain(fullName)
})
it('spawns yarn child process with correct arguments', async () => {
const componentName = 'test-widget'
await runAdd(getMockArgv({ args: componentName }))
const { calls } = spawnSpy.mock
expect(calls).toHaveLength(1)
expect(calls[0][1][1]).toBe(`pubsweet-component-${componentName}`)
})
})
jest.mock('child_process', () => ({ spawnSync: jest.fn() }))
jest.mock('fs-extra', () => {
const fs = require.requireActual('fs-extra')
fs.writeJsonSync = jest.fn()
fs.ensureFileSync = jest.fn()
return fs
})
jest.mock('../../src/package-management/helpers/', () => {
const helpers = require.requireActual('../../src/package-management/helpers/')
helpers.getDepsFromPackageJson = jest.fn()
return helpers
})
const fs = require('fs-extra')
const { getMockArgv } = require('../helpers/')
const runRemove = require('../../cli/remove')
const spawnSpy = require('child_process').spawnSync
const readPkgSpy = require('../../src/package-management/helpers/')
.getDepsFromPackageJson
const writeSpy = fs.writeJsonSync
describe('remove', () => {
beforeEach(() => {
jest.clearAllMocks()
})
it('requires a component', async () => {
await expect(runRemove(getMockArgv(''))).rejects.toBeInstanceOf(Error)
})
it('removes component from components.json', async () => {
const componentName = 'blog'
const fullName = `pubsweet-component-${componentName}`
readPkgSpy
.mockImplementationOnce(() => ({ [fullName]: 'version' }))
.mockImplementationOnce(() => ({}))
await runRemove(getMockArgv({ args: componentName }))
const { calls } = writeSpy.mock
expect(calls).toHaveLength(1)
expect(calls[0][1]).not.toContain(fullName)
})
it('spawns yarn child process with correct arguments', async () => {
const componentName = 'test-widget'
await runRemove(getMockArgv({ args: componentName }))
const { calls } = spawnSpy.mock
expect(calls).toHaveLength(1)
expect(calls[0][1][1]).toBe(`pubsweet-component-${componentName}`)
})
})
......@@ -67,42 +67,6 @@ describe('CLI: integration test', () => {
})
})
describe('add and remove', () => {
const componentsFile = path.join(appPath, 'config', 'components.json')
const componentName = 'ink-backend'
let oldComponents
beforeAll(() => {
oldComponents = fs.readJsonSync(componentsFile)
})
it('adds component', () => {
const { stdout, stderr } = runCommandSync({
args: `add ${componentName}`,
cwd: appPath,
stdio: 'pipe',
})
console.log(stdout, stderr)
expect(stdout).toContain('Success: 1 components installed')
const configPostAdd = fs.readJsonSync(componentsFile)
expect(configPostAdd).toEqual(
oldComponents.concat(`pubsweet-component-${componentName}`),
)
})
it('removes component', () => {
const { stdout, stderr } = runCommandSync({
args: `remove ${componentName}`,
cwd: appPath,
stdio: 'pipe',
})
console.log(stdout, stderr)
expect(stdout).toContain('Success: 1 components removed')
const configPostRemove = fs.readJsonSync(componentsFile)
expect(configPostRemove).toEqual(oldComponents)
})
})
describe('setupdb', () => {
it('creates tables', () => {
const { stdout, stderr } = runCommandSync({
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment