Skip to content

Commit

Permalink
Merge pull request #886 from infinitered/project-plugins
Browse files Browse the repository at this point in the history
Plugins that only live in your project.
  • Loading branch information
GantMan authored Mar 11, 2017
2 parents bcef5c1 + e539b12 commit 6549627
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 37 deletions.
32 changes: 13 additions & 19 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,19 @@
# Ignite Documentation

This is a list of documentation ideas.

## Advanced Guides
## Quick Start

* Creating plugins from scratch
* Creating plugins from an existing component
* Sporking template (why and how)
* How to test your plugin
* Creating your own "extensions" (these are 'libraries' things that can be used by plugins - such as file patching)
* Installing
* [Getting started](./quick-start/getting-started.md)
* [Ignite commands](./quick-start/ignite-commands.md)
* [Using boilerplates](./quick-start/using-boilerplates.md)
* Removing plugins
* Spork! - tweaking 3rd-party generators

## API
## Advanced Guides

## Quick Start
* [Creating plugins](./advanced-guides/creating-plugins.md)
* [Creating project plugins](./advanced-guides/creating-project-plugins.md)
* Writing tests for plugins
* Releasing plugins
* Creating extensions

* Using boilerplates
* Removing plugins you don't like
* Project plugins vs 3rd party plugins
* Gluegun and its features
* App structure
* Use and adding Generators
* Adding plugins
* Editing generators and the templates they use
* Ignite commands
8 changes: 2 additions & 6 deletions docs/advanced-guides/creating-plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,21 @@ Open up `package.json` and add your desired info.
{
"name": "ignite-radio-buttons",
"version": "0.0.1",
"description": "",
"description": "An Ignite plugin for react-native-radio-buttons.",
"license": "MIT",
"devDependencies": {},
"url": "https://github.com/infinitered/ignite-radio-buttons/issues",
"author": {
"name": "Robin Heinze",
"email": "robin@infinite.red",
"url": "https://infinite.red"
},
"devEngines": {
"node": ">=7.x",
"npm": ">=4.x"
}
}
```

### Edit the `index.js`

The `index.js` is the entrypoint for your plugin and provides the add/remove functionality. We need to make sure that the npm packages installed and component examples are copied over.
The `index.js` is the entrypoint for your plugin and provides the add/remove functionality. We need to make sure that the npm packages installed and component examples are copied over.

1. Change the `NPM_MODULE_NAME` to `react-native-radio-buttons`
2. Since this npm package does not require a linking step, we will change `ignite.addModule` to have `link: false` and `ignite.removeModule` to have `unlink: false`
Expand Down
72 changes: 72 additions & 0 deletions docs/advanced-guides/creating-project-plugins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Creating Project Plugins

First read the [creating plugins guide](./creating-plugins.md). It covers the structure of plugins.

Project-based plugins are plugins which stay within your repo. They're a great way to add some features to Ignite without going through the hassle or commitment of publishing to NPM.

Some examples of this might be:

* generators that make little sense outside your project
* scripts that are a bit more complex than a one liner inside your `package.json`
* a playground for exploring ignite
* a proving arena for plugins you intend to build & release, but aren't quite ready yet

## The ignite/plugins Directory

You place your plugins in the `ignite/plugins` directory. Plugins are directories themselves, so begin by creating a `sample` directory there.

In this directory, create a file called `ignite.json` and put this empty object inside:

```json
{}
```

Next create a new text file in that directory, naming it `ignite.toml`. Inside, place this:

```toml
description = "🔥🔥🔥 It's plugin time!🔥🔥🔥"
```

> Note! This will be replaced shortly with `ignite.json`. I just need to patch up gluegun to provide a post-load hook so ignite can do this.
## Running Your Plugin

Back in the project root, type:

```sh
ignite
```

You should see your plugin appear. Now, let's list the commands that you've made:

```sh
ignite sample
```

Empty. Let's make one by creating a new directory: `ignite/plugins/sample/commands`. In that directory place this `online.js`.

```js
// @cliDescription Let's gather some useful data on this mission!

module.exports = context => {
const { filesystem, print } = context
const { colors } = print

const pkg = filesystem.read('package.json', 'json')
const depsCount = Object.keys(pkg.dependencies || {}).length
print.info(`You have ${colors.bold(depsCount)} direct dependencies. And they are awesome.`)
}

```

```sh
ignite sample
```

Now you have one. Let's run it.

```sh
ignite sample online
```

For more details on creating commands (including generators), check out [the guide to plugins](./creating-plugins.md) and the [context API guide](https://infinitered.github.io/gluegun/#/context-api).
1 change: 1 addition & 0 deletions packages/ignite-cli/src/cli/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const buildIgnite = () => {
return build()
.brand('ignite')
.loadDefault(`${__dirname}/..`)
.loadAll(`${process.cwd()}/ignite/plugins`)
.loadAll(`${process.cwd()}/node_modules`, { matching: 'ignite-*', hidden: true })
.token('commandName', 'cliCommand')
.token('commandHidden', 'cliHidden')
Expand Down
37 changes: 25 additions & 12 deletions packages/ignite-cli/src/extensions/ignite/findIgnitePlugins.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
const { pipe, filter, propSatisfies, sortBy, prop } = require('ramda')
const {
contains,
anyPass,
pipe,
filter,
propSatisfies,
sortBy,
prop
} = require('ramda')
const { startsWith } = require('ramdasauce')

module.exports = (plugin, command, context) => {
// gluegun stuff
const { runtime, filesystem: { separator } } = context

// how to identify ignite plugins
const ignitePrefixed = propSatisfies(startsWith('ignite-'), 'name')
const isInRightLocation = contains(`ignite${separator}plugins`)
const inProjectPlugins = propSatisfies(isInRightLocation, 'directory')
const onlyIgnitePlugins = filter(anyPass([ignitePrefixed, inProjectPlugins]))
const getIgnitePlugins = pipe(onlyIgnitePlugins, sortBy(prop('name')))

/**
* Finds the gluegun plugins that are also ignite plugins.
* Finds the gluegun plugins that are also ignite plugins. These are
* plugins which have 1 of the following:
*
* - the name starts with "ignite-"
* - the directory contains "ignite/plugins"
*
* @returns {Plugin[]} - an array of ignite plugins
*/
function findIgnitePlugins () {
const { runtime } = context

return pipe(
filter(propSatisfies(startsWith('ignite-'), 'name')),
sortBy(prop('name'))
)(runtime.plugins)
}

return findIgnitePlugins
return () => getIgnitePlugins(runtime.plugins)
}
4 changes: 4 additions & 0 deletions packages/ignite-cli/tests/cli/cliConfig.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ test('ignite', async t => {
t.deepEqual(builderProps, {
brand: 'ignite',
loadAlls: [
{
dir: `${process.cwd()}/ignite/plugins`,
opts: {}
},
{
dir: `${process.cwd()}/node_modules`,
opts: { hidden: true, matching: 'ignite-*' }
Expand Down
54 changes: 54 additions & 0 deletions packages/ignite-cli/tests/extensions/findIgnitePlugins.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const test = require('ava')
const extension = require('../../src/extensions/ignite/findIgnitePlugins')

test('has the right interface', t => {
t.is(typeof extension, 'function')
const context = { filesystem: { separator: '/' } }
const findIgnitePlugin = extension(null, null, context)
t.is(typeof findIgnitePlugin, 'function')
})

test('plugin-less', t => {
const context = {
filesystem: { separator: '/' },
runtime: {
plugins: []
}
}
const findIgnitePlugin = extension(null, null, context)
t.deepEqual(findIgnitePlugin(), [])
})

test('skips non-ignite plugins', t => {
const context = {
filesystem: { separator: '/' },
runtime: {
plugins: [{ name: 'x', directory: 'y' }]
}
}
const findIgnitePlugin = extension(null, null, context)
t.deepEqual(findIgnitePlugin(), [])
})

test('finds ignite- prefixed plugins', t => {
const context = {
filesystem: { separator: '/' },
runtime: {
plugins: [{ name: 'ignite-foo', directory: 'y' }]
}
}
const findIgnitePlugin = extension(null, null, context)
t.deepEqual(findIgnitePlugin(), [{ name: 'ignite-foo', directory: 'y' }])
})

test('finds project plugins', t => {
const dir = `${process.cwd()}/ignite/plugins/y`
const context = {
filesystem: { separator: '/' },
runtime: {
plugins: [{ name: 'x', directory: dir }]
}
}
const findIgnitePlugin = extension(null, null, context)
t.deepEqual(findIgnitePlugin(), [{ name: 'x', directory: dir }])
})
3 changes: 3 additions & 0 deletions packages/ignite-cli/tests/extensions/ignite.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ test('has the right interface', t => {
},
system: {
which: () => true
},
filesystem: {
separator: '/'
}
}
const extension = attach(plugin, command, context)
Expand Down

0 comments on commit 6549627

Please sign in to comment.