Refactor strapi load

This commit is contained in:
Alexandre Bodin
2019-04-05 16:11:09 +02:00
parent 35160e8066
commit 9e9ff9907d
91 changed files with 23489 additions and 1074 deletions
+16
View File
@@ -0,0 +1,16 @@
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[{package.json,*.yml}]
indent_style = space
indent_size = 2
[*.md]
trim_trailing_whitespace = false
+1
View File
@@ -0,0 +1 @@
**/node_modules/**
+27
View File
@@ -0,0 +1,27 @@
{
"parser": "babel-eslint",
"extends": "eslint:recommended",
"env": {
"commonjs": true,
"es6": true,
"node": true,
"browser": false
},
"parserOptions": {
"ecmaFeatures": {
"experimentalObjectRestSpread": true,
"jsx": false
},
"sourceType": "module"
},
"globals": {
"strapi": true
},
"rules": {
"indent": ["error", 2, { "SwitchCase": 1 }],
"linebreak-style": ["error", "unix"],
"no-console": 0,
"quotes": ["error", "single"],
"semi": ["error", "always"]
}
}
+104
View File
@@ -0,0 +1,104 @@
############################
# OS X
############################
.DS_Store
.AppleDouble
.LSOverride
Icon
.Spotlight-V100
.Trashes
._*
############################
# Linux
############################
*~
############################
# Windows
############################
Thumbs.db
ehthumbs.db
Desktop.ini
$RECYCLE.BIN/
*.cab
*.msi
*.msm
*.msp
############################
# Packages
############################
*.7z
*.csv
*.dat
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip
*.com
*.class
*.dll
*.exe
*.o
*.seed
*.so
*.swo
*.swp
*.swn
*.swm
*.out
*.pid
############################
# Logs and databases
############################
.tmp
*.log
*.sql
*.sqlite
*.sqlite3
############################
# Misc.
############################
*#
ssl
.idea
nbproject
public/uploads/*
!public/uploads/.gitkeep
############################
# Node.js
############################
lib-cov
lcov.info
pids
logs
results
node_modules
.node_history
############################
# Tests
############################
testApp
coverage
+1
View File
@@ -0,0 +1 @@
package-lock=false
+3
View File
@@ -0,0 +1,3 @@
# getstarted
A quick description of getstarted.
@@ -0,0 +1,5 @@
module.exports = {
test() {
console.log('test');
},
};
@@ -0,0 +1,10 @@
{
"favicon": {
"path": "favicon.ico",
"maxAge": 86400000
},
"public": {
"path": "./public",
"maxAge": 60000
}
}
+3
View File
@@ -0,0 +1,3 @@
{
"myCustomConfiguration": "This configuration is accessible through strapi.config.myCustomConfiguration"
}
@@ -0,0 +1,3 @@
{
"myCustomConfiguration": "This configuration is accessible through strapi.config.environments.development.myCustomConfiguration"
}
@@ -0,0 +1,15 @@
{
"defaultConnection": "default",
"connections": {
"default": {
"connector": "strapi-hook-bookshelf",
"settings": {
"client": "sqlite",
"filename": ".tmp/data.db"
},
"options": {
"useNullAsDefault": true
}
}
}
}
@@ -0,0 +1,23 @@
{
"session": {
"enabled": true,
"client": "cookie",
"key": "strapi.sid",
"prefix": "strapi:sess:",
"secretKeys": ["mySecretKey1", "mySecretKey2"],
"httpOnly": true,
"maxAge": 86400000,
"overwrite": true,
"signed": false,
"rolling": false
},
"logger": {
"level": "debug",
"exposeInContext": true,
"requests": true
},
"parser": {
"enabled": true,
"multipart": true
}
}
@@ -0,0 +1,12 @@
{
"gzip": {
"enabled": false
},
"responseTime": {
"enabled": false
},
"poweredBy": {
"enabled": true,
"value": "Strapi <strapi.io>"
}
}
@@ -0,0 +1,60 @@
{
"csrf": {
"enabled": false,
"key": "_csrf",
"secret": "_csrfSecret"
},
"csp": {
"enabled": false,
"policy": {
"default-src": "'self'"
}
},
"p3p": {
"enabled": false,
"value": ""
},
"hsts": {
"enabled": false,
"maxAge": 31536000,
"includeSubDomains": true
},
"xframe": {
"enabled": false,
"value": "SAMEORIGIN"
},
"xss": {
"enabled": false,
"mode": "block"
},
"cors": {
"enabled": true,
"origin": "*",
"expose": [
"WWW-Authenticate",
"Server-Authorization"
],
"maxAge": 31536000,
"credentials": true,
"methods": [
"GET",
"POST",
"PUT",
"PATCH",
"DELETE",
"OPTIONS",
"HEAD"
],
"headers": [
"Content-Type",
"Authorization",
"X-Frame-Options",
"Origin"
]
},
"ip": {
"enabled": false,
"whiteList": [],
"blackList": []
}
}
@@ -0,0 +1,16 @@
{
"host": "localhost",
"port": 1337,
"proxy": {
"enabled": false
},
"autoReload": {
"enabled": true
},
"cron": {
"enabled": false
},
"admin": {
"autoOpen": false
}
}
@@ -0,0 +1,3 @@
{
"myCustomConfiguration": "This configuration is accessible through strapi.config.environments.production.myCustomConfiguration"
}
@@ -0,0 +1,17 @@
{
"defaultConnection": "default",
"connections": {
"default": {
"connector": "strapi-hook-bookshelf",
"settings": {
"client": "sqlite",
"host": "${process.env.DATABASE_HOST || '127.0.0.1'}",
"port": "${process.env.DATABASE_PORT || 27017}",
"database": "${process.env.DATABASE_NAME || 'strapi'}",
"username": "${process.env.DATABASE_USERNAME || ''}",
"password": "${process.env.DATABASE_PASSWORD || ''}"
},
"options": {}
}
}
}
@@ -0,0 +1,23 @@
{
"session": {
"enabled": true,
"client": "cookie",
"key": "strapi.sid",
"prefix": "strapi:sess:",
"secretKeys": ["mySecretKey1", "mySecretKey2"],
"httpOnly": true,
"maxAge": 86400000,
"overwrite": true,
"signed": false,
"rolling": false
},
"logger": {
"level": "info",
"exposeInContext": true,
"requests": false
},
"parser": {
"enabled": true,
"multipart": true
}
}
@@ -0,0 +1,12 @@
{
"gzip": {
"enabled": true
},
"responseTime": {
"enabled": false
},
"poweredBy": {
"enabled": true,
"value": "Strapi <strapi.io>"
}
}
@@ -0,0 +1,62 @@
{
"csrf": {
"enabled": false,
"key": "_csrf",
"secret": "_csrfSecret"
},
"csp": {
"enabled": true,
"policy": [{
"img-src": "'self' http:"
},
"block-all-mixed-content"
]
},
"p3p": {
"enabled": true,
"value": ""
},
"hsts": {
"enabled": true,
"maxAge": 31536000,
"includeSubDomains": true
},
"xframe": {
"enabled": true,
"value": "SAMEORIGIN"
},
"xss": {
"enabled": true,
"mode": "block"
},
"cors": {
"enabled": true,
"origin": "*",
"expose": [
"WWW-Authenticate",
"Server-Authorization"
],
"maxAge": 31536000,
"credentials": true,
"methods": [
"GET",
"POST",
"PUT",
"PATCH",
"DELETE",
"OPTIONS",
"HEAD"
],
"headers": [
"Content-Type",
"Authorization",
"X-Frame-Options",
"Origin"
]
},
"ip": {
"enabled": false,
"whiteList": [],
"blackList": []
}
}
@@ -0,0 +1,17 @@
{
"host": "localhost",
"port": "${process.env.PORT || 1337}",
"production": true,
"proxy": {
"enabled": false
},
"autoReload": {
"enabled": false
},
"cron": {
"enabled": false
},
"admin": {
"autoOpen": false
}
}
@@ -0,0 +1,3 @@
{
"myCustomConfiguration": "This configuration is accessible through strapi.config.environments.staging.myCustomConfiguration"
}
@@ -0,0 +1,17 @@
{
"defaultConnection": "default",
"connections": {
"default": {
"connector": "strapi-hook-bookshelf",
"settings": {
"client": "sqlite",
"host": "${process.env.DATABASE_HOST || '127.0.0.1'}",
"port": "${process.env.DATABASE_PORT || 27017}",
"database": "${process.env.DATABASE_NAME || 'strapi'}",
"username": "${process.env.DATABASE_USERNAME || ''}",
"password": "${process.env.DATABASE_PASSWORD || ''}"
},
"options": {}
}
}
}
@@ -0,0 +1,23 @@
{
"session": {
"enabled": true,
"client": "cookie",
"key": "strapi.sid",
"prefix": "strapi:sess:",
"secretKeys": ["mySecretKey1", "mySecretKey2"],
"httpOnly": true,
"maxAge": 86400000,
"overwrite": true,
"signed": false,
"rolling": false
},
"logger": {
"level": "info",
"exposeInContext": true,
"requests": false
},
"parser": {
"enabled": true,
"multipart": true
}
}
@@ -0,0 +1,12 @@
{
"gzip": {
"enabled": true
},
"responseTime": {
"enabled": false
},
"poweredBy": {
"enabled": true,
"value": "Strapi <strapi.io>"
}
}
@@ -0,0 +1,62 @@
{
"csrf": {
"enabled": false,
"key": "_csrf",
"secret": "_csrfSecret"
},
"csp": {
"enabled": true,
"policy": [{
"img-src": "'self' http:"
},
"block-all-mixed-content"
]
},
"p3p": {
"enabled": true,
"value": ""
},
"hsts": {
"enabled": true,
"maxAge": 31536000,
"includeSubDomains": true
},
"xframe": {
"enabled": true,
"value": "SAMEORIGIN"
},
"xss": {
"enabled": true,
"mode": "block"
},
"cors": {
"enabled": true,
"origin": "*",
"expose": [
"WWW-Authenticate",
"Server-Authorization"
],
"maxAge": 31536000,
"credentials": true,
"methods": [
"GET",
"POST",
"PUT",
"PATCH",
"DELETE",
"OPTIONS",
"HEAD"
],
"headers": [
"Content-Type",
"Authorization",
"X-Frame-Options",
"Origin"
]
},
"ip": {
"enabled": false,
"whiteList": [],
"blackList": []
}
}
@@ -0,0 +1,17 @@
{
"host": "localhost",
"port": "${process.env.PORT || 1337}",
"production": true,
"proxy": {
"enabled": false
},
"autoReload": {
"enabled": false
},
"cron": {
"enabled": false
},
"admin": {
"autoOpen": false
}
}
+13
View File
@@ -0,0 +1,13 @@
'use strict';
/**
* An asynchronous bootstrap function that runs before
* your application gets started.
*
* This gives you an opportunity to set up your data model,
* run jobs, or perform some special logic.
*/
module.exports = cb => {
cb();
};
@@ -0,0 +1,21 @@
'use strict';
/**
* Cron config that gives you an opportunity
* to run scheduled jobs.
*
* The cron format consists of:
* [MINUTE] [HOUR] [DAY OF MONTH] [MONTH OF YEAR] [DAY OF WEEK] [YEAR (optional)]
*/
module.exports = {
/**
* Simple example.
* Every monday at 1am.
*/
// '0 1 * * 1': () => {
//
// }
};
@@ -0,0 +1,5 @@
'use strict';
module.exports = async ctx => {
// return ctx.notFound('My custom message 404');
};
+10
View File
@@ -0,0 +1,10 @@
{
"timeout": 3000,
"load": {
"before": [],
"order": [
"Define the hooks' load order by putting their names in this array in the right order"
],
"after": []
}
}
+13
View File
@@ -0,0 +1,13 @@
{
"enabled": true,
"defaultLocale": "en_us",
"modes": [
"query",
"subdomain",
"cookie",
"header",
"url",
"tld"
],
"cookieName": "locale"
}
@@ -0,0 +1,3 @@
{
"welcome": "Willkommen"
}
@@ -0,0 +1,3 @@
{
"welcome": "Welcome"
}
@@ -0,0 +1,3 @@
{
"welcome": "Bienvenido"
}
@@ -0,0 +1,3 @@
{
"welcome": "Bienvenue"
}
@@ -0,0 +1,3 @@
{
"welcome": "Benvenuto"
}
@@ -0,0 +1,3 @@
{
"welcome": "ようこそ"
}
@@ -0,0 +1,4 @@
{
"welcome": "Добро пожаловать"
}
@@ -0,0 +1,3 @@
{
"welcome": "Hoşgeldin"
}
@@ -0,0 +1,19 @@
{
"timeout": 100,
"load": {
"before": [
"responseTime",
"logger",
"cors",
"responses",
"gzip"
],
"order": [
"Define the middlewares' load order by putting their name in this array is the right order"
],
"after": [
"parser",
"router"
]
}
}
@@ -0,0 +1 @@
{"actions":["application.articles.test","content-manager.contentmanager.models","content-manager.contentmanager.find","content-manager.contentmanager.count","content-manager.contentmanager.findone","content-manager.contentmanager.create","content-manager.contentmanager.update","content-manager.contentmanager.updatesettings","content-manager.contentmanager.delete","content-manager.contentmanager.deleteall","content-type-builder.contenttypebuilder.getmodels","content-type-builder.contenttypebuilder.getmodel","content-type-builder.contenttypebuilder.getconnections","content-type-builder.contenttypebuilder.createmodel","content-type-builder.contenttypebuilder.updatemodel","content-type-builder.contenttypebuilder.deletemodel","content-type-builder.contenttypebuilder.autoreload","content-type-builder.contenttypebuilder.checktableexists","email.email.send","email.email.getenvironments","email.email.getsettings","email.email.updatesettings","settings-manager.settingsmanager.menu","settings-manager.settingsmanager.environments","settings-manager.settingsmanager.languages","settings-manager.settingsmanager.databases","settings-manager.settingsmanager.database","settings-manager.settingsmanager.databasemodel","settings-manager.settingsmanager.get","settings-manager.settingsmanager.update","settings-manager.settingsmanager.createlanguage","settings-manager.settingsmanager.deletelanguage","settings-manager.settingsmanager.createdatabase","settings-manager.settingsmanager.updatedatabase","settings-manager.settingsmanager.deletedatabase","settings-manager.settingsmanager.autoreload","upload.upload.upload","upload.upload.getenvironments","upload.upload.getsettings","upload.upload.updatesettings","upload.upload.find","upload.upload.findone","upload.upload.count","upload.upload.destroy","upload.upload.search","users-permissions.auth.callback","users-permissions.auth.changepassword","users-permissions.auth.connect","users-permissions.auth.forgotpassword","users-permissions.auth.register","users-permissions.auth.emailconfirmation","users-permissions.user.find","users-permissions.user.me","users-permissions.user.findone","users-permissions.user.create","users-permissions.user.update","users-permissions.user.destroy","users-permissions.user.destroyall","users-permissions.userspermissions.createrole","users-permissions.userspermissions.deleteprovider","users-permissions.userspermissions.deleterole","users-permissions.userspermissions.getpermissions","users-permissions.userspermissions.getpolicies","users-permissions.userspermissions.getrole","users-permissions.userspermissions.getroles","users-permissions.userspermissions.getroutes","users-permissions.userspermissions.index","users-permissions.userspermissions.init","users-permissions.userspermissions.searchusers","users-permissions.userspermissions.updaterole","users-permissions.userspermissions.getemailtemplate","users-permissions.userspermissions.updateemailtemplate","users-permissions.userspermissions.getadvancedsettings","users-permissions.userspermissions.updateadvancedsettings","users-permissions.userspermissions.getproviders","users-permissions.userspermissions.updateproviders"]}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -0,0 +1,5 @@
{
"test-hook": {
"enabled": true
}
}
@@ -0,0 +1,7 @@
module.exports = () => {
return {
initialize(cb) {
cb();
},
};
};
@@ -0,0 +1,5 @@
{
"testM": {
"enabled": true
}
}
@@ -0,0 +1,7 @@
module.exports = () => {
return {
initialize(cb) {
cb();
},
};
};
+60
View File
@@ -0,0 +1,60 @@
{
"name": "getstarted",
"private": true,
"version": "0.1.0",
"description": "A Strapi application.",
"main": "./server.js",
"scripts": {
"setup": "cd admin && npm run setup",
"start": "node server.js",
"strapi": "node_modules/strapi/bin/strapi.js",
"lint": "node_modules/.bin/eslint api/**/*.js config/**/*.js plugins/**/*.js"
},
"devDependencies": {
"babel-eslint": "^7.1.1",
"eslint": "^4.19.1",
"eslint-config-airbnb": "^13.0.0",
"eslint-plugin-import": "^2.11.0",
"eslint-plugin-react": "^7.7.0"
},
"dependencies": {
"knex": "latest",
"lodash": "^4.17.5",
"sqlite3": "^4.0.6",
"strapi": "3.0.0-alpha.25.2",
"strapi-admin": "3.0.0-alpha.25.2",
"strapi-hook-bookshelf": "3.0.0-alpha.25.2",
"strapi-hook-knex": "3.0.0-alpha.25.2",
"strapi-middleware-views": "3.0.0-alpha.25.2",
"strapi-plugin-content-manager": "3.0.0-alpha.25.2",
"strapi-plugin-content-type-builder": "3.0.0-alpha.25.2",
"strapi-plugin-email": "3.0.0-alpha.25.2",
"strapi-plugin-settings-manager": "3.0.0-alpha.25.2",
"strapi-plugin-upload": "3.0.0-alpha.25.2",
"strapi-plugin-users-permissions": "3.0.0-alpha.25.2",
"strapi-provider-email-mailgun": "^3.0.0-alpha.15",
"strapi-provider-upload-aws-s3": "^3.0.0-alpha.15",
"strapi-utils": "3.0.0-alpha.25.2"
},
"author": {
"name": "alex",
"email": "",
"url": ""
},
"maintainers": [
{
"name": "alex",
"email": "",
"url": ""
}
],
"strapi": {
"packageManager": "npm",
"uuid": "8917e89f-c8ff-4f80-b963-e3d568088422"
},
"engines": {
"node": ">= 10.0.0",
"npm": ">= 6.0.0"
},
"license": "MIT"
}
@@ -0,0 +1,3 @@
{
"testConf": 1
}
@@ -0,0 +1,5 @@
{
"some-hook": {
"enabled": true
}
}
@@ -0,0 +1,7 @@
module.exports = () => {
return {
initialize(cb) {
cb();
},
};
};
@@ -0,0 +1,5 @@
{
"mazdaz": {
"enabled": true
}
}
@@ -0,0 +1,7 @@
module.exports = () => {
return {
initialize(cb) {
cb();
},
};
};
@@ -0,0 +1,14 @@
{
"connection": "default",
"info": {
"name": "test",
"description": ""
},
"attributes": {
"type": {
"type": "string",
"required": true,
"configurable": false
}
}
}
+165
View File
@@ -0,0 +1,165 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title>Welcome to your Strapi app</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
* {
-webkit-box-sizing: border-box;
}
body, html {
margin: 0;
padding: 40px 0;
}
body {
font: 17px/1.5 "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, Verdana, sans-serif;
background: white;
margin: 0;
color: #33333d;
overflow-y: scroll;
overflow-x: hidden;
}
h1 {
font-size: 1.6em;
margin-top: 0;
}
h2 {
margin-top: 44px;
font-size: 1.3em;
}
h3 {
margin-top: 30px;
font-size: 1em;
}
section {
margin: 0 5.555555555555555%;
}
p {
font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, Verdana, sans-serif;
}
a {
color: #33a0c0;
}
code {
font-family: monospace;
font-size: 1.1em;
}
pre {
background: white;
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
padding: 25px;
font-family: monospace;
overflow-x: auto;
}
.wrapper {
padding: 0 .75em;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
@media screen and (min-width:40em) {
body {
font-size: 1.0625em;
}
}
@media screen and (min-width:45em) {
body {
font-size: 1em;
}
}
@media screen and (min-width:55.5em) {
body {
font-size: 1.0625em;
}
}
@media screen and (min-width:61.5em) {
body {
font-size: 1em;
}
section {
margin: 0 16.666666666666664%;
}
}
@media screen and (min-width:75em) {
body {
font-size: 1.0625em;
}
}
@media screen and (min-width:87em) {
body {
font-size: 1em;
}
section {
margin: 0 27.77777777777778%;
}
}
@media screen and (min-width:105em) {
body {
font-size: 1.0625em;
}
}
@media screen and (min-width:117em) {
section {
margin: 0 5.555555555555555%;
}
section .wrapper {
width: 37.5%;
margin-left: 25%;
}
}
@media screen and (min-width:130em) {
body {
font-size: 1.125em;
max-width: 160em;
}
}
</style>
</head>
<body lang="en">
<section>
<div class="wrapper">
<h1>Welcome.</h1>
<p>You successfully created your Strapi application.</p>
<p>You are looking at: <code>./public/index.html</code>.</p>
<p>Your built-in admin panel is available at <a href="/admin" target="blank">/admin</a>.
<h2>Create your first API</h2>
<p>Easily generate a complete API with controllers, models and routes using:</p>
<pre><code class="lang-bash">$ strapi generate:api &lt;apiName&gt;</code></pre>
<h2>Resources</h2>
<p>You'll probably also want to learn how to customize your application, set up security and configure your data sources.</p>
<p>For more help getting started, check out:
<ul>
<li><a href="http://strapi.io/documentation/introduction" target="blank">Documentation</a></li>
<li><a href="https://github.com/strapi/strapi" target="blank">Repository on GitHub</a></li>
<li><a href="https://twitter.com/strapijs" target="blank">news on Twitter</a></li>
<li><a href="http://slack.strapi.io" target="blank">Real-time support on Slack</a></li>
</ul>
</p>
</div>
</section>
</body>
</html>
+3
View File
@@ -0,0 +1,3 @@
# To prevent search engines from seeing the site altogether, uncomment the next two lines:
# User-Agent: *
# Disallow: /
+16
View File
@@ -0,0 +1,16 @@
#!/usr/bin/env node
'use strict';
/**
* Use `server.js` to run your application without `$ strapi start`.
* To start the server, run: `$ npm start`.
*
* This is handy in situations where the Strapi CLI is not relevant or useful.
*/
process.chdir(__dirname);
(() => {
const strapi = require('strapi');
strapi.start();
})();
File diff suppressed because it is too large Load Diff
+4 -6
View File
@@ -1,8 +1,6 @@
{
"lerna": "2.0.0",
"version": "3.0.0-alpha.5.3",
"packages": [
"packages/*"
],
"commands": {}
"version": "0.0.0",
"packages": ["packages/*", "examples/*"],
"npmClient": "yarn",
"useWorkspaces": true
}
+8 -3
View File
@@ -1,7 +1,6 @@
{
"private": true,
"version": "3.0.0-alpha.25.2",
"dependencies": {},
"devDependencies": {
"assert": "~1.3.0",
"axios": "^0.18.0",
@@ -32,7 +31,7 @@
"istanbul": "~0.4.2",
"jest": "^24.5.0",
"jest-cli": "^24.5.0",
"lerna": "^2.0.0",
"lerna": "^3.13.1",
"lodash": "^4.17.5",
"pre-commit": "~1.1.2",
"prettier": "^1.16.4",
@@ -46,6 +45,7 @@
"wait-on": "^3.2.0"
},
"scripts": {
"bootstrap": "yarn install && lerna bootstrap",
"clean": "npm run removesymlinkdependencies && npx rimraf package-lock.json && npx rimraf packages/*/package-lock.json",
"clean:all": "npm run removesymlinkdependencies && npx rimraf package-lock.json && npx rimraf packages/*/package-lock.json && npx rimraf packages/*/node_modules",
"doc": "node ./scripts/documentation.js",
@@ -95,5 +95,10 @@
"node": ">= 10.0.0",
"npm": ">= 6.0.0"
},
"license": "MIT"
"license": "MIT",
"name": "strapi",
"workspaces": [
"packages/*",
"examples/*"
]
}
@@ -42,9 +42,8 @@ module.exports = scope => {
'scripts': {
'setup': 'cd admin && npm run setup', // Ready to deploy setup
'start': 'node server.js',
'strapi': 'node_modules/strapi/bin/strapi.js', // Allow to use `npm run strapi` CLI,
'lint': 'node_modules/.bin/eslint api/**/*.js config/**/*.js plugins/**/*.js',
'postinstall': 'node node_modules/strapi/lib/utils/post-install.js'
'strapi': 'strapi', // Allow to use `npm run strapi` CLI,
'lint': 'eslint api/**/*.js config/**/*.js plugins/**/*.js'
},
'devDependencies': {
'babel-eslint': '^7.1.1',
@@ -56,6 +55,7 @@ module.exports = scope => {
'dependencies': Object.assign({}, {
'lodash': '^4.17.5',
'strapi': getDependencyVersion(cliPkg, 'strapi'),
'strapi-admin': getDependencyVersion(cliPkg, 'strapi'),
'strapi-utils': getDependencyVersion(cliPkg, 'strapi'),
[scope.client.connector]: getDependencyVersion(cliPkg, 'strapi'),
}, additionalsDependencies, {
+62 -162
View File
@@ -9,7 +9,7 @@ const path = require('path');
// Public node modules.
const _ = require('lodash');
const {green, cyan} = require('chalk');
const { green, cyan } = require('chalk');
const fs = require('fs-extra');
const npm = require('enpeem');
const ora = require('ora');
@@ -19,184 +19,84 @@ const shell = require('shelljs');
const { packageManager } = require('strapi-utils');
const trackSuccess = require('./success');
/**
* Runs after this generator has finished
*
* @param {Object} scope
* @param {Function} cb
*/
const runInstall = () => {
if (packageManager.isStrapiInstalledWithNPM()) {
return new Promise((resolve, reject) => {
shell.exec(
'npm install --production',
{ silent: true },
(code, _, stderr) => {
if (stderr && code !== 0) return reject(new Error(stderr));
return resolve();
}
);
});
}
/* eslint-disable no-console */
/* eslint-disable prefer-template */
module.exports = (scope, cb) => {
return new Promise((resolve, reject) => {
shell.exec(
'yarn install --production',
{ silent: true },
(code, _, stderr) => {
if (stderr && code !== 0) return reject(new Error(stderr));
return resolve();
}
);
});
};
module.exports = async (scope, cb) => {
console.log('🏗 Application generation:');
let loader = ora('Copy dashboard').start();
const packageJSON = require(path.resolve(scope.rootPath, 'package.json'));
// const packageJSON = require(path.resolve(scope.rootPath, 'package.json'));
// const strapiRootPath = path.resolve(scope.strapiRoot, '..');
process.chdir(scope.rootPath);
// Copy the default files.
fs.copySync(path.resolve(__dirname, '..', 'files'), path.resolve(scope.rootPath));
fs.copySync(
path.resolve(__dirname, '..', 'files'),
path.resolve(scope.rootPath)
);
loader.succeed();
let availableDependencies = [];
const dependencies = _.get(packageJSON, 'dependencies');
const strapiDependencies = Object.keys(dependencies).filter(key => key.indexOf('strapi') !== -1);
const othersDependencies = Object.keys(dependencies).filter(key => key.indexOf('strapi') === -1);
// Add this check to know if we are in development mode so the creation is faster.
const isStrapiInstalledWithNPM = packageManager.isStrapiInstalledWithNPM();
const globalRootPath = shell.exec(packageManager.commands('root -g'), {silent: true});
loader.start('Install dependencies');
// Verify if the dependencies are available into the global
_.forEach(strapiDependencies, (key) => {
try {
const depPath = isStrapiInstalledWithNPM ? path.resolve(_.trim(globalRootPath.toString()), key) : path.resolve(_.trim(globalRootPath.toString()), `node_modules/${key}`);
fs.accessSync(depPath, fs.constants.R_OK | fs.constants.F_OK);
try {
await runInstall();
loader.succeed();
} catch (err) {
loader.fail();
trackSuccess('didNotInstallProjectDependencies', scope);
cb(err);
}
availableDependencies.push({
key,
global: true,
path: depPath
});
} catch (e) {
othersDependencies.push(key);
}
});
console.log();
console.log(
`👌 Your new application ${green(scope.name)} is ready at ${cyan(
scope.rootPath
)}.`
);
if (!_.isEmpty(othersDependencies)) {
if (isStrapiInstalledWithNPM) {
npm.install({
dir: scope.rootPath,
dependencies: othersDependencies,
loglevel: 'silent',
production: true,
'cache-min': 999999999
}, err => {
if (err) {
trackSuccess('didNotInstallProjectDependencies', scope);
console.log();
console.log('⚠️ You should run `npm install` into your application before starting it.');
console.log();
console.log('⚠️ Some dependencies could not be installed:');
_.forEach(othersDependencies, value => console.log('• ' + value));
console.log();
trackSuccess('didCreateProject', scope);
return cb();
}
pluginsInstallation();
});
} else {
const alphaDependencies = othersDependencies.map(dep => {
if (_.includes(dep, 'strapi')) { // We need this for yarn
return `${dep}@${scope.strapiPackageJSON.version}`;
}
return dep;
}).join(' ');
const data = shell.exec(`yarn --cwd ${scope.rootPath} add ${alphaDependencies} --production`, { silent: true });
if (data.stderr && data.code !== 0) {
trackSuccess('didNotInstallProjectDependencies', scope);
cb();
}
pluginsInstallation();
}
if (scope.quick) {
console.log();
console.log('⚡️ Starting your application:');
console.log(`${green('strapi start')}`);
} else {
pluginsInstallation();
console.log();
console.log('⚡️ Change directory:');
console.log(`$ ${green(`cd ${scope.name}`)}`);
console.log();
console.log('⚡️ Start application:');
console.log(`$ ${green('strapi start')}`);
}
// Install default plugins and link dependencies.
function pluginsInstallation() {
const strapiBin = path.join(scope.strapiRoot, scope.strapiPackageJSON.bin.strapi);
// Define the list of default plugins.
const defaultPlugins = [{
name: 'settings-manager',
core: true
}, {
name: 'content-type-builder',
core: true
}, {
name: 'content-manager',
core: true
}, {
name: 'users-permissions',
core: true
}, {
name: 'email',
core: true
},{
name: 'upload',
core: true
}];
let installPlugin = new Promise(resolve => {
return resolve();
});
// Install each plugin.
defaultPlugins.forEach(defaultPlugin => {
installPlugin = installPlugin.then(() => {
return new Promise(resolve => {
loader = ora(`Install plugin ${cyan(defaultPlugin.name)}.`).start();
shell.exec(`node ${strapiBin} install ${defaultPlugin.name} ${scope.developerMode && defaultPlugin.core ? '--dev' : ''}`, {silent: true}, (code, stdout, stderr) => {
if (code) {
trackSuccess('didNotInstallProjectPlugins', scope);
loader.warn(`An error occurred during ${defaultPlugin.name} plugin installation.`);
console.log(stderr);
return resolve();
}
loader.succeed();
return resolve();
});
});
});
});
installPlugin
.then(() => {
// Link dependencies.
availableDependencies.forEach(dependency => {
loader = ora(`Link ${cyan(dependency.key)} dependency to the project.`).start();
if (dependency.global) {
try {
fs.accessSync(dependency.path, fs.constants.R_OK | fs.constants.F_OK);
fs.symlinkSync(dependency.path, path.resolve(scope.rootPath, 'node_modules', dependency.key), 'junction');
} catch (e) {
// Silent.
}
} else {
try {
fs.accessSync(path.resolve(scope.strapiRoot, 'node_modules', dependency.key), fs.constants.R_OK | fs.constants.F_OK);
fs.symlinkSync(path.resolve(scope.strapiRoot, 'node_modules', dependency.key), path.resolve(scope.rootPath, 'node_modules', dependency.key), 'junction');
} catch (e) {
// Silent.
}
}
loader.succeed();
});
console.log();
console.log(`👌 Your new application ${green(scope.name)} is ready at ${cyan(scope.rootPath)}.`);
console.log();
console.log('⚡️ Change directory:');
console.log(`$ ${green(`cd ${scope.name}`)}`);
console.log();
console.log('⚡️ Start application:');
console.log(`$ ${green('strapi start')}`);
trackSuccess('didCreateProject', scope);
cb();
});
}
};
cb();
// });
// }
};
+13 -4
View File
@@ -41,7 +41,15 @@ module.exports = (scope, cb) => {
email: process.env.EMAIL || '',
year: (new Date()).getFullYear(),
license: 'MIT',
database: {}
database: {},
additionalsDependencies: [
'strapi-plugin-settings-manager',
'strapi-plugin-content-type-builder',
'strapi-plugin-content-manager',
'strapi-plugin-users-permissions',
'strapi-plugin-email',
'strapi-plugin-upload',
]
});
// Make changes to the rootPath where the Strapi project will be created.
@@ -133,7 +141,7 @@ module.exports = (scope, cb) => {
scope.quick = answers.type === 'quick' || scope.quick;
const isQuick = scope.quick;
if (isQuick) {
answers.client = databaseChoices[0].value;
}
@@ -307,7 +315,7 @@ module.exports = (scope, cb) => {
cmd += ` strapi-hook-knex@${scope.strapiPackageJSON.version}`;
linkNodeModulesCommand += ` && npm link strapi-hook-knex`;
scope.additionalsDependencies = ['strapi-hook-knex', 'knex'];
scope.additionalsDependencies = scope.additionalsDependencies.concat(['strapi-hook-knex', 'knex']);
}
if (isQuick) {
@@ -316,6 +324,7 @@ module.exports = (scope, cb) => {
return resolve();
}
shell.exec(cmd, { silent: true }, () => {
if (scope.client.module) {
const lock = require(path.join(`${scope.tmpPath}`, '/node_modules/', `${scope.client.module}/package.json`));
@@ -352,7 +361,7 @@ module.exports = (scope, cb) => {
console.log(`The app has been connected to the database ${green('successfully')}!`);
console.log();
}
if (isQuick) {
trackSuccess('didChooseQuickstart', scope);
} else {
+2 -2
View File
@@ -23,7 +23,7 @@ module.exports = {
targets: {
// Call the `admin` generator.
'.': ['admin'],
// '.': ['admin'],
// Main package.
'package.json': {
@@ -61,7 +61,7 @@ module.exports = {
},
// Empty plugins directory.
'plugins': {
'extensions': {
folder: {}
},
+2 -2
View File
@@ -77,7 +77,7 @@ module.exports = strapi => {
// `node_modules` directory.
let client;
try {
client = require(path.resolve(strapi.config.appPath, 'node_modules', connection.settings.client));
client = require(connection.settings.client);
} catch (err) {
strapi.log.error('The client `' + connection.settings.client + '` is not installed.');
strapi.log.error('You can install it with `$ npm install ' + connection.settings.client + ' --save`.');
@@ -175,7 +175,7 @@ module.exports = strapi => {
// applications to have `knex` as a dependency.
try {
// Try to require from local dependency.
const connection = require(path.resolve(strapi.config.appPath, 'node_modules', 'knex'))(options);
const connection = require('knex')(options);
_.set(strapi, `connections.${name}`, connection);
} catch (err) {
+25 -57
View File
@@ -7,9 +7,6 @@
* This gives you an opportunity to set up your data model,
* run jobs, or perform some special logic.
*/
const path = require('path');
const fs = require('fs');
const _ = require('lodash');
module.exports = async cb => {
@@ -17,67 +14,38 @@ module.exports = async cb => {
const pluginStore = strapi.store({
environment: strapi.config.environment,
type: 'plugin',
name: 'email'
name: 'email',
});
strapi.plugins.email.config.providers = [];
const loadProviders = (basePath, cb) => {
fs.readdir(path.join(basePath, 'node_modules'), async (err, node_modules) => {
// get all email providers
const emails = _.filter(node_modules, (node_module) => {
// DEPRECATED strapi-email-* will be remove in next version
return _.startsWith(node_module, 'strapi-provider-email') || _.startsWith(node_module, 'strapi-email');
const installedProviders = Object.keys(
strapi.config.info.dependencies
).filter(d => d.startsWith('strapi-provider-email-'));
for (let installedProvider of installedProviders) {
strapi.plugins.email.config.providers.push(require(installedProvider));
}
try {
// if provider config does not exist set one by default
const config = await pluginStore.get({ key: 'provider' });
if (!config) {
const provider = _.find(strapi.plugins.email.config.providers, {
provider: 'sendmail',
});
node_modules.filter((node_module) => {
return node_module.startsWith('@');
})
.forEach((orga) => {
const node_modules = fs.readdirSync(path.join(basePath, 'node_modules', orga));
node_modules.forEach((node_module) => {
// DEPRECATED strapi-email-* will be remove in next version
if (_.startsWith(node_module, 'strapi-provider-email') || _.startsWith(node_module, 'strapi-email')) {
emails.push(`${orga}/${node_module}`);
}
});
});
// mount all providers to get configs
_.forEach(emails, (node_module) => {
strapi.plugins.email.config.providers.push(
require(path.join(`${basePath}/node_modules/${node_module}`))
);
const value = _.assign({}, provider, {
// TODO: set other default settings here
});
try {
// if provider config not exist set one by default
const config = await pluginStore.get({key: 'provider'});
if (!config) {
const provider = _.find(strapi.plugins.email.config.providers, {provider: 'sendmail'});
const value = _.assign({}, provider, {
// TODO: set other default settings here
});
await pluginStore.set({key: 'provider', value});
}
} catch (err) {
strapi.log.error(`Can't load ${config.provider} email provider.`);
strapi.log.warn(`Please install strapi-provider-email-${config.provider} --save in ${path.join(strapi.config.appPath, 'plugins', 'email')} folder.`);
strapi.stop();
}
cb();
});
};
// Load providers from the plugins' node_modules.
loadProviders(path.join(strapi.config.appPath, 'plugins', 'email'), () => {
// Load providers from the root node_modules.
loadProviders(path.join(strapi.config.appPath), cb);
});
await pluginStore.set({ key: 'provider', value });
}
} catch (err) {
strapi.log.error(err);
strapi.stop();
}
cb();
};
+27 -60
View File
@@ -7,9 +7,6 @@
* This gives you an opportunity to set up your data model,
* run jobs, or perform some special logic.
*/
const path = require('path');
const fs = require('fs');
const _ = require('lodash');
module.exports = async cb => {
@@ -17,69 +14,39 @@ module.exports = async cb => {
const pluginStore = strapi.store({
environment: strapi.config.environment,
type: 'plugin',
name: 'upload'
name: 'upload',
});
strapi.plugins.upload.config.providers = [];
const loadProviders = (basePath, cb) => {
fs.readdir(path.join(basePath, 'node_modules'), async (err, node_modules) => {
// get all upload provider
const uploads = _.filter(node_modules, (node_module) => {
// DEPRECATED strapi-upload-* will be remove in next version
return _.startsWith(node_module, 'strapi-provider-upload') || _.startsWith(node_module, 'strapi-upload');
const installedProviders = Object.keys(
strapi.config.info.dependencies
).filter(d => d.startsWith('strapi-provider-upload-'));
for (let installedProvider of installedProviders) {
strapi.plugins.email.config.providers.push(require(installedProvider));
}
try {
// if provider config does not exist set one by default
const config = await pluginStore.get({ key: 'provider' });
if (!config) {
const provider = _.find(strapi.plugins.email.config.providers, {
provider: 'local',
});
node_modules.filter((node_module) => {
return node_module.startsWith('@');
})
.forEach((orga) => {
const node_modules = fs.readdirSync(path.join(basePath, 'node_modules', orga));
node_modules.forEach((node_module) => {
// DEPRECATED strapi-email-* will be remove in next version
if (_.startsWith(node_module, 'strapi-provider-upload') || _.startsWith(node_module, 'strapi-upload')) {
uploads.push(`${orga}/${node_module}`);
}
});
});
// mount all providers to get configs
_.forEach(uploads, (node_module) => {
strapi.plugins.upload.config.providers.push(
require(path.join(`${basePath}/node_modules/${node_module}`))
);
const value = _.assign({}, provider, {
enabled: true,
// by default limit size to 1 GB
sizeLimit: 1000000,
});
try {
// if provider config not exit set one by default
const config = await pluginStore.get({key: 'provider'});
if (!config) {
const provider = _.find(strapi.plugins.upload.config.providers, {provider: 'local'});
const value = _.assign({}, provider, {
enabled: true,
// by default limit size to 1 GB
sizeLimit: 1000000
});
await pluginStore.set({key: 'provider', value});
}
} catch (err) {
strapi.log.error(`Can't load ${config.provider} upload provider.`);
strapi.log.warn(`Please install strapi-provider-upload-${config.provider} --save in ${path.join(strapi.config.appPath, 'plugins', 'upload')} folder.`);
strapi.stop();
}
cb();
});
};
// Load providers from the plugins' node_modules.
loadProviders(path.join(strapi.config.appPath, 'plugins', 'upload'), () => {
// Load providers from the root node_modules.
loadProviders(path.join(strapi.config.appPath), cb);
});
await pluginStore.set({ key: 'provider', value });
}
} catch (err) {
strapi.log.error(err);
strapi.stop();
}
cb();
};
@@ -1,12 +1,24 @@
const RateLimit = require('koa2-ratelimit').RateLimit;
const lazyRateLimit = {
get RateLimit() {
return require('koa2-ratelimit').RateLimit;
},
};
module.exports = async (ctx, next) => {
const message = ctx.request.admin ? [{ messages: [{ id: 'Auth.form.error.ratelimit' }] }] : 'Too many attempts, please try again in a minute.';
const message = ctx.request.admin
? [{ messages: [{ id: 'Auth.form.error.ratelimit' }] }]
: 'Too many attempts, please try again in a minute.';
return RateLimit.middleware(Object.assign({}, {
interval: 1*60*1000,
max: 5,
prefixKey: `${ctx.request.url}:${ctx.request.ip}`,
message
}, strapi.plugins['users-permissions'].config.ratelimit))(ctx, next);
return lazyRateLimit.RateLimit.middleware(
Object.assign(
{},
{
interval: 1 * 60 * 1000,
max: 5,
prefixKey: `${ctx.request.url}:${ctx.request.ip}`,
message,
},
strapi.plugins['users-permissions'].config.ratelimit
)
)(ctx, next);
};
@@ -9,34 +9,40 @@ const _ = require('lodash');
module.exports = strapi => {
return {
beforeInitialize: function() {
beforeInitialize: function() {
strapi.config.middleware.load.before.unshift('users-permissions');
},
initialize: function(cb) {
_.forEach(strapi.admin.config.routes, value => {
if (_.get(value.config, 'policies')) {
value.config.policies.unshift('plugins.users-permissions.permissions');
value.config.policies.unshift(
'plugins.users-permissions.permissions'
);
}
});
_.forEach(strapi.config.routes, value => {
if (_.get(value.config, 'policies')) {
value.config.policies.unshift('plugins.users-permissions.permissions');
value.config.policies.unshift(
'plugins.users-permissions.permissions'
);
}
});
if (strapi.plugins) {
_.forEach(strapi.plugins, (plugin, name) => {
_.forEach(strapi.plugins, plugin => {
_.forEach(plugin.config.routes, value => {
if (_.get(value.config, 'policies')) {
value.config.policies.unshift('plugins.users-permissions.permissions');
value.config.policies.unshift(
'plugins.users-permissions.permissions'
);
}
});
});
}
cb();
}
},
};
};
@@ -8,7 +8,7 @@
const _ = require('lodash');
const request = require('request');
// Purest strategies.
// Purest strategies.<
const Purest = require('purest');
/**
@@ -1,6 +1,6 @@
'use strict';
const fs = require('fs');
const fs = require('fs-extra');
const path = require('path');
const _ = require('lodash');
const request = require('request');
@@ -611,24 +611,15 @@ module.exports = {
},
writeActions: (data, cb) => {
const actionsPath = path.join(
strapi.config.appPath,
'plugins',
'users-permissions',
'config',
'actions.json',
);
const actionsPath = path.join(strapi.config.appPath, 'extensions', 'users-permissions', 'config', 'actions.json');
try {
// Disable auto-reload.
strapi.reload.isWatching = false;
if (!strapi.config.currentEnvironment.server.production) {
// Rewrite actions.json file.
fs.writeFileSync(
actionsPath,
JSON.stringify({ actions: data }),
'utf8',
);
fs.ensureFileSync(actionsPath);
fs.writeFileSync(actionsPath, JSON.stringify({ actions: data }), 'utf8');
}
// Set value to AST to avoid restart.
_.set(strapi.plugins['users-permissions'], 'config.actions', data);
+13 -7
View File
@@ -10,7 +10,10 @@ const _ = require('lodash');
const logLevels = ['fatal', 'error', 'warn', 'info', 'debug', 'trace'];
function getLogLevel() {
if (_.isString(process.env.STRAPI_LOG_LEVEL) && _.includes(logLevels, process.env.STRAPI_LOG_LEVEL.toLowerCase())) {
if (
_.isString(process.env.STRAPI_LOG_LEVEL) &&
_.includes(logLevels, process.env.STRAPI_LOG_LEVEL.toLowerCase())
) {
return process.env.STRAPI_LOG_LEVEL;
}
return 'debug';
@@ -29,19 +32,22 @@ const loggerConfig = {
level: getLogLevel(),
timestamp: getBool(process.env.STRAPI_LOG_TIMESTAMP, false),
// prettyPrint: getBool(process.env.STRAPI_LOG_PRETTY_PRINT, true),
forceColor: getBool(process.env.STRAPI_LOG_FORCE_COLOR, true)
forceColor: getBool(process.env.STRAPI_LOG_FORCE_COLOR, true),
};
const pretty = pino.pretty({
formatter: (logs, options) => {
return `${options.asColoredText({ level: 10 }, `[${new Date().toISOString()}]`)} ${options.prefix.toLowerCase()} ${logs.msg}`;
}
return `${options.asColoredText(
{ level: 10 },
`[${new Date().toISOString()}]`
)} ${options.prefix.toLowerCase()} ${logs.stack ? logs.stack : logs.msg}`;
},
});
pretty.pipe(process.stdout);
const logger = getBool(process.env.STRAPI_LOG_PRETTY_PRINT, true) ?
pino(loggerConfig, pretty):
pino(loggerConfig);
const logger = getBool(process.env.STRAPI_LOG_PRETTY_PRINT, true)
? pino(loggerConfig, pretty)
: pino(loggerConfig);
module.exports = logger;
+41 -32
View File
@@ -7,7 +7,6 @@
*/
// Node.js core.
const child_process = require('child_process');
const os = require('os');
const path = require('path');
@@ -17,7 +16,6 @@ const fetch = require('node-fetch');
const { machineIdSync } = require('node-machine-id');
const shell = require('shelljs');
// Master of ceremonies for generators.
const generate = require('strapi-generate');
@@ -30,7 +28,7 @@ const packageJSON = require('../package.json');
* Generate a new Strapi application.
*/
module.exports = function (name, cliArguments) {
module.exports = function(name, cliArguments) {
console.log('🚀 Starting to create your Strapi application.');
const developerMode = cliArguments.dev !== undefined;
@@ -50,15 +48,27 @@ module.exports = function (name, cliArguments) {
strapiPackageJSON: packageJSON,
developerMode,
debug: cliArguments.debug !== undefined,
quick: cliArguments.quickstart !== undefined
quick: cliArguments.quickstart !== undefined,
};
const dbArguments = ['dbclient', 'dbhost', 'dbport', 'dbname', 'dbusername', 'dbpassword'];
const dbArguments = [
'dbclient',
'dbhost',
'dbport',
'dbname',
'dbusername',
'dbpassword',
];
const matchingDbArguments = _.intersection(_.keys(cliArguments), dbArguments);
if (matchingDbArguments.length) {
if (matchingDbArguments.length !== dbArguments.length && cliArguments.dbclient !== 'sqlite') {
console.log(`⛔️ Some database arguments are missing. Required arguments list: ${dbArguments}`);
if (
matchingDbArguments.length !== dbArguments.length &&
cliArguments.dbclient !== 'sqlite'
) {
console.log(
`⛔️ Some database arguments are missing. Required arguments list: ${dbArguments}`
);
return process.exit(1);
}
@@ -73,16 +83,16 @@ module.exports = function (name, cliArguments) {
database: cliArguments.dbname,
username: cliArguments.dbusername,
password: cliArguments.dbpassword,
filename: cliArguments.dbfile
filename: cliArguments.dbfile,
},
options: {
authenticationDatabase: cliArguments.dbauth,
ssl: cliArguments.dbssl
}
ssl: cliArguments.dbssl,
},
};
}
const error = (error) => {
const error = error => {
fetch('https://analytics.strapi.io/track', {
method: 'POST',
body: JSON.stringify({
@@ -90,17 +100,15 @@ module.exports = function (name, cliArguments) {
deviceId: machineIdSync(),
properties: {
error,
os: os.type()
}
os: os.type(),
},
}),
headers: { 'Content-Type': 'application/json' }
})
.catch(() => {});
headers: { 'Content-Type': 'application/json' },
}).catch(() => {});
};
// Return the scope and the response (`error` or `success`).
return generate(scope, {
// Log and exit the REPL in case there is an error
// while we were trying to generate the new app.
error: function returnError(err) {
@@ -109,40 +117,41 @@ module.exports = function (name, cliArguments) {
process.exit(1);
},
success: () => {
success: () => {
if (scope.quick) {
try {
// Enter inside the project folder.
shell.cd(scope.rootPath);
// shell.cd(scope.rootPath);
// Empty log.
console.log();
// Create interface for windows user to let them quit the program.
if (process.platform === "win32") {
const rl = require("readline").createInterface({
if (process.platform === 'win32') {
const rl = require('readline').createInterface({
input: process.stdin,
output: process.stdout
output: process.stdout,
});
rl.on("SIGINT", function () {
process.emit("SIGINT");
rl.on('SIGINT', function() {
process.emit('SIGINT');
});
}
// Listen Ctrl+C / SIGINT event to close the process.
process.on("SIGINT", function () {
process.on('SIGINT', function() {
process.exit();
});
// Launch the server.
const child = child_process.exec('strapi start', { stdio: 'inherit' });
// Display child process logs in the parent process.
child.stdout.pipe(process.stdout);
child.stderr.pipe(process.stderr);
// shell.exec('strapi start');
shell.exec('strapi start', {
stdio: 'inherit',
env: {
...process.env,
FORCE_COLOR: 1,
},
});
} catch (e) {
console.log(e);
error(e);
}
}
}
},
});
};
+156 -90
View File
@@ -6,17 +6,23 @@ const path = require('path');
const cluster = require('cluster');
const { EventEmitter } = require('events');
const Koa = require('koa');
const { includes, get, assign, toLower } = require('lodash');
const _ = require('lodash');
const { logger, models } = require('strapi-utils');
const stackTrace = require('stack-trace');
const utils = require('./utils');
const { nestedConfigurations, appConfigurations, apis, middlewares, hooks, plugins, admin, store } = require('./core');
const {
loadConfigs,
loadApis,
loadMiddlewares,
loadHooks,
appConfigurations,
plugins,
admin,
store,
} = require('./core');
const initializeMiddlewares = require('./middlewares');
const initializeHooks = require('./hooks');
/* eslint-disable prefer-template */
/* eslint-disable no-console */
/* eslint-disable indent */
/**
* Construct an Strapi instance.
*
@@ -60,7 +66,7 @@ class Strapi extends EventEmitter {
appPath: process.cwd(),
host: process.env.HOST || process.env.HOSTNAME || 'localhost',
port: process.env.PORT || 1337,
environment: toLower(process.env.NODE_ENV) || 'development',
environment: _.toLower(process.env.NODE_ENV) || 'development',
environments: {},
admin: {},
paths: {
@@ -82,18 +88,14 @@ class Strapi extends EventEmitter {
functions: {},
routes: {},
};
// Bind context functions.
this.loadFile = utils.loadFile.bind(this);
}
async start(config = {}, cb) {
try {
this.config = assign(this.config, config);
this.config = _.assign(this.config, config);
// Emit starting event.
this.emit('server:starting');
// Load the app.
await this.load();
// Run bootstrap function.
@@ -106,17 +108,17 @@ class Strapi extends EventEmitter {
utils.init.call(this);
// Launch server.
this.server.listen(this.config.port, async err => {
if (err) {
this.log.debug(`⚠️ Server wasn't able to start properly.`);
this.log.error(err);
return this.stop();
}
if (err) return this.stopWithError(err);
this.log.info('Time: ' + new Date());
this.log.info('Launched in: ' + (Date.now() - this.config.launchedAt) + ' ms');
this.log.info(
'Launched in: ' + (Date.now() - this.config.launchedAt) + ' ms'
);
this.log.info('Environment: ' + this.config.environment);
this.log.info('Process PID: ' + process.pid);
this.log.info(`Version: ${this.config.info.strapi} (node v${this.config.info.node})`);
this.log.info(
`Version: ${this.config.info.strapi} (node v${this.config.info.node})`
);
this.log.info('To shut down your server, press <CTRL> + C at any time');
console.log();
this.log.info(`☄️ Admin panel: ${this.config.admin.url}`);
@@ -132,21 +134,37 @@ class Strapi extends EventEmitter {
if (
(this.config.environment === 'development' &&
get(this.config.currentEnvironment, 'server.admin.autoOpen', true) !== false) ||
_.get(
this.config.currentEnvironment,
'server.admin.autoOpen',
true
) !== false) ||
this.config.init
) {
await utils.openBrowser.call(this);
}
});
} catch (err) {
this.log.debug(`⛔️ Server wasn't able to start properly.`);
this.log.error(err);
console.log(err);
this.stop();
this.stopWithError(err);
}
}
/**
* Add behaviors to the server
*/
async enhancer() {
// handle port in use cleanly
this.server.on('error', err => {
if (err.code === 'EADDRINUSE') {
return this.stopWithError(
`The port ${err.port} is already used by another application.`
);
}
this.log.error(err);
});
// Close current connections to fully destroy the server
const connections = {};
this.server.on('connection', conn => {
@@ -158,17 +176,6 @@ class Strapi extends EventEmitter {
});
});
this.server.on('error', err => {
if (err.code === 'EADDRINUSE') {
this.log.debug(`⛔️ Server wasn't able to start properly.`);
this.log.error(`The port ${err.port} is already used by another application.`);
this.stop();
return;
}
console.error(err);
});
this.server.destroy = cb => {
this.server.close(cb);
@@ -178,6 +185,12 @@ class Strapi extends EventEmitter {
};
}
stopWithError(err) {
this.log.debug(`⛔️ Server wasn't able to start properly.`);
this.log.error(err);
return this.stop();
}
stop() {
// Destroy server and available connections.
this.server.destroy();
@@ -185,7 +198,11 @@ class Strapi extends EventEmitter {
if (
cluster.isWorker &&
this.config.environment === 'development' &&
get(this.config, 'currentEnvironment.server.autoReload.enabled', true) === true
_.get(
this.config,
'currentEnvironment.server.autoReload.enabled',
true
) === true
) {
process.send('stop');
}
@@ -206,20 +223,47 @@ class Strapi extends EventEmitter {
}
});
// Create AST.
await Promise.all([nestedConfigurations.call(this), apis.call(this), middlewares.call(this), hooks.call(this)]);
this.config.info = require(path.resolve(
this.config.appPath,
'package.json'
));
this.config.installedPlugins = Object.keys(
this.config.info.dependencies
).filter(d => d.startsWith('strapi-plugin'));
this.config.installedMiddlewares = Object.keys(
this.config.info.dependencies
).filter(d => d.startsWith('strapi-middleware'));
this.config.installedHooks = Object.keys(
this.config.info.dependencies
).filter(d => d.startsWith('strapi-hook'));
// load configs
_.merge(this, await loadConfigs(this.config));
// load apis
_.merge(this, await loadApis(this.config));
// load middlewares
const { middlewares, koaMiddlewares } = await loadMiddlewares(this.config);
this.middleware = middlewares;
this.koaMiddlewares = koaMiddlewares;
// load hooks
this.hook = await loadHooks(this.config);
// Populate AST with configurations.
await appConfigurations.call(this);
// Usage.
await utils.usage.call(this);
await utils.usage(this.config);
// Init core store
await store.call(this);
// Initialize hooks and middlewares.
await Promise.all([initializeMiddlewares.call(this), initializeHooks.call(this)]);
await Promise.all([
initializeMiddlewares.call(this),
initializeHooks.call(this),
]);
// Harmonize plugins configuration.
await plugins.call(this);
@@ -241,7 +285,11 @@ class Strapi extends EventEmitter {
if (
cluster.isWorker &&
this.config.environment === 'development' &&
get(this.config, 'currentEnvironment.server.autoReload.enabled', true) === true
_.get(
this.config,
'currentEnvironment.server.autoReload.enabled',
true
) === true
) {
this.server.close();
process.send('reload');
@@ -270,48 +318,57 @@ class Strapi extends EventEmitter {
}
async bootstrap() {
const execBootstrap = fn =>
!fn
? Promise.resolve()
: new Promise((resolve, reject) => {
const timeoutMs = this.config.bootstrapTimeout || 3500;
const timer = setTimeout(() => {
this.log.warn(`Bootstrap is taking unusually long to execute its callback ${timeoutMs} miliseconds).`);
this.log.warn('Perhaps you forgot to call it?');
}, timeoutMs);
const execBootstrap = fn => {
if (!fn) return Promise.resolve();
let ranBootstrapFn = false;
return new Promise((resolve, reject) => {
const timeoutMs = this.config.bootstrapTimeout || 3500;
const timer = setTimeout(() => {
this.log.warn(
`The bootstrap function is taking unusually long to execute (${timeoutMs} miliseconds).`
);
this.log.warn('Make sure you call it?');
}, timeoutMs);
try {
fn(err => {
if (ranBootstrapFn) {
this.log.error('You called the callback in `strapi.config.boostrap` more than once!');
let ranBootstrapFn = false;
return reject();
}
try {
fn(err => {
if (ranBootstrapFn) {
this.log.error(
'You called the callback in `strapi.config.boostrap` more than once!'
);
ranBootstrapFn = true;
clearTimeout(timer);
return resolve(err);
});
} catch (e) {
if (ranBootstrapFn) {
this.log.error('The bootstrap function threw an error after its callback was called.');
return reject(e);
}
ranBootstrapFn = true;
clearTimeout(timer);
return resolve(e);
return reject();
}
});
return Promise.all(Object.values(this.plugins).map(x => execBootstrap(get(x, 'config.functions.bootstrap')))).then(
() => execBootstrap(this.config.functions.bootstrap),
);
ranBootstrapFn = true;
clearTimeout(timer);
return resolve(err);
});
} catch (e) {
if (ranBootstrapFn) {
this.log.error(
'The bootstrap function threw an error after its callback was called.'
);
return reject(e);
}
ranBootstrapFn = true;
clearTimeout(timer);
return resolve(e);
}
});
};
return Promise.all(
Object.values(this.plugins).map(plugin =>
execBootstrap(_.get(plugin, 'config.functions.bootstrap'))
)
).then(() => execBootstrap(this.config.functions.bootstrap));
}
async freeze() {
@@ -321,7 +378,7 @@ class Strapi extends EventEmitter {
delete this.propertiesToNotFreeze;
return Object.keys(this)
.filter(x => !includes(propertiesToNotFreeze, x))
.filter(x => !_.includes(propertiesToNotFreeze, x))
.forEach(key => {
Object.freeze(this[key]);
});
@@ -329,17 +386,18 @@ class Strapi extends EventEmitter {
query(entity, plugin) {
if (!entity) {
return this.log.error(`You can't call the query method without passing the model's name as a first argument.`);
return this.log.error(
`You can't call the query method without passing the model's name as a first argument.`
);
}
const model = entity.toLowerCase();
let Model;
if (plugin === 'admin') {
Model = get(strapi.admin, ['models', model], undefined);
Model = _.get(strapi.admin, ['models', model], undefined);
} else {
Model = get(strapi.plugins, [plugin, 'models', model]) || get(strapi, ['models', model]) || undefined;
Model = _.get(strapi.plugins, [plugin, 'models', model]) || get(strapi, ['models', model]) || undefined;
}
if (!Model) {
@@ -349,7 +407,9 @@ class Strapi extends EventEmitter {
const connector = Model.orm;
if (!connector) {
return this.log.error(`Impossible to determine the use ORM for the model ${model}.`);
return this.log.error(
`Impossible to determine the use ORM for the model ${model}.`
);
}
// Get stack trace.
@@ -361,7 +421,9 @@ class Strapi extends EventEmitter {
let pluginPath = undefined;
if (file.indexOf('strapi-plugin-') !== -1) {
pluginPath = file.split(path.sep).filter(x => x.indexOf('strapi-plugin-') !== -1)[0];
pluginPath = file
.split(path.sep)
.filter(x => x.indexOf('strapi-plugin-') !== -1)[0];
} else if (file.indexOf(path.sep + 'plugins' + path.sep) !== -1) {
const pathTerms = file.split(path.sep);
const index = pathTerms.indexOf('plugins');
@@ -374,18 +436,22 @@ class Strapi extends EventEmitter {
}
if (!pluginPath) {
return this.log.error('Impossible to find the plugin where `strapi.query` has been called.');
return this.log.error(
'Impossible to find the plugin where `strapi.query` has been called.'
);
}
// Get plugin name.
const pluginName = pluginPath.replace('strapi-plugin-', '').toLowerCase();
const queries =
pluginPath === 'admin'
? get(this.admin, `config.queries.${connector}`)
: get(this.plugins, `${pluginName}.config.queries.${connector}`);
? _.get(this.admin, `config.queries.${connector}`)
: _.get(this.plugins, `${pluginName}.config.queries.${connector}`);
if (!queries) {
return this.log.error(`There is no query available for the model ${model}.`);
return this.log.error(
`There is no query available for the model ${model}.`
);
}
// Bind queries with the current model to allow the use of `this`.
+104 -46
View File
@@ -1,52 +1,110 @@
'use strict';
// Dependencies.
const glob = require('glob');
const utils = require('../utils');
// const glob = require('glob');
const path = require('path');
const slash = require('slash');
const _ = require('lodash');
const glob = require('../load/glob');
const findPackagePath = require('../load/package-path');
module.exports = function() {
return Promise.all([
new Promise((resolve, reject) => {
// Load configurations.
glob('./api/*/!(config)/*.*(js|json)', {
cwd: this.config.appPath
}, (err, files) => {
if (err) {
return reject(err);
}
files.map(p => utils.setConfig(this, p, 'aggregate', this.loadFile));
resolve();
});
}),
new Promise((resolve, reject) => {
// Load configurations.
glob('./admin/!(config|node_modules|scripts)/*.*(js|json)', {
cwd: this.config.appPath
}, (err, files) => {
if (err) {
return reject(err);
}
files.map(p => utils.setConfig(this, p, 'aggregate', this.loadFile));
resolve();
});
}),
new Promise((resolve, reject) => {
// Load configurations.
glob('{./plugins/*/!(config|node_modules|test)/*.*(js|json),./plugins/*/package.json}', {
cwd: this.config.appPath
}, (err, files) => {
if (err) {
return reject(err);
}
files.map(p => utils.setConfig(this, p, 'aggregate', this.loadFile));
resolve();
});
})
module.exports = async function({ appPath, installedPlugins }) {
const [api, admin, plugins, localPlugins] = await Promise.all([
loadAppApis(appPath),
loadAdminApis(),
loadPluginsApis(installedPlugins),
loadLocalPluginsApis(appPath),
]);
return {
api,
admin,
plugins: _.merge(plugins, localPlugins),
};
};
const loadFile = (obj, dir, file, prefix = null) => {
const rootPath = path
.join(path.dirname(file), path.basename(file, path.extname(file)))
.replace(/(\.settings|.json|.js)/g, '')
.toLowerCase();
const propPath = slash(rootPath).split('/');
_.set(
obj,
prefix ? [prefix].concat(propPath) : propPath,
require(path.join(dir, file))
);
};
const loadAppApis = async appPath => {
let apis = {};
const apiPath = path.resolve(appPath, 'api');
const files = await glob('*/!(config)/*.*(js|json)', {
cwd: apiPath,
});
for (let file of files) {
loadFile(apis, apiPath, file);
}
return apis;
};
const loadAdminApis = async () => {
let admin = {};
const adminPath = path.resolve(findPackagePath('strapi-admin'));
const files = await glob('!(config|node_modules|scripts)//*.*(js|json)', {
cwd: adminPath,
});
for (let file of files) {
loadFile(admin, adminPath, file);
}
return admin;
};
const loadLocalPluginsApis = async appPath => {
let localPlugins = {};
const pluginsPath = path.resolve(appPath, 'plugins');
const files = await glob('*/!(config)/*.*(js|json)', {
cwd: pluginsPath,
});
for (let file of files) {
loadFile(localPlugins, pluginsPath, file);
}
return localPlugins;
};
const loadPluginsApis = async installedPlugins => {
let plugins = {};
for (let plugin of installedPlugins) {
const pluginPath = path.resolve(findPackagePath(plugin));
const files = await glob(
'{!(config|node_modules|test)//*.*(js|json),package.json}',
{
cwd: pluginPath,
}
);
for (let file of files) {
loadFile(
plugins,
pluginPath,
file,
plugin.substr('strapi-plugin-'.length)
);
}
}
return plugins;
};
+281 -164
View File
@@ -1,100 +1,125 @@
'use strict';
// Dependencies.
const fs = require('fs');
// const fs = require('fs');
const path = require('path');
const glob = require('glob');
const { merge, setWith, get, upperFirst, isEmpty, isObject, pullAll, defaults, assign, clone, cloneDeep, camelCase } = require('lodash');
const { templateConfiguration } = require('strapi-utils');
const utils = require('../utils');
const _ = require('lodash');
const fs = require('fs-extra');
module.exports.nested = function() {
return Promise.all([
// Load root configurations.
new Promise((resolve, reject) => {
glob('./config/**/*.*(js|json)', {
cwd: this.config.appPath,
dot: true
}, (err, files) => {
if (err) {
return reject(err);
}
const loadConfig = require('../load/config');
const findPackagePath = require('../load/package-path');
utils.loadConfig.call(this, files).then(resolve).catch(reject);
});
}),
// Load APIs configurations.
new Promise((resolve, reject) => {
glob('./api/*/config/**/*.*(js|json)', {
cwd: this.config.appPath
}, (err, files) => {
if (err) {
return reject(err);
}
const PLUGIN_PREFIX = 'strapi-plugin';
utils.loadConfig.call(this, files).then(resolve).catch(reject);
});
}),
// Load plugins configurations.
new Promise((resolve, reject) => {
glob('./plugins/*/config/**/*.*(js|json)', {
cwd: this.config.appPath
}, (err, files) => {
if (err) {
return reject(err);
}
utils.loadConfig.call(this, files).then(resolve).catch(reject);
});
}),
// Load admin configurations.
new Promise((resolve, reject) => {
glob('./admin/config/**/*.*(js|json)', {
cwd: this.config.appPath
}, (err, files) => {
if (err) {
return reject(err);
}
utils.loadConfig.call(this, files).then(resolve).catch(reject);
});
}),
// Load plugins configurations.
new Promise(resolve => {
setWith(
this,
'config.info',
require(path.resolve(process.cwd(), 'package.json')),
Object
);
resolve();
})
module.exports.loadConfigs = async function({ appPath, installedPlugins }) {
const [config, admin, api, plugins, localPlugins] = await Promise.all([
loadAppConfig(appPath),
loadAdminConfig(),
loadApisConfig(appPath),
loadPluginsConfig(installedPlugins),
loadLocalPluginsConfig(appPath),
]);
return {
config,
admin,
api,
plugins: _.merge(plugins, localPlugins),
};
};
module.exports.app = async function() {
// Loads an app config folder
const loadAppConfig = appPath => loadConfig(path.resolve(appPath, 'config'));
// Loads the strapi-admin config folder
const loadAdminConfig = async () => ({
config: await loadConfig(
path.resolve(findPackagePath('strapi-admin'), 'config')
),
});
// Loads every apis config folder
const loadApisConfig = async appPath => {
let apis = {};
const apiFolder = path.resolve(appPath, 'api');
const apiFolders = await fs.readdir(apiFolder);
for (let apiFolder of apiFolders) {
const apiConfig = await loadConfig(
path.resolve(apiFolder, apiFolder, 'config')
);
_.set(apis, [apiFolder, 'config'], apiConfig);
}
return apis;
};
const loadLocalPluginsConfig = async appPath => {
let localPlugins = {};
const pluginsFolder = path.resolve(appPath, 'plugins');
const pluginsFolders = await fs.readdir(pluginsFolder);
for (let pluginsFolder of pluginsFolders) {
const pluginsConfig = await loadConfig(
path.resolve(pluginsFolder, pluginsFolder, 'config')
);
_.set(localPlugins, [pluginsFolder, 'config'], pluginsConfig);
}
return localPlugins;
};
// Loads installed plugins config
const loadPluginsConfig = async pluginsNames => {
let plugins = {};
for (let plugin of pluginsNames) {
const pluginConfig = await loadConfig(
path.resolve(findPackagePath(plugin), 'config')
);
_.set(
plugins,
[plugin.substring(PLUGIN_PREFIX.length + 1), 'config'],
pluginConfig
);
}
return plugins;
};
module.exports.app = function() {
// Retrieve Strapi version.
this.config.uuid = get(this.config.info, 'strapi.uuid', '');
this.config.info.customs = get(this.config.info, 'strapi', {});
this.config.info.strapi = (get(this.config, 'info.dependencies.strapi') || '').replace(/(\^|~)/g, ''),
this.config.uuid = _.get(this.config.info, 'strapi.uuid', '');
this.config.info.customs = _.get(this.config.info, 'strapi', {});
this.config.info.strapi = (
_.get(this.config, 'info.dependencies.strapi') || ''
).replace(/(\^|~)/g, '');
this.config.info.node = process.versions.node;
// Set connections.
this.connections = {};
// Set current environment config.
this.config.currentEnvironment = this.config.environments[this.config.environment] || {};
this.config.currentEnvironment =
this.config.environments[this.config.environment] || {};
// Set current connections.
this.config.connections = get(this.config.currentEnvironment, 'database.connections', {});
this.config.connections = _.get(
this.config.currentEnvironment,
'database.connections',
{}
);
if (get(this.config, 'language.enabled')) {
this.config.language.locales = Object.keys(get(strapi.config, 'locales', {}));
if (_.get(this.config, 'language.enabled')) {
this.config.language.locales = Object.keys(
_.get(strapi.config, 'locales', {})
);
}
// Template literal string.
this.config = templateConfiguration(this.config);
// this.config = templateConfiguration(this.config);
// Initialize main router to use it in middlewares.
this.router = this.koaMiddlewares.routerJoi();
@@ -103,7 +128,7 @@ module.exports.app = async function() {
this.controllers = Object.keys(this.api || []).reduce((acc, key) => {
for (let index in this.api[key].controllers) {
if (!this.api[key].controllers[index].identity) {
this.api[key].controllers[index].identity = upperFirst(index);
this.api[key].controllers[index].identity = _.upperFirst(index);
}
acc[index] = this.api[key].controllers[index];
@@ -116,15 +141,17 @@ module.exports.app = async function() {
this.models = Object.keys(this.api || []).reduce((acc, key) => {
for (let index in this.api[key].models) {
if (!this.api[key].models[index].globalId) {
this.api[key].models[index].globalId = upperFirst(camelCase(index));
this.api[key].models[index].globalId = _.upperFirst(_.camelCase(index));
}
if (!this.api[key].models[index].connection) {
this.api[key].models[index].connection = this.config.currentEnvironment.database.defaultConnection;
this.api[key].models[
index
].connection = this.config.currentEnvironment.database.defaultConnection;
}
if (!this.api[key].models[index].collectionName) {
this.api[key].models[index].collectionName = (`${index}`).toLowerCase();
this.api[key].models[index].collectionName = `${index}`.toLowerCase();
}
acc[index] = this.api[key].models[index];
@@ -143,41 +170,53 @@ module.exports.app = async function() {
// Set routes.
this.config.routes = Object.keys(this.api || []).reduce((acc, key) => {
return acc.concat(get(this.api[key], 'config.routes') || {});
return acc.concat(_.get(this.api[key], 'config.routes') || {});
}, []);
// Set admin controllers.
this.admin.controllers = Object.keys(this.admin.controllers || []).reduce((acc, key) => {
if (!this.admin.controllers[key].identity) {
this.admin.controllers[key].identity = key;
}
this.admin.controllers = Object.keys(this.admin.controllers || []).reduce(
(acc, key) => {
if (!this.admin.controllers[key].identity) {
this.admin.controllers[key].identity = key;
}
acc[key] = this.admin.controllers[key];
acc[key] = this.admin.controllers[key];
return acc;
}, {});
return acc;
},
{}
);
// Set admin models.
this.admin.models = Object.keys(this.admin.models || []).reduce((acc, key) => {
if (!this.admin.models[key].identity) {
this.admin.models[key].identity = upperFirst(key);
}
this.admin.models = Object.keys(this.admin.models || []).reduce(
(acc, key) => {
if (!this.admin.models[key].identity) {
this.admin.models[key].identity = _.upperFirst(key);
}
if (!this.admin.models[key].globalId) {
this.admin.models[key].globalId = upperFirst(camelCase(`admin-${key}`));
}
if (!this.admin.models[key].globalId) {
this.admin.models[key].globalId = _.upperFirst(
_.camelCase(`admin-${key}`)
);
}
if (!this.admin.models[key].connection) {
this.admin.models[key].connection = this.config.currentEnvironment.database.defaultConnection;
}
if (!this.admin.models[key].connection) {
this.admin.models[
key
].connection = this.config.currentEnvironment.database.defaultConnection;
}
acc[key] = this.admin.models[key];
acc[key] = this.admin.models[key];
return acc;
}, {});
return acc;
},
{}
);
this.plugins = Object.keys(this.plugins).reduce((acc, key) => {
this.plugins[key].controllers = Object.keys(this.plugins[key].controllers || []).reduce((sum, index) => {
this.plugins[key].controllers = Object.keys(
this.plugins[key].controllers || []
).reduce((sum, index) => {
if (!this.plugins[key].controllers[index].identity) {
this.plugins[key].controllers[index].identity = index;
}
@@ -187,17 +226,25 @@ module.exports.app = async function() {
return sum;
}, {});
this.plugins[key].models = Object.keys(this.plugins[key].models || []).reduce((sum, index) => {
this.plugins[key].models = Object.keys(
this.plugins[key].models || []
).reduce((sum, index) => {
if (!this.plugins[key].models[index].connection) {
this.plugins[key].models[index].connection = this.config.currentEnvironment.database.defaultConnection;
this.plugins[key].models[
index
].connection = this.config.currentEnvironment.database.defaultConnection;
}
if (!this.plugins[key].models[index].globalId) {
this.plugins[key].models[index].globalId = upperFirst(camelCase(`${key}-${index}`));
this.plugins[key].models[index].globalId = _.upperFirst(
_.camelCase(`${key}-${index}`)
);
}
if (!this.plugins[key].models[index].collectionName) {
this.plugins[key].models[index].collectionName = `${key}_${index}`.toLowerCase();
this.plugins[key].models[
index
].collectionName = `${key}_${index}`.toLowerCase();
}
sum[index] = this.plugins[key].models[index];
@@ -215,17 +262,17 @@ module.exports.app = async function() {
// Flatten middlewares configurations.
const flattenMiddlewaresConfig = middlewareCategories.reduce((acc, index) => {
const current = merge(this.config.currentEnvironment[index], {
public: defaults(this.config.public, {
enabled: true
const current = _.merge(this.config.currentEnvironment[index], {
public: _.defaults(this.config.public, {
enabled: true,
}),
favicon: _.defaults(this.config.favicon, {
enabled: true,
}),
favicon: defaults(this.config.favicon, {
enabled: true
})
});
if (isObject(current)) {
acc = merge(acc, current);
if (_.isObject(current)) {
acc = _.merge(acc, current);
} else {
acc[index] = current;
}
@@ -234,45 +281,48 @@ module.exports.app = async function() {
}, {});
// These middlewares cannot be disabled.
merge(flattenMiddlewaresConfig, {
_.merge(flattenMiddlewaresConfig, {
// Necessary middlewares for the core.
responses: {
enabled: true
enabled: true,
},
router: {
enabled: true
enabled: true,
},
logger: {
enabled: true
enabled: true,
},
boom: {
enabled: true
enabled: true,
},
mask: {
enabled: true
enabled: true,
},
// Necessary middlewares for the administration panel.
cors: {
enabled: true
enabled: true,
},
xframe: {
enabled: true
enabled: true,
},
xss: {
enabled: true
}
enabled: true,
},
});
// Exclude database and custom.
middlewareCategories.push('database');
// Flatten hooks configurations.
const flattenHooksConfig = pullAll(Object.keys(this.config.currentEnvironment), middlewareCategories).reduce((acc, index) => {
const flattenHooksConfig = _.pullAll(
Object.keys(this.config.currentEnvironment),
middlewareCategories
).reduce((acc, index) => {
const current = this.config.currentEnvironment[index];
if (isObject(current)) {
acc = merge(acc, {
[index]: current
if (_.isObject(current)) {
acc = _.merge(acc, {
[index]: current,
});
} else {
acc[index] = current;
@@ -290,70 +340,122 @@ module.exports.app = async function() {
}
// Preset config in alphabetical order.
this.config.middleware.settings = Object.keys(this.middleware).reduce((acc, current) => {
// Try to find the settings in the current environment, then in the main configurations.
const currentSettings = merge(get(cloneDeep(this.middleware[current]), ['defaults', current], {}), flattenMiddlewaresConfig[current] || this.config.currentEnvironment[current] || this.config[current]);
acc[current] = !isObject(currentSettings) ? {} : currentSettings;
this.config.middleware.settings = Object.keys(this.middleware).reduce(
(acc, current) => {
// Try to find the settings in the current environment, then in the main configurations.
const currentSettings = _.merge(
_.get(_.cloneDeep(this.middleware[current]), ['defaults', current], {}),
flattenMiddlewaresConfig[current] ||
this.config.currentEnvironment[current] ||
this.config[current]
);
acc[current] = !_.isObject(currentSettings) ? {} : currentSettings;
if (!acc[current].hasOwnProperty('enabled')) {
this.log.warn(`(middleware:${current}) wasn't loaded due to missing key \`enabled\` in the configuration`);
}
if (!acc[current].hasOwnProperty('enabled')) {
this.log.warn(
`(middleware:${current}) wasn't loaded due to missing key \`enabled\` in the configuration`
);
}
// Ensure that enabled key exist by forcing to false.
defaults(acc[current], { enabled : false });
// Ensure that enabled key exist by forcing to false.
_.defaults(acc[current], { enabled: false });
return acc;
}, {});
return acc;
},
{}
);
this.config.hook.settings = Object.keys(this.hook).reduce((acc, current) => {
// Try to find the settings in the current environment, then in the main configurations.
const currentSettings = merge(get(cloneDeep(this.hook[current]), ['defaults', current], {}), flattenHooksConfig[current] || get(this.config.currentEnvironment, ['hook', current]) || get(this.config, ['hook', current]));
acc[current] = !isObject(currentSettings) ? {} : currentSettings;
const currentSettings = _.merge(
_.get(_.cloneDeep(this.hook[current]), ['defaults', current], {}),
flattenHooksConfig[current] ||
_.get(this.config.currentEnvironment, ['hook', current]) ||
_.get(this.config, ['hook', current])
);
acc[current] = !_.isObject(currentSettings) ? {} : currentSettings;
if (!acc[current].hasOwnProperty('enabled')) {
this.log.warn(`(hook:${current}) wasn't loaded due to missing key \`enabled\` in the configuration`);
this.log.warn(
`(hook:${current}) wasn't loaded due to missing key \`enabled\` in the configuration`
);
}
// Ensure that enabled key exist by forcing to false.
defaults(acc[current], { enabled : false });
_.defaults(acc[current], { enabled: false });
return acc;
}, {});
// default settings
this.config.port = get(this.config.currentEnvironment, 'server.port') || this.config.port;
this.config.host = get(this.config.currentEnvironment, 'server.host') || this.config.host;
this.config.port =
_.get(this.config.currentEnvironment, 'server.port') || this.config.port;
this.config.host =
_.get(this.config.currentEnvironment, 'server.host') || this.config.host;
// Admin.
const url = getURLFromSegments({ hostname: this.config.host, port: this.config.port });
const adminPath = get(this.config.currentEnvironment.server, 'admin.path', 'admin');
const url = getURLFromSegments({
hostname: this.config.host,
port: this.config.port,
});
const adminPath = _.get(
this.config.currentEnvironment.server,
'admin.path',
'admin'
);
this.config.admin.devMode = isAdminInDevMode.call(this);
this.config.admin.url = this.config.admin.devMode ?
(new URL(adminPath, `http://${this.config.host}:4000`)).toString():
(new URL(adminPath, url)).toString();
this.config.admin.url = this.config.admin.devMode
? new URL(adminPath, `http://${this.config.host}:4000`).toString()
: new URL(adminPath, url).toString();
// proxy settings
const proxy = get(this.config.currentEnvironment, 'server.proxy', {});
const proxy = _.get(this.config.currentEnvironment, 'server.proxy', {});
this.config.proxy = proxy;
// check if proxy is enabled and construct url
this.config.url = proxy.enabled ? getURLFromSegments({ hostname: proxy.host, port: proxy.port, ssl: proxy.ssl }) : url;
this.config.url = proxy.enabled
? getURLFromSegments({
hostname: proxy.host,
port: proxy.port,
ssl: proxy.ssl,
})
: url;
};
const enableHookNestedDependencies = function (name, flattenHooksConfig, force = false) {
const enableHookNestedDependencies = function(
name,
flattenHooksConfig,
force = false
) {
if (!this.hook[name]) {
this.log.warn(`(hook:${name}) \`strapi-hook-${name}\` is missing in your dependencies. Please run \`npm install strapi-hook-${name}\``);
this.log.warn(
`(hook:${name}) \`strapi-hook-${name}\` is missing in your dependencies. Please run \`npm install strapi-hook-${name}\``
);
}
// Couldn't find configurations for this hook.
if (isEmpty(get(flattenHooksConfig, name, true))) {
if (_.isEmpty(_.get(flattenHooksConfig, name, true))) {
// Check if database connector is used
const modelsUsed = Object.keys(assign(clone(this.api) || {}, this.plugins))
.filter(x => isObject(get(this.api, [x, 'models']) || get(this.plugins, [x, 'models']))) // Filter API with models
.map(x => get(this.api, [x, 'models']) || get(this.plugins, [x, 'models'])) // Keep models
const modelsUsed = Object.keys(
_.assign(_.clone(this.api) || {}, this.plugins)
)
.filter(x =>
_.isObject(
_.get(this.api, [x, 'models']) || _.get(this.plugins, [x, 'models'])
)
) // Filter API with models
.map(
x =>
_.get(this.api, [x, 'models']) || _.get(this.plugins, [x, 'models'])
) // Keep models
.filter(models => {
const apiModelsUsed = Object.keys(models).filter(model => {
const connector = get(this.config.connections, models[model].connection, {}).connector;
const connector = _.get(
this.config.connections,
models[model].connection,
{}
).connector;
if (connector) {
return connector.replace('strapi-hook-', '') === name;
@@ -366,21 +468,35 @@ const enableHookNestedDependencies = function (name, flattenHooksConfig, force =
}); // Filter model with the right connector
flattenHooksConfig[name] = {
enabled: force || modelsUsed.length > 0 // Will return false if there is no model, else true.
enabled: force || modelsUsed.length > 0, // Will return false if there is no model, else true.
};
// Enabled dependencies.
if (get(this.hook, `${name}.dependencies`, []).length > 0) {
if (_.get(this.hook, `${name}.dependencies`, []).length > 0) {
this.hook[name].dependencies.forEach(dependency => {
enableHookNestedDependencies.call(this, dependency.replace('strapi-hook-', ''), flattenHooksConfig, true);
enableHookNestedDependencies.call(
this,
dependency.replace('strapi-hook-', ''),
flattenHooksConfig,
true
);
});
}
}
};
const isAdminInDevMode = function () {
const isAdminInDevMode = function() {
try {
fs.accessSync(path.resolve(this.config.appPath, 'admin', 'admin', 'build', 'index.html'), fs.constants.R_OK | fs.constants.W_OK);
fs.accessSync(
path.resolve(
this.config.appPath,
'admin',
'admin',
'build',
'index.html'
),
fs.constants.R_OK | fs.constants.W_OK
);
return false;
} catch (e) {
@@ -388,10 +504,11 @@ const isAdminInDevMode = function () {
}
};
const getURLFromSegments = function ({ hostname, port, ssl = false }) {
const getURLFromSegments = function({ hostname, port, ssl = false }) {
const protocol = ssl ? 'https' : 'http';
const defaultPort = ssl ? 443 : 80;
const portString = (port === undefined || parseInt(port) === defaultPort) ? '' : `:${port}`;
const portString =
port === undefined || parseInt(port) === defaultPort ? '' : `:${port}`;
return `${protocol}://${hostname}${portString}`;
};
+147 -92
View File
@@ -1,103 +1,158 @@
'use strict';
// Dependencies.
const fs = require('fs-extra');
const path = require('path');
const glob = require('glob');
const { parallel } = require('async');
const { endsWith, get } = require('lodash');
const slash = require('slash');
// const glob = require('glob');
// const { parallel } = require('async');
const _ = require('lodash');
const glob = require('../load/glob');
const findPackagePath = require('../load/package-path');
module.exports = function() {
this.hook = {};
module.exports = async function({ installedHooks, installedPlugins, appPath }) {
let hooks = {};
return Promise.all([
new Promise((resolve, reject) => {
const cwd = this.config.appPath;
// Load configurations.
glob('./node_modules/*(strapi-hook-*)/*/*(index|defaults).*(js|json)', {
cwd
}, (err, files) => {
if (err) {
return reject(err);
}
mountHooks.call(this, files, cwd, 'node_modules')(resolve, reject);
});
}),
new Promise((resolve, reject) => {
const cwd = path.resolve(this.config.appPath, 'hooks');
// Load configurations.
glob('./*/*(index|defaults).*(js|json)', {
cwd
}, (err, files) => {
if (err) {
return reject(err);
}
mountHooks.call(this, files, cwd)(resolve, reject);
});
}),
new Promise((resolve, reject) => {
const cwd = path.resolve(this.config.appPath, 'plugins');
// Load configurations.
glob('./*/hooks/*/*(index|defaults).*(js|json)', {
cwd
}, (err, files) => {
if (err) {
return reject(err);
}
mountHooks.call(this, files, cwd, 'plugins')(resolve, reject);
});
})
await Promise.all([
loadHookDependencies(installedHooks, hooks),
// local middleware
loadHooksInDir(path.resolve(appPath, 'hooks'), hooks),
// plugins middlewares
loadPluginsHooks(installedPlugins, hooks),
// local plugin middlewares
loadLocalPluginsHooks(appPath, hooks),
]);
return hooks;
};
const mountHooks = function (files, cwd, source) {
return (resolve, reject) =>
parallel(
files.map(p => cb => {
const folders = p.replace(/^.\/node_modules\/strapi-hook-/, './')
.split('/');
const name = source === 'plugins' ? folders[folders.length - 2] : folders[1];
const loadHooksInDir = async (dir, hooks) => {
const files = await glob('*/*(index|defaults).*(js|json)', {
cwd: dir,
});
this.hook[name] = this.hook[name] || {
loaded: false
};
let dependencies = [];
if (source === 'node_modules') {
try {
dependencies = get(require(path.resolve(this.config.appPath, 'node_modules', `strapi-hook-${name}`, 'package.json')), 'strapi.dependencies', []);
} catch(err) {
// Silent
}
}
if (endsWith(p, 'index.js') && !this.hook[name].load) {
// Lazy loading.
Object.defineProperty(this.hook[name], 'load', {
configurable: false,
enumerable: true,
get: () => require(path.resolve(cwd, p)),
dependencies
});
this.hook[name].dependencies = dependencies;
} else if (endsWith(p, 'defaults.json')) {
this.hook[name].defaults = require(path.resolve(cwd, p));
}
cb();
}),
(err) => {
if (err) {
return reject(err);
}
resolve();
}
);
files.forEach(f => {
const name = slash(f).split('/')[0];
mountHooks(name, [path.resolve(dir, f)], hooks);
});
};
const loadPluginsHooks = async (plugins, hooks) => {
for (let pluginName of plugins) {
const dir = path.resolve(findPackagePath(pluginName), 'hooks');
await loadHooksInDir(dir, hooks);
}
};
const loadLocalPluginsHooks = async (appPath, hooks) => {
const pluginsFolder = path.resolve(appPath, 'plugins');
const pluginsFolders = await fs.readdir(pluginsFolder);
for (let pluginFolder of pluginsFolders) {
const dir = path.resolve(pluginsFolder, pluginFolder, 'hooks');
await loadHooksInDir(dir, hooks);
}
};
const loadHookDependencies = async (installedHooks, hooks) => {
for (let hook of installedHooks) {
const hookDir = path.dirname(require.resolve(hook));
const files = await glob('*(index|defaults).*(js|json)', {
cwd: hookDir,
absolute: true,
});
mountHooks(hook.substring('strapi-hook-'.length), files, hooks);
}
};
const mountHooks = (name, files, hooks) => {
files.forEach(file => {
hooks[name] = hooks[name] || { loaded: false };
let dependencies = [];
try {
dependencies = _.get(
require(`strapi-hook-${name}/package.json`),
'strapi.dependencies',
[]
);
} catch (err) {
// Silent
}
if (_.endsWith(file, 'index.js') && !hooks[name].load) {
Object.defineProperty(hooks[name], 'load', {
configurable: false,
enumerable: true,
get: () => require(file),
});
hooks[name].dependencies = dependencies;
return;
}
if (_.endsWith(file, 'defaults.json')) {
hooks[name].defaults = require(file);
return;
}
});
};
// const mountHooks = function(files, cwd, source) {
// return (resolve, reject) =>
// parallel(
// files.map(p => cb => {
// const folders = p
// .replace(/^.\/node_modules\/strapi-hook-/, './')
// .split('/');
// const name =
// source === 'plugins' ? folders[folders.length - 2] : folders[1];
// this.hook[name] = this.hook[name] || {
// loaded: false,
// };
// let dependencies = [];
// if (source === 'node_modules') {
// try {
// dependencies = get(
// require(path.resolve(
// this.config.appPath,
// 'node_modules',
// `strapi-hook-${name}`,
// 'package.json'
// )),
// 'strapi.dependencies',
// []
// );
// } catch (err) {
// // Silent
// }
// }
// if (endsWith(p, 'index.js') && !this.hook[name].load) {
// // Lazy loading.
// Object.defineProperty(this.hook[name], 'load', {
// configurable: false,
// enumerable: true,
// get: () => require(path.resolve(cwd, p)),
// dependencies,
// });
// this.hook[name].dependencies = dependencies;
// } else if (endsWith(p, 'defaults.json')) {
// this.hook[name].defaults = require(path.resolve(cwd, p));
// }
// cb();
// }),
// err => {
// if (err) {
// return reject(err);
// }
// resolve();
// }
// );
// };
+9 -9
View File
@@ -1,20 +1,20 @@
'use strict';
const { nested, app } = require('./configurations');
const apis = require('./apis');
const middlewares = require('./middlewares');
const hooks = require('./hooks');
const { loadConfigs, app } = require('./configurations');
const loadApis = require('./apis');
const loadMiddlewares = require('./middlewares');
const loadHooks = require('./hooks');
const plugins = require('./plugins');
const admin = require('./admin');
const store = require('./store');
module.exports = {
nestedConfigurations: nested,
loadConfigs,
loadMiddlewares,
loadHooks,
loadApis,
appConfigurations: app,
apis,
middlewares,
hooks,
plugins,
admin,
store
store,
};
+105 -172
View File
@@ -1,189 +1,122 @@
'use strict';
// Dependencies.
const fs = require('fs-extra');
const path = require('path');
const glob = require('glob');
const { parallel } = require('async');
const { upperFirst, lowerFirst, endsWith } = require('lodash');
const slash = require('slash');
const _ = require('lodash');
const glob = require('../load/glob');
const findPackagePath = require('../load/package-path');
module.exports = function() {
this.middleware = {};
this.koaMiddlewares = {};
const MIDDLEWARE_PREFIX = 'strapi-middleware';
return Promise.all([
new Promise((resolve, reject) => {
const cwd = path.resolve(__dirname, '..', '..');
const requiredMiddlewares = {
kcors: 'kcors',
body: 'koa-body',
compose: 'koa-compose',
compress: 'koa-compress',
convert: 'koa-convert',
favicon: 'koa-favicon',
i18n: 'koa-i18n',
ip: 'koa-ip',
locale: 'koa-locale',
lusca: 'koa-lusca',
routerJoi: 'koa-router-joi',
session: 'koa-session',
static: 'koa-static',
};
glob(
'./node_modules/*(koa-*|kcors)',
{
cwd
},
(err, files) => {
if (err) {
return reject(err);
}
module.exports = async function(config) {
const { installedMiddlewares, installedPlugins, appPath } = config;
requireMiddlewares.call(this, files, cwd)(resolve, reject);
}
);
}),
new Promise((resolve, reject) => {
const cwd = this.config.appPath;
let middlewares = {};
let koaMiddlewares = {};
glob(
'./node_modules/*(koa-*|kcors)',
{
cwd
},
(err, files) => {
if (err) {
return reject(err);
}
Object.keys(requiredMiddlewares).forEach(key => {
Object.defineProperty(koaMiddlewares, key, {
configurable: false,
enumerable: true,
get: () => require(requiredMiddlewares[key]),
});
});
requireMiddlewares.call(this, files, cwd)(resolve, reject);
}
);
}),
new Promise((resolve, reject) => {
const cwd = this.config.appPath;
glob(
'./node_modules/*(strapi-middleware-*)/*/*(index|defaults).*(js|json)',
{
cwd
},
(err, files) => {
if (err) {
return reject(err);
}
mountMiddlewares.call(this, files, cwd)(resolve, reject);
}
);
}),
new Promise((resolve, reject) => {
const cwd = path.resolve(__dirname, '..', 'middlewares');
glob(
'./*/*(index|defaults).*(js|json)',
{
cwd
},
(err, files) => {
if (err) {
return reject(err);
}
mountMiddlewares.call(this, files, cwd)(resolve, reject);
}
);
}),
new Promise((resolve, reject) => {
const cwd = path.resolve(this.config.appPath, 'middlewares');
glob(
'./*/*(index|defaults).*(js|json)',
{
cwd
},
(err, files) => {
if (err) {
return reject(err);
}
mountMiddlewares.call(this, files, cwd)(resolve, reject);
}
);
}),
new Promise((resolve, reject) => {
const cwd = path.resolve(this.config.appPath, 'plugins');
glob(
'./*/middlewares/*/*(index|defaults).*(js|json)',
{
cwd
},
(err, files) => {
if (err) {
return reject(err);
}
mountMiddlewares.call(this, files, cwd, true)(resolve, reject);
}
);
})
await Promise.all([
loadMiddlewareDependencies(installedMiddlewares, middlewares),
// internal middlewares
loadMiddlewaresInDir(
path.resolve(__dirname, '..', 'middlewares'),
middlewares
),
// local middleware
loadMiddlewaresInDir(path.resolve(appPath, 'middlewares'), middlewares),
// plugins middlewares
loadPluginsMiddlewares(installedPlugins, middlewares),
// local plugin middlewares
loadLocalPluginsMiddlewares(appPath, middlewares),
]);
return {
middlewares,
koaMiddlewares,
};
};
const requireMiddlewares = function (files, cwd) {
return (resolve, reject) =>
parallel(
files.map(p => cb => {
const extractStr = p
.split('/')
.pop()
.replace(/^koa(-|\.)/, '')
.split('-');
const loadMiddlewaresInDir = async (dir, middlewares) => {
const files = await glob('*/*(index|defaults).*(js|json)', {
cwd: dir,
});
const name = lowerFirst(
extractStr.length === 1
? extractStr[0]
: extractStr.map(p => upperFirst(p)).join('')
);
// Lazy loading.
if (!this.koaMiddlewares.hasOwnProperty(name)) {
Object.defineProperty(this.koaMiddlewares, name, {
configurable: false,
enumerable: true,
get: () => require(path.resolve(cwd, p))
});
}
cb();
}),
err => {
if (err) {
return reject(err);
}
resolve();
}
);
files.forEach(f => {
const name = slash(f).split('/')[0];
mountMiddleware(name, [path.resolve(dir, f)], middlewares);
});
};
const mountMiddlewares = function (files, cwd, isPlugin) {
return (resolve, reject) =>
parallel(
files.map(p => cb => {
const folders = p.replace(/^.\/node_modules\/strapi-middleware-/, './')
.split('/');
const name = isPlugin ? folders[folders.length - 2] : folders[1];
this.middleware[name] = this.middleware[name] || {
loaded: false
};
if (endsWith(p, 'index.js') && !this.middleware[name].load) {
// Lazy loading.
Object.defineProperty(this.middleware[name], 'load', {
configurable: false,
enumerable: true,
get: () => require(path.resolve(cwd, p))(this)
});
} else if (endsWith(p, 'defaults.json')) {
this.middleware[name].defaults = require(path.resolve(cwd, p));
}
cb();
}),
err => {
if (err) {
return reject(err);
}
resolve();
}
);
const loadPluginsMiddlewares = async (plugins, middlewares) => {
for (let pluginName of plugins) {
const dir = path.resolve(findPackagePath(pluginName), 'middlewares');
await loadMiddlewaresInDir(dir, middlewares);
}
};
const loadLocalPluginsMiddlewares = async (appPath, middlewares) => {
const pluginsFolder = path.resolve(appPath, 'plugins');
const pluginsFolders = await fs.readdir(pluginsFolder);
for (let pluginFolder of pluginsFolders) {
const dir = path.resolve(pluginsFolder, pluginFolder, 'middlewares');
await loadMiddlewaresInDir(dir, middlewares);
}
};
const loadMiddlewareDependencies = async (packages, middlewares) => {
for (let packageName of packages) {
const baseDir = path.dirname(require.resolve(packageName));
const files = await glob('*(index|defaults).*(js|json)', {
cwd: baseDir,
absolute: true,
});
const name = packageName.substring(MIDDLEWARE_PREFIX.length + 1);
mountMiddleware(name, files, middlewares);
}
};
const mountMiddleware = (name, files, middlewares) => {
files.forEach(file => {
middlewares[name] = middlewares[name] || { loaded: false };
if (_.endsWith(file, 'index.js') && !middlewares[name].load) {
return Object.defineProperty(middlewares[name], 'load', {
configurable: false,
enumerable: true,
get: () => require(file)(strapi),
});
}
if (_.endsWith(file, 'defaults.json')) {
middlewares[name].defaults = require(file);
return;
}
});
};
+1 -11
View File
@@ -3,14 +3,4 @@
// Starting date
global.startedAt = Date.now();
/**
* Instantiate and expose a Strapi singleton
* (maintains legacy support).
*/
module.exports = function(global) {
try {
return global.strapi = require('./Strapi'); // Strapi instance instanciated
} catch (error) {
console.error(error);
}
}.call(this, global);
module.exports = global.strapi = require('./Strapi'); // Strapi instance instanciated
+70
View File
@@ -0,0 +1,70 @@
const path = require('path');
const slash = require('slash');
const _ = require('lodash');
const requireFile = require('./require-file');
const glob = require('./glob');
const setValue = (obj, rootPath, source) => {
if (rootPath === null) {
return _.assign(obj, source);
}
const propPath = slash(rootPath.toLowerCase()).split('/');
if (propPath.length === 0) {
return _.assign(obj, source);
}
_.setWith(obj, propPath, source, Object);
};
const prefixedPath = [
...['staging', 'production', 'development'].reduce((acc, env) => {
return acc.concat(
`environments/${env}/database`,
`environments/${env}/security`,
`environments/${env}/request`,
`environments/${env}/response`,
`environments/${env}/server`
);
}, []),
'functions',
'policies',
'locales',
'hook',
'middleware',
'language',
'queries',
'layout',
];
/**
* Loads app config from a dir
* @param {Object} options - Options
* @param {string} options.dir - config dir to load
*/
module.exports = async dir => {
let root = {};
const files = await glob('**/*.+(js|json)', {
cwd: dir,
});
files.forEach(file => {
const m = requireFile(path.resolve(dir, file));
if (_.some(prefixedPath, e => slash(file).startsWith(e))) {
const rootPath = path.join(
path.dirname(file),
path.basename(file, path.extname(file))
);
setValue(root, rootPath, m);
} else {
const rootPath = path.dirname(file);
setValue(root, rootPath === '.' ? null : rootPath, m);
}
});
return root;
};
+10
View File
@@ -0,0 +1,10 @@
const glob = require('glob');
module.exports = (...args) => {
return new Promise((resolve, reject) => {
glob(...args, (err, files) => {
if (err) return reject(err);
resolve(files);
});
});
};
+4
View File
@@ -0,0 +1,4 @@
const path = require('path');
module.exports = moduleName =>
path.dirname(require.resolve(`${moduleName}/package.json`));
+13
View File
@@ -0,0 +1,13 @@
const path = require('path');
const { templateConfiguration } = require('strapi-utils');
/**
* Requires a file and eval expression if it is a json
* @param {string} filePath - file path
*/
module.exports = filePath => {
if (path.extname(filePath) === '.json') {
return templateConfiguration(require(filePath));
}
return require(filePath);
};
@@ -25,6 +25,7 @@ module.exports = strapi => function routerChecker(value, endpoint, plugin) {
: strapi.controllers[handler[0].toLowerCase()] ||
strapi.admin.controllers[handler[0].toLowerCase()];
const action = controller[handler[1]];
// Retrieve the API's name where the controller is located
+19 -123
View File
@@ -23,134 +23,30 @@ module.exports = {
}
},
loadFile: function(url) {
// Clear cache.
delete require.cache[require.resolve(path.resolve(this.config.appPath, url))];
// Require without cache.
return require(path.resolve(this.config.appPath, url));
},
setConfig: function(ctx, path, type, loader) {
const objPath = type === 'optional'
? this.optionalPath(path)
: this.aggregatePath(path);
// Load value.
const value = loader(path);
// Merge doesn't work for none-object value and function.
const obj = isObject(value) && !isFunction(value) ? merge(get(ctx, objPath), value) : value;
// Assignation.
return setWith(ctx, objPath, obj, Object);
},
setConfigAdmin: function(ctx, path, type, loader) {
const objPath = 'admin.' + (type === 'optional'
? this.optionalPath(path)
: this.aggregatePath(path));
// Direct assignation.
if (objPath.split('.').length === 1) {
return setWith(
ctx,
objPath,
merge(get(ctx, objPath), loader(path)),
Object
);
}
// Nested assignation.
return setWith(ctx, objPath, loader(path), Object);
},
optionalPath: path => {
return path
.replace(/(\.settings|.json|.js)/g, '')
.split('/')
.slice(1, path.split('/').length - 1)
.join('.')
.toLowerCase();
},
aggregatePath: path => {
return path
.replace(/(\.settings|.json|.js)/g, '')
.split('/')
.slice(1)
.join('.')
.toLowerCase();
},
loadConfig: function(files, shouldBeAggregated = false) {
const aggregate = files.filter(p => {
if (shouldBeAggregated) {
return true;
}
if (intersection(p.split('/').map(p => p.replace('.json', '')), ['environments', 'database', 'security', 'request', 'response', 'server']).length === 2) {
return true;
}
if (
p.indexOf('config/functions') !== -1 ||
p.indexOf('config/policies') !== -1 ||
p.indexOf('config/locales') !== -1 ||
p.indexOf('config/hook') !== -1 ||
p.indexOf('config/middleware') !== -1 ||
p.indexOf('config/language') !== -1 ||
p.indexOf('config/queries') !== -1 ||
p.indexOf('config/layout') !== -1
) {
return true;
}
return false;
});
const optional = difference(files, aggregate);
return Promise.all([
new Promise((resolve, reject) => {
map(aggregate, p =>
module.exports.setConfig(this, p, 'aggregate', this.loadFile)
);
resolve();
}),
new Promise((resolve, reject) => {
map(optional, p =>
module.exports.setConfig(this, p, 'optional', this.loadFile)
);
resolve();
})
]);
},
usage: async function () {
async usage({ uuid }) {
try {
if (this.config.uuid) {
const publicKey = fs.readFileSync(path.resolve(__dirname, 'resources', 'key.pub'));
const options = { timeout: 1500 };
if (!uuid) return;
const [usage, signedHash, required] = await Promise.all([
fetch('https://strapi.io/assets/images/usage.gif', options),
fetch('https://strapi.io/hash.txt', options),
fetch('https://strapi.io/required.txt', options)
]).catch(err => {});
const publicKey = fs.readFileSync(path.resolve(__dirname, 'resources', 'key.pub'));
const options = { timeout: 1500 };
if (usage.status === 200 && signedHash.status === 200) {
const code = Buffer.from(await usage.text(), 'base64').toString();
const hash = crypto.createHash('sha512').update(code).digest('hex');
const dependencies = Buffer.from(await required.text(), 'base64').toString();
const [usage, signedHash, required] = await Promise.all([
fetch('https://strapi.io/assets/images/usage.gif', options),
fetch('https://strapi.io/hash.txt', options),
fetch('https://strapi.io/required.txt', options)
]).catch(err => {});
const verifier = crypto.createVerify('RSA-SHA256').update(hash);
if (usage.status === 200 && signedHash.status === 200) {
const code = Buffer.from(await usage.text(), 'base64').toString();
const hash = crypto.createHash('sha512').update(code).digest('hex');
const dependencies = Buffer.from(await required.text(), 'base64').toString();
if (verifier.verify(publicKey, await signedHash.text(), 'hex')) {
return new Promise(resolve => {
vm.runInNewContext(code)(this.config.uuid, exposer(dependencies), resolve);
});
}
const verifier = crypto.createVerify('RSA-SHA256').update(hash);
if (verifier.verify(publicKey, await signedHash.text(), 'hex')) {
return new Promise(resolve => {
vm.runInNewContext(code)(uuid, exposer(dependencies), resolve);
});
}
}
} catch (e) {
+1 -1
View File
@@ -18,7 +18,7 @@ const adminDirPath = path.join(process.cwd(), 'admin');
let packageManager;
try {
packageManager = require(path.resolve(process.cwd(), 'package')).strapi.packageManager;
packageManager = require(path.resolve(process.cwd(), 'package.json')).strapi.packageManager;
} catch (error) {
packageManager = 'npm';
}
+1
View File
@@ -62,6 +62,7 @@
"rimraf": "^2.6.2",
"semver": "^5.4.1",
"shelljs": "^0.8.3",
"slash": "^2.0.0",
"stack-trace": "0.0.10",
"strapi-generate": "3.0.0-alpha.25.2",
"strapi-generate-admin": "3.0.0-alpha.25.2",
+18557
View File
File diff suppressed because it is too large Load Diff