Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Feature/Module/connector => "Plugin" (Second try) #591

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
38 changes: 19 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,33 +202,33 @@ There are also application config options available in `app.json` to aid with de
| debugSQL | Print executed by backend SQL commands |
| apolloLogging | Log all Apollo GraphQL operations |

### Feature Modules Scaffolding with CLI
### Plugin Scaffolding with CLI

This starter kit encourages modular design of application features. Each feature should be designed as a decoupled
module, deleting feature should ideally not break the remaining application. Basic feature module scaffolding is
module called a plugin. Deleting a plugin should ideally not break the remaining application. Basic plugin scaffolding is
provided with the following command:

```
yarn cli addmodule <moduleName>
yarn cli addplugin <pluginName>
```

This will create all the necessary files to start developing on a new feature module. It creates `client` and `server`
module. If you would like to only add one or the other, add a second parameter like:
This will create all the necessary files to start developing on a new plugin. It creates `client` and `server`
plugin. If you would like to only add one or the other, add a second parameter like:

```
yarn cli addmodule <moduleName> [client|server]
yarn cli addplugin <pluginName> [client|server]
```

If you wish to remove an existing module, do so with:
If you wish to remove an existing plugin, do so with:

```
yarn cli deletemodule <moduleName>
yarn cli deleteplugin <pluginName>
```

Again you can specify `client` or `server` as a second parameter, if you only wish to delete one or the other.

This way you can easily delete existing examples, like `counter`, `post` or `user`. Do keep in mind that you need at
least one module linked on the server side. So deleting both, before creating any new ones first, will result in
least one plugin linked on the server side. So deleting both, before creating any new ones first, will result in
`TypeError: Cannot read property 'schema' of undefined` on the server side.

Run the following command to see the CLI help:
Expand All @@ -237,12 +237,12 @@ Run the following command to see the CLI help:
yarn cli
```

## Features and examples included
## Plugins and examples included

* Full LOGIN funcionality in user example with [JWT] tokens stored in `localStorage` and `cookies`

* [Stripe] Payment Processor integration as a starting point for apps that use user subscriptions.
Check [subscription module documentation](src/client/modules/subscription/README.md) for details.
Check [subscription plugin documentation](src/client/plugins/subscription/README.md) for details.

* [GraphQL] API

Expand All @@ -264,7 +264,7 @@ Check [subscription module documentation](src/client/modules/subscription/README
* [Webpack] for back end

This starter kit is different from most of the starter kits out there, because it uses Webpack not only for front end,
but for back-end code as well. This enables powerful Webpack features for back-end code, such as conditional
but for back-end code as well. This enables powerful Webpack plugins for back-end code, such as conditional
compilation, embedding non-js files and CSS stylesheets into the code, hot code reload, etc.

* [Webpack] and [Expo] for mobile front-end
Expand Down Expand Up @@ -317,10 +317,10 @@ Check [subscription module documentation](src/client/modules/subscription/README

If you would like to use a different styling than [Twitter Bootstrap], UI components are structured in a way to make
it easy to use something else. We already prepared [Ant Design] integation. To switch the UI all you need to do is
rename the import in `src/client/modules/common/components/web/index.jsx`.
rename the import in `src/client/plugins/common/components/web/index.jsx`.

[NativeBase] for mobile styling, with an option to use [Ant Design Mobile]. To switch, just change the export in
`src/client/modules/common/components/native/index.jsx`.
`src/client/plugins/common/components/native/index.jsx`.

* [Babel] for ES2017 transpiling

Expand All @@ -341,7 +341,7 @@ Check [subscription module documentation](src/client/modules/subscription/README

## Project Structure

The project structure presented in this boilerplate is **fractal**, where functionality is grouped primarily by feature
The project structure presented in this boilerplate is **fractal**, where functionality is grouped primarily by plugin
rather than file type. This structure is only meant to serve as a guide, it is by no means prescriptive. That said, it
aims to represent generally accepted guidelines and patterns for building scalable applications.

Expand All @@ -350,7 +350,7 @@ aims to represent generally accepted guidelines and patterns for building scalab
├── src # Application source code
│ ├── client # Front-end source code
│ │ ├── app # Common front-end application code
│ │ └── modules # Front-end feature-modules, each module has:
│ │ └── plugins # Front-end plugins, each plugin has:
│ │ │ # (components, containers, GraphQL queries, redux reducers)
│ │ └── styles # Application-wide styles
│ │ └── testHelpers # Test helper for front-end integration tests
Expand All @@ -364,9 +364,9 @@ aims to represent generally accepted guidelines and patterns for building scalab
│ │ │ └── migrations # Database migration scripts using Knex
│ │ │ └── seeds # Database seed scripts using Knex
│ │ └── middleware # Graphiql, GraphQL express and SSR rendering
│ │ └── modules # Back-end server feature-modules, each module has:
│ │ └── plugins # Back-end server plugins, each plugin has:
│ │ │ # (schema definition, resolvers, sql queries)
│ │ └── sql # Knex connector
│ │ └── sql # Knex connection
│ │ └── testHelpers # Test helper for back-end integration tests
│ │ └── server.js # GraphQL api server set up
│ │ └── index.js # Entry point to back-end wtih hot code reload
Expand All @@ -389,7 +389,7 @@ While developing, you will probably rely mostly on `yarn watch`; however, there
| `seed` | Seed sample database using SQLite. Use `--prod` flag to run in "production" mode. |
| `migrate` | Migrate the sample database |
| `rollback` | Rollback the sample database to previous state. |
| `cli` | CLI tool, currently used for modules scaffolding only. |
| `cli` | CLI tool, currently used for plugins scaffolding only. |

## Deployment to Production

Expand Down
14 changes: 7 additions & 7 deletions src/client/app/Main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,17 @@ import createApolloClient from '../../common/createApolloClient';
import createReduxStore, { storeReducer } from '../../common/createReduxStore';
import settings from '../../../settings';
import Routes from './Routes';
import modules from '../modules';
import plugins from '../plugins';

const { hostname, pathname, port } = url.parse(__BACKEND_URL__);

const fetch = createApolloFetch({
uri: hostname === 'localhost' ? '/graphql' : __BACKEND_URL__,
constructOptions: modules.constructFetchOptions
constructOptions: plugins.constructFetchOptions
});
const cache = new InMemoryCache();

for (const middleware of modules.middlewares) {
for (const middleware of plugins.middlewares) {
fetch.batchUse(({ requests, options }, next) => {
options.credentials = 'same-origin';
options.headers = options.headers || {};
Expand All @@ -51,14 +51,14 @@ for (const middleware of modules.middlewares) {
});
}

for (const afterware of modules.afterwares) {
for (const afterware of plugins.afterwares) {
fetch.batchUseAfter(({ response, options }, next) => {
afterware(response, options, next);
});
}

let connectionParams = {};
for (const connectionParam of modules.connectionParams) {
for (const connectionParam of plugins.connectionParams) {
Object.assign(connectionParams, connectionParam());
}

Expand All @@ -76,7 +76,7 @@ wsClient.use([
{
applyMiddleware(operationOptions, next) {
let params = {};
for (const param of modules.connectionParams) {
for (const param of plugins.connectionParams) {
Object.assign(params, param());
}

Expand Down Expand Up @@ -176,7 +176,7 @@ export default class Main extends React.Component {
return this.state.error ? (
<RedBox error={this.state.error} />
) : (
modules.getWrappedRoot(
plugins.getWrappedRoot(
<Provider store={store}>
<ApolloProvider client={client}>
<ConnectedRouter history={history}>{Routes}</ConnectedRouter>
Expand Down
4 changes: 2 additions & 2 deletions src/client/app/Routes.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { TabNavigator } from 'react-navigation';

import modules from '../modules';
import plugins from '../plugins';

const MainScreenNavigator = TabNavigator({
...modules.tabItems
...plugins.tabItems
});

export default MainScreenNavigator;
4 changes: 2 additions & 2 deletions src/client/app/Routes.web.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { Switch } from 'react-router-dom';

import modules from '../modules';
import plugins from '../plugins';

export default <Switch>{modules.routes}</Switch>;
export default <Switch>{plugins.routes}</Switch>;
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Row from 'antd/lib/row';
import Col from 'antd/lib/col';
import MenuItem from './MenuItem';

import modules from '../../../../../../modules';
import plugins from '../../../../../../plugins';
import settings from '../../../../../../../../settings';

class NavBar extends React.Component {
Expand Down Expand Up @@ -36,7 +36,7 @@ class NavBar extends React.Component {
{settings.app.name}
</NavLink>
</MenuItem>
{modules.navItems}
{plugins.navItems}
</Menu>
</Col>
<Col span={10}>
Expand All @@ -47,7 +47,7 @@ class NavBar extends React.Component {
theme="dark"
style={{ lineHeight: '64px', float: 'right' }}
>
{modules.navItemsRight}
{plugins.navItemsRight}
{__DEV__ && (
<MenuItem>
<a href="/graphiql">GraphiQL</a>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import { NavLink } from 'react-router-dom';
import { Container, Navbar, Nav, NavItem } from 'reactstrap';

import modules from '../../../../../../modules';
import plugins from '../../../../../../plugins';
import settings from '../../../../../../../../settings';

const NavBar = () => (
Expand All @@ -12,11 +12,11 @@ const NavBar = () => (
<NavLink to="/" className="navbar-brand">
{settings.app.name}
</NavLink>
{modules.navItems}
{plugins.navItems}
</Nav>

<Nav className="ustify-content-end">
{modules.navItemsRight}
{plugins.navItemsRight}
{(!__PERSIST_GQL__ || __DEV__) && (
<NavItem>
<a href="/graphiql" className="nav-link">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { Ionicons } from '@expo/vector-icons';
import { createTabBarIconWrapper } from '../common/components/native';
import Contact from './containers/Contact';

import Feature from '../connector';
import Plugin from '../plugin';

export default new Feature({
export default new Plugin({
tabItem: {
Contact: {
screen: Contact,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React from 'react';
import { Route, NavLink } from 'react-router-dom';
import { MenuItem } from '../../modules/common/components/web';
import { MenuItem } from '../../plugins/common/components/web';
import Contact from './containers/Contact';

import Feature, { featureCatalog } from '../connector';
import Plugin, { featureCatalog } from '../plugin';

console.log('catalog:', featureCatalog);

export default new Feature({
export default new Plugin({
route: <Route exact path="/contact" component={Contact} />,
navItem: (
<MenuItem key="contact">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { createTabBarIconWrapper } from '../common/components/native';
import Counter from './containers/Counter';
import reducers from './reducers';

import Feature from '../connector';
import Plugin from '../plugin';

export default new Feature({
export default new Plugin({
tabItem: {
Counter: {
screen: Counter,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { Route } from 'react-router-dom';
import Counter from './containers/Counter';
import reducers from './reducers';

import Feature from '../connector';
import Plugin from '../plugin';

export default new Feature({
export default new Plugin({
route: <Route exact path="/" component={Counter} />,
reducer: { counter: reducers }
});
4 changes: 2 additions & 2 deletions src/client/modules/index.js → src/client/plugins/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ import contact from './contact';
import pageNotFound from './pageNotFound';
import './favicon';

import Feature from './connector';
import Plugin from './plugin';

export default new Feature(counter, post, upload, user, subscription, contact, pageNotFound);
export default new Plugin(counter, post, upload, user, subscription, contact, pageNotFound);
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import React from 'react';
import { Route } from 'react-router-dom';

import PageNotFound from './containers/PageNotFound';
import Feature from '../connector';
import Plugin from '../plugin';

export default new Feature({
export default new Plugin({
route: <Route component={PageNotFound} />
});
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

mutation addComment($input: AddCommentInput!) {
addComment(input: $input) {
... CommentInfo
...CommentInfo
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

mutation addPost($input: AddPostInput!) {
addPost(input: $input) {
... PostInfo
...PostInfo
comments {
... CommentInfo
...CommentInfo
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ subscription onCommentUpdated($postId: Int!) {
id
postId
node {
... CommentInfo
...CommentInfo
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

mutation editComment($input: EditCommentInput!) {
editComment(input: $input) {
... CommentInfo
...CommentInfo
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

mutation editPost($input: EditPostInput!) {
editPost(input: $input) {
... PostInfo
...PostInfo
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

query post($id: Int!) {
post(id: $id) {
... PostInfo
...PostInfo
comments {
... CommentInfo
...CommentInfo
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

subscription onPostUpdated($id: Int!) {
postUpdated(id: $id) {
... PostInfo
...PostInfo
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ query posts($limit: Int!, $after: Int) {
edges {
cursor
node {
... PostInfo
...PostInfo
}
}
pageInfo {
Expand Down
Loading