mirror of
https://github.com/wassname/talk.git
synced 2026-07-02 06:31:39 +08:00
Merge pull request #746 from coralproject/create-plugin
Create Plugins - Create plugins through the CLI
This commit is contained in:
+120
-1
@@ -8,13 +8,14 @@
|
||||
// https://yarnpkg.com/
|
||||
|
||||
const program = require('./commander');
|
||||
const inquirer = require('inquirer');
|
||||
|
||||
// Make things colorful!
|
||||
require('colors');
|
||||
const emoji = require('node-emoji');
|
||||
|
||||
const dir = process.cwd();
|
||||
const fs = require('fs');
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const spawn = require('cross-spawn');
|
||||
const semver = require('semver');
|
||||
@@ -272,10 +273,128 @@ async function reconcilePluginDeps({skipLocal, skipRemote, dryRun, upgradeRemote
|
||||
console.log(`✨ Done in ${totalTime}s.`);
|
||||
}
|
||||
|
||||
async function createSeedPlugin() {
|
||||
const pluginsDir = path.join(__dirname, 'plugins');
|
||||
|
||||
function pluginNameExists(pluginName) {
|
||||
const pluginNames = fs.readdirSync(pluginsDir);
|
||||
return !!pluginNames
|
||||
.filter((pn) => pn === pluginName).length;
|
||||
}
|
||||
|
||||
let answers = await inquirer.prompt([
|
||||
{
|
||||
type: 'input',
|
||||
name: 'pluginName',
|
||||
message: 'Plugin Name:',
|
||||
validate: (input) => {
|
||||
|
||||
if (pluginNameExists(input)) {
|
||||
return 'Please, choose another name. That name already exists';
|
||||
}
|
||||
|
||||
if (input && input.length > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return 'Plugin Name is required.';
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'confirm',
|
||||
name: 'server',
|
||||
message: 'Is this plugin extending the server capabilities?'
|
||||
},
|
||||
{
|
||||
type: 'confirm',
|
||||
name: 'client',
|
||||
message: 'Is this plugin extending the client capabilities?'
|
||||
},
|
||||
{
|
||||
type: 'confirm',
|
||||
name: 'addPluginsJson',
|
||||
message: 'Should we add it to the plugins.json?'
|
||||
}
|
||||
]);
|
||||
|
||||
//==============================================================================
|
||||
// Creating plugin seed
|
||||
//==============================================================================
|
||||
|
||||
const seedPlugin = path.join(__dirname, 'bin/templates/plugin');
|
||||
const newPluginPath = path.join(pluginsDir, answers.pluginName);
|
||||
|
||||
if (fs.existsSync(seedPlugin)) {
|
||||
|
||||
if (answers.server && answers.client) {
|
||||
|
||||
// This is a server-side and client-side plugin!, let's copy the template
|
||||
fs.copySync(seedPlugin, newPluginPath);
|
||||
} else {
|
||||
|
||||
fs.copySync(seedPlugin, newPluginPath, {filter: (p) => {
|
||||
|
||||
// Allowing plugin folder and files with no subfolders
|
||||
const rootRx = /plugin$|plugin\/[^/]*(\.).{2,3}/igm;
|
||||
if (rootRx.test(p) && (fs.lstatSync(p).isDirectory() || fs.lstatSync(p).isFile())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If it's a client-side plugin, copying client folder
|
||||
if (answers.client) {
|
||||
return /client/.test(p);
|
||||
}
|
||||
|
||||
// If it's a server-side plugin, copying server folder
|
||||
if (answers.server) {
|
||||
return /server/.test(p);
|
||||
}
|
||||
|
||||
}});
|
||||
}
|
||||
|
||||
// Let's add this to the plugins.json
|
||||
if (answers.addPluginsJson) {
|
||||
const pluginsJson = path.join(dir, 'plugins.json');
|
||||
|
||||
fs.readJson(pluginsJson)
|
||||
.then((j) => {
|
||||
|
||||
// This is a client-side plugin, let's push this.
|
||||
if (answers.client) {
|
||||
j.client.push(answers.pluginName);
|
||||
|
||||
const output = JSON.stringify(j, null, 2);
|
||||
fs.writeFileSync(pluginsJson, output);
|
||||
}
|
||||
|
||||
// This is a server-side plugin, let's push this.
|
||||
if (answers.server) {
|
||||
j.server.push(answers.pluginName);
|
||||
|
||||
const output = JSON.stringify(j, null, 2);
|
||||
fs.writeFileSync(pluginsJson, output);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
console.log(`✨ Yay! Plugin created! Find your plugin: ${answers.pluginName} in the ./plugins folder`);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Setting up the program command line arguments.
|
||||
//==============================================================================
|
||||
|
||||
program
|
||||
.command('create')
|
||||
.description('creates a seed plugin')
|
||||
.action(createSeedPlugin);
|
||||
|
||||
program
|
||||
.command('list')
|
||||
.description('')
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"presets": [
|
||||
"es2015"
|
||||
],
|
||||
"plugins": [
|
||||
"add-module-exports",
|
||||
"transform-class-properties",
|
||||
"transform-decorators-legacy",
|
||||
"transform-object-assign",
|
||||
"transform-object-rest-spread",
|
||||
"transform-async-to-generator",
|
||||
"transform-react-jsx"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"mocha": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {
|
||||
"experimentalObjectRestSpread": true,
|
||||
"jsx": true
|
||||
}
|
||||
},
|
||||
"parser": "babel-eslint",
|
||||
"plugins": [
|
||||
"react"
|
||||
],
|
||||
"rules": {
|
||||
"react/jsx-uses-react": "error",
|
||||
"react/jsx-uses-vars": "error",
|
||||
"no-console": ["warn", { "allow": ["warn", "error"] }]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
.myPluginContainer {
|
||||
padding: 10px;
|
||||
background: #f0f0f0;
|
||||
border: 1px solid #d6d6d6;
|
||||
margin: 10px 0;
|
||||
text-align: center;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
position: block;
|
||||
animation: spin 2s infinite ease;
|
||||
animation-delay: 1s;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.description {
|
||||
color: #444444;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import React from 'react';
|
||||
import {CoralLogo} from 'plugin-api/beta/client/components/ui';
|
||||
import styles from './MyPluginComponent.css';
|
||||
|
||||
class MyPluginComponent extends React.Component {
|
||||
render() {
|
||||
return (
|
||||
<div className={styles.myPluginContainer}>
|
||||
<CoralLogo className={styles.logo}/>
|
||||
<div className={styles.description}>
|
||||
<h3>Plugin created by Talk CLI</h3>
|
||||
|
||||
<small>
|
||||
To read more about plugins check{' '}
|
||||
<a href="https://coralproject.github.io/talk/plugins-client.html">
|
||||
our docs and guides!
|
||||
</a>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default MyPluginComponent;
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
/**
|
||||
This is a client index example file and it could look like this:
|
||||
|
||||
```
|
||||
import LoveButton from './components/LoveButton';
|
||||
|
||||
export default {
|
||||
slots: {
|
||||
commentReactions: [LoveButton]
|
||||
},
|
||||
reducer,
|
||||
translations
|
||||
};
|
||||
```
|
||||
|
||||
To read more info on how to build client plugins. Please, go to: https://coralproject.github.io/talk/plugins-client.html
|
||||
*/
|
||||
|
||||
import MyPluginComponent from './components/MyPluginComponent';
|
||||
|
||||
export default {
|
||||
slots: {
|
||||
stream: [MyPluginComponent]
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# This file is for translations and they should look like this:
|
||||
#
|
||||
#
|
||||
# ```
|
||||
# en:
|
||||
# coral-plugin-respect:
|
||||
# respect: Respect
|
||||
# respected: Respected
|
||||
# es:
|
||||
# coral-plugin-respect:
|
||||
# respect: Respetar
|
||||
# respected: Respetado
|
||||
# ```
|
||||
#
|
||||
@@ -0,0 +1 @@
|
||||
module.exports = {};
|
||||
@@ -15,9 +15,9 @@ function getSlotComponents(slot) {
|
||||
|
||||
// Filter out components that have been disabled in `plugin_config`
|
||||
return flatten(plugins
|
||||
|
||||
// Filter out components that have been disabled in `plugin_config`
|
||||
.filter((o) => !pluginConfig || !pluginConfig[o.plugin] || !pluginConfig[o.plugin].disable_components)
|
||||
|
||||
// Filter out components that have slots and have been disabled in `plugin_config`
|
||||
.filter((o) => o.module.slots && (!pluginConfig || !pluginConfig[o.plugin] || !pluginConfig[o.plugin].disable_components))
|
||||
|
||||
.filter((o) => o.module.slots[slot])
|
||||
.map((o) => o.module.slots[slot]));
|
||||
@@ -78,7 +78,7 @@ export function getSlotsFragments(slots) {
|
||||
}
|
||||
const components = uniq(flattenDeep(slots.map((slot) => {
|
||||
return plugins
|
||||
.filter((o) => o.module.slots[slot])
|
||||
.filter((o) => o.module.slots ? o.module.slots[slot] : false)
|
||||
.map((o) => o.module.slots[slot]);
|
||||
})));
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
"express": "^4.15.2",
|
||||
"express-session": "^1.15.1",
|
||||
"form-data": "^2.1.2",
|
||||
"fs-extra": "^3.0.1",
|
||||
"gql-merge": "^0.0.4",
|
||||
"graphql": "^0.9.1",
|
||||
"graphql-errors": "^2.1.0",
|
||||
|
||||
@@ -3290,6 +3290,14 @@ fs-extra@^0.26.4:
|
||||
path-is-absolute "^1.0.0"
|
||||
rimraf "^2.2.8"
|
||||
|
||||
fs-extra@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-3.0.1.tgz#3794f378c58b342ea7dbbb23095109c4b3b62291"
|
||||
dependencies:
|
||||
graceful-fs "^4.1.2"
|
||||
jsonfile "^3.0.0"
|
||||
universalify "^0.1.0"
|
||||
|
||||
fs-promise@^0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/fs-promise/-/fs-promise-0.3.1.tgz#bf34050368f24d6dc9dfc6688ab5cead8f86842a"
|
||||
@@ -4614,6 +4622,10 @@ json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1:
|
||||
dependencies:
|
||||
jsonify "~0.0.0"
|
||||
|
||||
json-stringify-pretty-compact@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/json-stringify-pretty-compact/-/json-stringify-pretty-compact-1.0.4.tgz#d5161131be27fd9748391360597fcca250c6c5ce"
|
||||
|
||||
json-stringify-safe@~5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
|
||||
@@ -4632,6 +4644,12 @@ jsonfile@^2.1.0:
|
||||
optionalDependencies:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
jsonfile@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66"
|
||||
optionalDependencies:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
jsonify@~0.0.0:
|
||||
version "0.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
|
||||
@@ -8263,6 +8281,10 @@ uniqs@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02"
|
||||
|
||||
universalify@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.0.tgz#9eb1c4651debcc670cc94f1a75762332bb967778"
|
||||
|
||||
unpipe@1.0.0, unpipe@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
|
||||
|
||||
Reference in New Issue
Block a user