diff --git a/packages/generators/generate-plop/files/admin/src/containers/App/index.js b/packages/generators/generate-plop/files/admin/src/containers/App/index.js
new file mode 100644
index 0000000000..b2d80ef744
--- /dev/null
+++ b/packages/generators/generate-plop/files/admin/src/containers/App/index.js
@@ -0,0 +1,25 @@
+/**
+ *
+ * This component is the skeleton around the actual pages, and should only
+ * contain code that should be seen on all pages. (e.g. navigation bar)
+ *
+ */
+
+import React from 'react';
+import { Switch, Route } from 'react-router-dom';
+import { NotFound } from '@strapi/helper-plugin';
+import pluginId from '../../pluginId';
+import HomePage from '../HomePage';
+
+const App = () => {
+ return (
+
+
+
+
+
+
+ );
+};
+
+export default App;
diff --git a/packages/generators/generate-plop/files/admin/src/containers/HomePage/index.js b/packages/generators/generate-plop/files/admin/src/containers/HomePage/index.js
new file mode 100644
index 0000000000..05c5a6a377
--- /dev/null
+++ b/packages/generators/generate-plop/files/admin/src/containers/HomePage/index.js
@@ -0,0 +1,20 @@
+/*
+ *
+ * HomePage
+ *
+ */
+
+import React, { memo } from 'react';
+// import PropTypes from 'prop-types';
+import pluginId from '../../pluginId';
+
+const HomePage = () => {
+ return (
+
+
{pluginId}'s HomePage
+
Happy coding
+
+ );
+};
+
+export default memo(HomePage);
diff --git a/packages/generators/generate-plop/files/admin/src/containers/Initializer/index.js b/packages/generators/generate-plop/files/admin/src/containers/Initializer/index.js
new file mode 100644
index 0000000000..71dc50e94c
--- /dev/null
+++ b/packages/generators/generate-plop/files/admin/src/containers/Initializer/index.js
@@ -0,0 +1,26 @@
+/**
+ *
+ * Initializer
+ *
+ */
+
+import { useEffect, useRef } from 'react';
+import PropTypes from 'prop-types';
+import pluginId from '../../pluginId';
+
+const Initializer = ({ setPlugin }) => {
+ const ref = useRef();
+ ref.current = setPlugin;
+
+ useEffect(() => {
+ ref.current(pluginId);
+ }, []);
+
+ return null;
+};
+
+Initializer.propTypes = {
+ setPlugin: PropTypes.func.isRequired,
+};
+
+export default Initializer;
diff --git a/packages/generators/generate-plop/files/admin/src/index.js b/packages/generators/generate-plop/files/admin/src/index.js
new file mode 100644
index 0000000000..704e4277d8
--- /dev/null
+++ b/packages/generators/generate-plop/files/admin/src/index.js
@@ -0,0 +1,62 @@
+import { prefixPluginTranslations } from '@strapi/helper-plugin';
+import pluginPkg from '../../package.json';
+import pluginId from './pluginId';
+import App from './containers/App';
+import Initializer from './containers/Initializer';
+
+const pluginDescription = pluginPkg.strapi.description || pluginPkg.description;
+const icon = pluginPkg.strapi.icon;
+const name = pluginPkg.strapi.name;
+
+export default {
+ register(app) {
+ app.addMenuLink({
+ to: `/plugins/${pluginId}`,
+ icon,
+ intlLabel: {
+ id: `${pluginId}.plugin.name`,
+ defaultMessage: name,
+ },
+ Component: App,
+ permissions: [
+ // Uncomment to set the permissions of the plugin here
+ // {
+ // action: '', // the action name should be plugins::plugin-name.actionType
+ // subject: null,
+ // },
+ ],
+ });
+ app.registerPlugin({
+ description: pluginDescription,
+ icon,
+ id: pluginId,
+ initializer: Initializer,
+ isReady: false,
+ isRequired: pluginPkg.strapi.required || false,
+ name,
+ });
+ },
+ // eslint-disable-next-line
+ bootstrap(app) {},
+ async registerTrads({ locales }) {
+ const importedTrads = await Promise.all(
+ locales.map(locale => {
+ return import(`./translations/${locale}.json`)
+ .then(({ default: data }) => {
+ return {
+ data: prefixPluginTranslations(data, pluginId),
+ locale,
+ };
+ })
+ .catch(() => {
+ return {
+ data: {},
+ locale,
+ };
+ });
+ })
+ );
+
+ return Promise.resolve(importedTrads);
+ },
+};
diff --git a/packages/generators/generate-plop/files/admin/src/pluginId.js b/packages/generators/generate-plop/files/admin/src/pluginId.js
new file mode 100644
index 0000000000..f604a009da
--- /dev/null
+++ b/packages/generators/generate-plop/files/admin/src/pluginId.js
@@ -0,0 +1,5 @@
+const pluginPkg = require('../../package.json');
+
+const pluginId = pluginPkg.name.replace(/^@strapi\/plugin-/i, '');
+
+module.exports = pluginId;
diff --git a/packages/generators/generate-plop/files/admin/src/translations/en.json b/packages/generators/generate-plop/files/admin/src/translations/en.json
new file mode 100644
index 0000000000..9e26dfeeb6
--- /dev/null
+++ b/packages/generators/generate-plop/files/admin/src/translations/en.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/packages/generators/generate-plop/files/admin/src/translations/fr.json b/packages/generators/generate-plop/files/admin/src/translations/fr.json
new file mode 100644
index 0000000000..9e26dfeeb6
--- /dev/null
+++ b/packages/generators/generate-plop/files/admin/src/translations/fr.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/packages/generators/generate-plop/files/admin/src/utils/getTrad.js b/packages/generators/generate-plop/files/admin/src/utils/getTrad.js
new file mode 100644
index 0000000000..a2b8632a8d
--- /dev/null
+++ b/packages/generators/generate-plop/files/admin/src/utils/getTrad.js
@@ -0,0 +1,5 @@
+import pluginId from '../pluginId';
+
+const getTrad = id => `${pluginId}.${id}`;
+
+export default getTrad;
diff --git a/packages/generators/generate-plop/package.json b/packages/generators/generate-plop/package.json
index 900c86e010..d241f5842d 100644
--- a/packages/generators/generate-plop/package.json
+++ b/packages/generators/generate-plop/package.json
@@ -5,6 +5,7 @@
"main": "index.js",
"license": "MIT",
"dependencies": {
+ "fs-extra": "10.0.0",
"plop": "2.7.4"
}
}
diff --git a/packages/generators/generate-plop/plopfile.js b/packages/generators/generate-plop/plopfile.js
index d3d469b8ff..2640a23c7f 100644
--- a/packages/generators/generate-plop/plopfile.js
+++ b/packages/generators/generate-plop/plopfile.js
@@ -1,8 +1,12 @@
'use strict';
const { join } = require('path');
+const fs = require('fs-extra');
module.exports = function(plop) {
+ const rootDir = process.cwd();
+ plop.setWelcomeMessage('Strapi Generators');
+
// Service generator
plop.setGenerator('service', {
description: 'Generate a service for an API',
@@ -16,7 +20,7 @@ module.exports = function(plop) {
actions: [
{
type: 'add',
- path: join(process.cwd(), 'api/{{id}}/services/{{id}}.js'),
+ path: join(rootDir, 'api/{{id}}/services/{{id}}.js'),
templateFile: 'templates/service.js.hbs',
},
],
@@ -24,7 +28,7 @@ module.exports = function(plop) {
// Model generator
plop.setGenerator('model', {
- description: 'application model logic',
+ description: 'Generate a model for an API',
prompts: [
{
type: 'input',
@@ -40,12 +44,12 @@ module.exports = function(plop) {
actions: [
{
type: 'add',
- path: join(process.cwd(), 'api/{{id}}/models/{{id}}.js'),
+ path: join(rootDir, 'api/{{id}}/models/{{id}}.js'),
templateFile: 'templates/model.js.hbs',
},
{
type: 'add',
- path: join(process.cwd(), 'api/{{id}}/models/{{id}}.settings.json'),
+ path: join(rootDir, 'api/{{id}}/models/{{id}}.settings.json'),
templateFile: 'templates/model.settings.json.hbs',
},
],
@@ -64,7 +68,7 @@ module.exports = function(plop) {
actions: [
{
type: 'add',
- path: join(process.cwd(), 'api/{{id}}/controllers/{{id}}.js'),
+ path: join(rootDir, 'api/{{id}}/controllers/{{id}}.js'),
templateFile: 'templates/controller.js.hbs',
},
],
@@ -72,7 +76,7 @@ module.exports = function(plop) {
// Policy generator
plop.setGenerator('policy', {
- description: 'Generate a policy',
+ description: 'Generate a policy for an API',
prompts: [
{
type: 'input',
@@ -83,9 +87,60 @@ module.exports = function(plop) {
actions: [
{
type: 'add',
- path: join(process.cwd(), 'config/policies/{{id}}.js'),
+ path: join(rootDir, 'config/policies/{{id}}.js'),
templateFile: 'templates/policy.js.hbs',
},
],
});
+
+ // Plugin generator
+ plop.setGenerator('plugin', {
+ description: 'Generate a basic plugin',
+ prompts: [
+ {
+ type: 'input',
+ name: 'id',
+ message: 'Plugin name',
+ },
+ ],
+ actions: data => {
+ fs.copySync(join(__dirname, 'files', 'admin'), join(rootDir, 'plugins', data.id, 'admin'));
+
+ return [
+ {
+ type: 'add',
+ path: join(rootDir, 'plugins/{{id}}/services/{{id}}.js'),
+ templateFile: 'templates/service.js.hbs',
+ },
+ {
+ type: 'add',
+ path: join(rootDir, 'plugins/{{id}}/controllers/{{id}}.js'),
+ templateFile: 'templates/controller.js.hbs',
+ },
+ {
+ type: 'add',
+ path: join(rootDir, 'plugins/{{id}}/config/routes.json'),
+ templateFile: 'templates/routes.json.hbs',
+ },
+ {
+ type: 'add',
+ path: join(rootDir, 'plugins/{{id}}/README.md'),
+ templateFile: 'templates/README.md.hbs',
+ },
+ {
+ type: 'add',
+ path: join(rootDir, 'plugins/{{id}}/package.json'),
+ templateFile: 'templates/plugin-package.json.hbs',
+ },
+ {
+ destination: join(rootDir, 'plugins/{{id}}'),
+ type: 'addMany',
+ templateFiles: 'templates/.*',
+ globOptions: {
+ dot: true,
+ },
+ },
+ ];
+ },
+ });
};
diff --git a/packages/generators/generate-plop/templates/.editorconfig b/packages/generators/generate-plop/templates/.editorconfig
new file mode 100644
index 0000000000..d4eed8406b
--- /dev/null
+++ b/packages/generators/generate-plop/templates/.editorconfig
@@ -0,0 +1,7 @@
+root = true
+
+[*]
+end_of_line = lf
+insert_final_newline = false
+indent_style = space
+indent_size = 2
diff --git a/packages/generators/generate-plop/templates/.gitattributes b/packages/generators/generate-plop/templates/.gitattributes
new file mode 100644
index 0000000000..065a11c71d
--- /dev/null
+++ b/packages/generators/generate-plop/templates/.gitattributes
@@ -0,0 +1,103 @@
+# From https://github.com/Danimoth/gitattributes/blob/master/Web.gitattributes
+
+# Handle line endings automatically for files detected as text
+# and leave all files detected as binary untouched.
+* text=auto
+
+#
+# The above will handle all files NOT found below
+#
+
+#
+## These files are text and should be normalized (Convert crlf => lf)
+#
+
+# source code
+*.php text
+*.css text
+*.sass text
+*.scss text
+*.less text
+*.styl text
+*.js text eol=lf
+*.coffee text
+*.json text
+*.htm text
+*.html text
+*.xml text
+*.svg text
+*.txt text
+*.ini text
+*.inc text
+*.pl text
+*.rb text
+*.py text
+*.scm text
+*.sql text
+*.sh text
+*.bat text
+
+# templates
+*.ejs text
+*.hbt text
+*.jade text
+*.haml text
+*.hbs text
+*.dot text
+*.tmpl text
+*.phtml text
+
+# git config
+.gitattributes text
+.gitignore text
+.gitconfig text
+
+# code analysis config
+.jshintrc text
+.jscsrc text
+.jshintignore text
+.csslintrc text
+
+# misc config
+*.yaml text
+*.yml text
+.editorconfig text
+
+# build config
+*.npmignore text
+*.bowerrc text
+
+# Heroku
+Procfile text
+.slugignore text
+
+# Documentation
+*.md text
+LICENSE text
+AUTHORS text
+
+
+#
+## These files are binary and should be left untouched
+#
+
+# (binary is a macro for -text -diff)
+*.png binary
+*.jpg binary
+*.jpeg binary
+*.gif binary
+*.ico binary
+*.mov binary
+*.mp4 binary
+*.mp3 binary
+*.flv binary
+*.fla binary
+*.swf binary
+*.gz binary
+*.zip binary
+*.7z binary
+*.ttf binary
+*.eot binary
+*.woff binary
+*.pyc binary
+*.pdf binary
diff --git a/packages/generators/generate-plop/templates/.gitignore b/packages/generators/generate-plop/templates/.gitignore
new file mode 100644
index 0000000000..afe256bf30
--- /dev/null
+++ b/packages/generators/generate-plop/templates/.gitignore
@@ -0,0 +1,10 @@
+# Don't check auto-generated stuff into git
+coverage
+node_modules
+stats.json
+package-lock.json
+
+# Cruft
+.DS_Store
+npm-debug.log
+.idea
diff --git a/packages/generators/generate-plop/templates/README.md.hbs b/packages/generators/generate-plop/templates/README.md.hbs
new file mode 100644
index 0000000000..c0073e2006
--- /dev/null
+++ b/packages/generators/generate-plop/templates/README.md.hbs
@@ -0,0 +1,3 @@
+# Strapi plugin {{id}}
+
+A quick description of {{id}}.
diff --git a/packages/generators/generate-plop/templates/plugin-package.json.hbs b/packages/generators/generate-plop/templates/plugin-package.json.hbs
new file mode 100644
index 0000000000..75bec5a029
--- /dev/null
+++ b/packages/generators/generate-plop/templates/plugin-package.json.hbs
@@ -0,0 +1,28 @@
+{
+ "name": "strapi-plugin-{{id}}",
+ "version": "0.0.0",
+ "description": "This is the description of the plugin.",
+ "strapi": {
+ "name": "{{id}}",
+ "icon": "plug",
+ "description": "Description of {{id}} plugin."
+ },
+ "dependencies": {},
+ "author": {
+ "name": "A Strapi developer",
+ "email": "",
+ "url": ""
+ },
+ "maintainers": [
+ {
+ "name": "A Strapi developer",
+ "email": "",
+ "url": ""
+ }
+ ],
+ "engines": {
+ "node": ">=12.x. <=14.x.x",
+ "npm": ">=6.0.0"
+ },
+ "license": "MIT"
+}
\ No newline at end of file
diff --git a/packages/generators/generate-plop/templates/routes.json.hbs b/packages/generators/generate-plop/templates/routes.json.hbs
new file mode 100644
index 0000000000..1de66cd215
--- /dev/null
+++ b/packages/generators/generate-plop/templates/routes.json.hbs
@@ -0,0 +1,12 @@
+{
+ "routes": [
+ {
+ "method": "GET",
+ "path": "/",
+ "handler": "{{id}}.index",
+ "config": {
+ "policies": []
+ }
+ }
+ ]
+}
\ No newline at end of file