This commit is contained in:
Sergey Yarkov 2020-02-28 22:41:26 +03:00
commit 804ebbc5a7
85 changed files with 29006 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
node_modules

16
backend/.editorconfig Normal file
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

3
backend/.eslintignore Normal file
View File

@ -0,0 +1,3 @@
.cache
build
**/node_modules/**

27
backend/.eslintrc Normal file
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"]
}
}

112
backend/.gitignore vendored Normal file
View File

@ -0,0 +1,112 @@
############################
# 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
############################
# Strapi
############################
exports
.cache
build

3
backend/README.md Normal file
View File

@ -0,0 +1,3 @@
# Strapi application
A quick description of your strapi application

0
backend/api/.gitkeep Normal file
View File

View File

@ -0,0 +1,52 @@
{
"routes": [
{
"method": "GET",
"path": "/articles",
"handler": "article.find",
"config": {
"policies": []
}
},
{
"method": "GET",
"path": "/articles/count",
"handler": "article.count",
"config": {
"policies": []
}
},
{
"method": "GET",
"path": "/articles/:id",
"handler": "article.findOne",
"config": {
"policies": []
}
},
{
"method": "POST",
"path": "/articles",
"handler": "article.create",
"config": {
"policies": []
}
},
{
"method": "PUT",
"path": "/articles/:id",
"handler": "article.update",
"config": {
"policies": []
}
},
{
"method": "DELETE",
"path": "/articles/:id",
"handler": "article.delete",
"config": {
"policies": []
}
}
]
}

View File

@ -0,0 +1,8 @@
'use strict';
/**
* Read the documentation (https://strapi.io/documentation/3.0.0-beta.x/concepts/controllers.html#core-controllers)
* to customize this controller
*/
module.exports = {};

View File

@ -0,0 +1,55 @@
'use strict';
/**
* Lifecycle callbacks for the `article` model.
*/
module.exports = {
// Before saving a value.
// Fired before an `insert` or `update` query.
// beforeSave: async (model, attrs, options) => {},
// After saving a value.
// Fired after an `insert` or `update` query.
// afterSave: async (model, response, options) => {},
// Before fetching a value.
// Fired before a `fetch` operation.
// beforeFetch: async (model, columns, options) => {},
// After fetching a value.
// Fired after a `fetch` operation.
// afterFetch: async (model, response, options) => {},
// Before fetching all values.
// Fired before a `fetchAll` operation.
// beforeFetchAll: async (model, columns, options) => {},
// After fetching all values.
// Fired after a `fetchAll` operation.
// afterFetchAll: async (model, response, options) => {},
// Before creating a value.
// Fired before an `insert` query.
// beforeCreate: async (model, attrs, options) => {},
// After creating a value.
// Fired after an `insert` query.
// afterCreate: async (model, attrs, options) => {},
// Before updating a value.
// Fired before an `update` query.
// beforeUpdate: async (model, attrs, options) => {},
// After updating a value.
// Fired after an `update` query.
// afterUpdate: async (model, attrs, options) => {},
// Before destroying a value.
// Fired before a `delete` query.
// beforeDestroy: async (model, attrs, options) => {},
// After destroying a value.
// Fired after a `delete` query.
// afterDestroy: async (model, attrs, options) => {}
};

View File

@ -0,0 +1,35 @@
{
"connection": "default",
"collectionName": "articles",
"info": {
"name": "article"
},
"options": {
"increments": true,
"timestamps": true
},
"attributes": {
"title": {
"type": "string",
"required": true
},
"content": {
"type": "richtext",
"required": true
},
"image": {
"model": "file",
"via": "related",
"plugin": "upload",
"required": true
},
"published_at": {
"type": "date",
"required": true
},
"category": {
"model": "category",
"via": "articles"
}
}
}

View File

@ -0,0 +1,8 @@
'use strict';
/**
* Read the documentation (https://strapi.io/documentation/3.0.0-beta.x/concepts/services.html#core-services)
* to customize this service
*/
module.exports = {};

View File

@ -0,0 +1,52 @@
{
"routes": [
{
"method": "GET",
"path": "/categories",
"handler": "category.find",
"config": {
"policies": []
}
},
{
"method": "GET",
"path": "/categories/count",
"handler": "category.count",
"config": {
"policies": []
}
},
{
"method": "GET",
"path": "/categories/:id",
"handler": "category.findOne",
"config": {
"policies": []
}
},
{
"method": "POST",
"path": "/categories",
"handler": "category.create",
"config": {
"policies": []
}
},
{
"method": "PUT",
"path": "/categories/:id",
"handler": "category.update",
"config": {
"policies": []
}
},
{
"method": "DELETE",
"path": "/categories/:id",
"handler": "category.delete",
"config": {
"policies": []
}
}
]
}

View File

@ -0,0 +1,8 @@
'use strict';
/**
* Read the documentation (https://strapi.io/documentation/3.0.0-beta.x/concepts/controllers.html#core-controllers)
* to customize this controller
*/
module.exports = {};

View File

@ -0,0 +1,55 @@
'use strict';
/**
* Lifecycle callbacks for the `category` model.
*/
module.exports = {
// Before saving a value.
// Fired before an `insert` or `update` query.
// beforeSave: async (model, attrs, options) => {},
// After saving a value.
// Fired after an `insert` or `update` query.
// afterSave: async (model, response, options) => {},
// Before fetching a value.
// Fired before a `fetch` operation.
// beforeFetch: async (model, columns, options) => {},
// After fetching a value.
// Fired after a `fetch` operation.
// afterFetch: async (model, response, options) => {},
// Before fetching all values.
// Fired before a `fetchAll` operation.
// beforeFetchAll: async (model, columns, options) => {},
// After fetching all values.
// Fired after a `fetchAll` operation.
// afterFetchAll: async (model, response, options) => {},
// Before creating a value.
// Fired before an `insert` query.
// beforeCreate: async (model, attrs, options) => {},
// After creating a value.
// Fired after an `insert` query.
// afterCreate: async (model, attrs, options) => {},
// Before updating a value.
// Fired before an `update` query.
// beforeUpdate: async (model, attrs, options) => {},
// After updating a value.
// Fired after an `update` query.
// afterUpdate: async (model, attrs, options) => {},
// Before destroying a value.
// Fired before a `delete` query.
// beforeDestroy: async (model, attrs, options) => {},
// After destroying a value.
// Fired after a `delete` query.
// afterDestroy: async (model, attrs, options) => {}
};

View File

@ -0,0 +1,20 @@
{
"connection": "default",
"collectionName": "categories",
"info": {
"name": "category"
},
"options": {
"increments": true,
"timestamps": true
},
"attributes": {
"name": {
"type": "string"
},
"articles": {
"via": "category",
"collection": "article"
}
}
}

View File

@ -0,0 +1,8 @@
'use strict';
/**
* Read the documentation (https://strapi.io/documentation/3.0.0-beta.x/concepts/services.html#core-services)
* to customize this service
*/
module.exports = {};

View File

@ -0,0 +1,10 @@
{
"favicon": {
"path": "favicon.ico",
"maxAge": 86400000
},
"public": {
"path": "./public",
"maxAge": 60000
}
}

View File

@ -0,0 +1,3 @@
{
"myCustomConfiguration": "This configuration is accessible through strapi.config.myCustomConfiguration"
}

View File

@ -0,0 +1,3 @@
{
"myCustomConfiguration": "This configuration is accessible through strapi.config.environments.development.myCustomConfiguration"
}

View File

@ -0,0 +1,15 @@
{
"defaultConnection": "default",
"connections": {
"default": {
"connector": "bookshelf",
"settings": {
"client": "sqlite",
"filename": ".tmp/data.db"
},
"options": {
"useNullAsDefault": true
}
}
}
}

View File

@ -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
}
}

View File

@ -0,0 +1,12 @@
{
"gzip": {
"enabled": false
},
"responseTime": {
"enabled": false
},
"poweredBy": {
"enabled": true,
"value": "Strapi <strapi.io>"
}
}

View File

@ -0,0 +1,31 @@
{
"csp": {
"enabled": true,
"policy": ["block-all-mixed-content"]
},
"p3p": {
"enabled": false,
"value": ""
},
"hsts": {
"enabled": true,
"maxAge": 31536000,
"includeSubDomains": true
},
"xframe": {
"enabled": true,
"value": "SAMEORIGIN"
},
"xss": {
"enabled": true,
"mode": "block"
},
"cors": {
"enabled": true
},
"ip": {
"enabled": false,
"whiteList": [],
"blackList": []
}
}

View File

@ -0,0 +1,13 @@
{
"host": "localhost",
"port": 1337,
"proxy": {
"enabled": false
},
"cron": {
"enabled": false
},
"admin": {
"autoOpen": false
}
}

View File

@ -0,0 +1,3 @@
{
"myCustomConfiguration": "This configuration is accessible through strapi.config.environments.production.myCustomConfiguration"
}

View File

@ -0,0 +1,17 @@
{
"defaultConnection": "default",
"connections": {
"default": {
"connector": "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": {}
}
}
}

View File

@ -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
}
}

View File

@ -0,0 +1,12 @@
{
"gzip": {
"enabled": true
},
"responseTime": {
"enabled": false
},
"poweredBy": {
"enabled": true,
"value": "Strapi <strapi.io>"
}
}

View File

@ -0,0 +1,31 @@
{
"csp": {
"enabled": true,
"policy": ["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
},
"ip": {
"enabled": false,
"whiteList": [],
"blackList": []
}
}

View File

@ -0,0 +1,14 @@
{
"host": "localhost",
"port": "${process.env.PORT || 1337}",
"production": true,
"proxy": {
"enabled": false
},
"cron": {
"enabled": false
},
"admin": {
"autoOpen": false
}
}

View File

@ -0,0 +1,3 @@
{
"myCustomConfiguration": "This configuration is accessible through strapi.config.environments.staging.myCustomConfiguration"
}

View File

@ -0,0 +1,17 @@
{
"defaultConnection": "default",
"connections": {
"default": {
"connector": "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": {}
}
}
}

View File

@ -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
}
}

View File

@ -0,0 +1,12 @@
{
"gzip": {
"enabled": true
},
"responseTime": {
"enabled": false
},
"poweredBy": {
"enabled": true,
"value": "Strapi <strapi.io>"
}
}

View File

@ -0,0 +1,31 @@
{
"csp": {
"enabled": true,
"policy": ["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
},
"ip": {
"enabled": false,
"whiteList": [],
"blackList": []
}
}

View File

@ -0,0 +1,14 @@
{
"host": "localhost",
"port": "${process.env.PORT || 1337}",
"production": true,
"proxy": {
"enabled": false
},
"cron": {
"enabled": false
},
"admin": {
"autoOpen": false
}
}

13
backend/config/functions/bootstrap.js vendored Normal file
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.
*
* See more details here: https://strapi.io/documentation/3.0.0-beta.x/concepts/configurations.html#bootstrap
*/
module.exports = () => {};

View File

@ -0,0 +1,21 @@
'use strict';
/**
* Cron config that gives you an opportunity
* to run scheduled jobs.
*
* The cron format consists of:
* [SECOND (optional)] [MINUTE] [HOUR] [DAY OF MONTH] [MONTH OF YEAR] [DAY OF WEEK]
*
* See more details here: https://strapi.io/documentation/3.0.0-beta.x/concepts/configurations.html#cron-tasks
*/
module.exports = {
/**
* Simple example.
* Every monday at 1am.
*/
// '0 1 * * 1': () => {
//
// }
};

View File

@ -0,0 +1,5 @@
'use strict';
module.exports = async (/* ctx */) => {
// return ctx.notFound('My custom message 404');
};

10
backend/config/hook.json Normal file
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": []
}
}

View File

@ -0,0 +1,13 @@
{
"enabled": true,
"defaultLocale": "en_us",
"modes": [
"query",
"subdomain",
"cookie",
"header",
"url",
"tld"
],
"cookieName": "locale"
}

View File

@ -0,0 +1,3 @@
{
"welcome": "Vítejte"
}

View File

@ -0,0 +1,3 @@
{
"welcome": "Willkommen"
}

View File

@ -0,0 +1,3 @@
{
"welcome": "Welcome"
}

View File

@ -0,0 +1,3 @@
{
"welcome": "Bienvenido"
}

View File

@ -0,0 +1,3 @@
{
"welcome": "Bienvenue"
}

View File

@ -0,0 +1,3 @@
{
"welcome": "Benvenuto"
}

View File

@ -0,0 +1,3 @@
{
"welcome": "ようこそ"
}

View File

@ -0,0 +1,4 @@
{
"welcome": "Добро пожаловать"
}

View File

@ -0,0 +1,3 @@
{
"welcome": "Hoşgeldin"
}

View File

@ -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"
]
}
}

View File

View File

@ -0,0 +1,3 @@
{
"jwtSecret": "fc4be92f-25ac-4dfe-bac3-7b19917064c6"
}

BIN
backend/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

38
backend/package.json Normal file
View File

@ -0,0 +1,38 @@
{
"name": "backend",
"private": true,
"version": "0.1.0",
"description": "A Strapi application",
"scripts": {
"develop": "strapi develop",
"start": "strapi start",
"build": "strapi build",
"strapi": "strapi"
},
"devDependencies": {},
"dependencies": {
"knex": "<0.20.0",
"sqlite3": "latest",
"strapi": "3.0.0-beta.18.8",
"strapi-admin": "3.0.0-beta.18.8",
"strapi-connector-bookshelf": "3.0.0-beta.18.8",
"strapi-plugin-content-manager": "3.0.0-beta.18.8",
"strapi-plugin-content-type-builder": "3.0.0-beta.18.8",
"strapi-plugin-email": "3.0.0-beta.18.8",
"strapi-plugin-graphql": "3.0.0-beta.18.8",
"strapi-plugin-upload": "3.0.0-beta.18.8",
"strapi-plugin-users-permissions": "3.0.0-beta.18.8",
"strapi-utils": "3.0.0-beta.18.8"
},
"author": {
"name": "A Strapi developer"
},
"strapi": {
"uuid": "6eb87738-282f-42e3-b657-0006839e0a75"
},
"engines": {
"node": ">=10.0.0",
"npm": ">=6.0.0"
},
"license": "MIT"
}

56
backend/public/index.html Normal file
View File

@ -0,0 +1,56 @@
<!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" />
<meta name="robots" content="noindex">
<link href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css?family=Lato:400,700&display=swap" rel="stylesheet" />
<style>
*{-webkit-box-sizing:border-box;text-decoration:none}body,html{margin:0;padding:0;font-size:62.5%;-webkit-font-smoothing:antialiased}body{font-size:1.3rem;font-family:Lato,Helvetica,Arial,Verdana,sans-serif;background:#fafafb;margin:0;padding:80px 0;color:#333740;line-height:1.8rem}strong{font-weight:700}.wrapper{width:684px;margin:auto}h1{text-align:center}h2{font-size:1.8rem;font-weight:700;margin-bottom:1px}.logo{height:40px;margin-bottom:74px}.informations{position:relative;overflow:hidden;display:flex;justify-content:space-between;width:100%;height:126px;margin-top:18px;padding:20px 30px;background:#fff;border-radius:2px;box-shadow:0 2px 4px 0 #e3e9f3}.informations:before{position:absolute;top:0;left:0;content:'';display:block;width:100%;height:2px;background:#007eff}.environment{display:inline-block;padding:0 10px;height:20px;margin-bottom:36px;background:#e6f0fb;border:1px solid #aed4fb;border-radius:2px;text-transform:uppercase;color:#007eff;font-size:1.2rem;font-weight:700;line-height:20px;letter-spacing:.05rem}.cta{display:inline-block;height:30px;padding:0 15px;margin-top:32px;border-radius:2px;color:#fff;font-weight:700;line-height:28px}.cta i{position:relative;display:inline-block;height:100%;vertical-align:middle;font-size:1rem;margin-right:20px}.cta i:before{position:absolute;top:8px}.cta-primary{background:#007eff}.cta-secondary{background:#6dbb1a}.text-align-right{text-align:right}.lets-started{position:relative;overflow:hidden;width:100%;height:144px;margin-top:18px;padding:20px 30px;background:#fff;border-radius:2px;box-shadow:0 2px 4px 0 #e3e9f3}.people-saying-hello{position:absolute;right:30px;bottom:-8px;width:113px;height:70px}.visible{opacity:1!important}.people-saying-hello img{position:absolute;max-width:100%;opacity:0;transition:opacity .2s ease-out}@media only screen and (max-width:768px){.wrapper{width:auto!important;margin:0 20px}.informations{flex-direction:column;height:auto}.environment{width:100%;text-align:center;margin-bottom:18px}.text-align-right{margin-top:18px;text-align:center}.cta{width:100%;text-align:center}.lets-started{height:auto}.people-saying-hello{display:none}}
</style>
</head>
<body lang="en">
<section class="wrapper">
<h1><img class="logo" src="https://strapi.io/assets/images/logo_login.png" /></h1>
<% if (isInitialised) { %>
<div class="informations">
<div>
<span class="environment"><%= strapi.config.environment %></span>
<p>
The server is running successfully (<strong>v<%= strapi.config.info.version %>)</strong>
</p>
</div>
<div class="text-align-right">
<p><%= serverTime %></p>
<a class="cta cta-primary" href="<%= strapi.config.admin.url %>" target="_blank" title="Click to open the administration" ><i class="fas fa-external-link-alt"></i>Open the administration</a>
</div>
</div>
<% } %>
<% if (!isInitialised) { %>
<div class="lets-started">
<h2>Let's get started!</h2>
<p>To discover the power provided by Strapi, you need to create an administrator.</p>
<a class="cta cta-secondary" href="<%= strapi.config.admin.url %>" target="_blank" title="Click to create the first administration" ><i class="fas fa-external-link-alt"></i>Create the first administrator</a>
<div class="people-saying-hello">
<img class="visible" src="https://strapi.io/assets/images/group_people_1.png" alt="People saying hello" />
<img src="https://strapi.io/assets/images/group_people_2.png" alt="People saying hello" />
<img src="https://strapi.io/assets/images/group_people_3.png" alt="People saying hello" />
</div>
</div>
<% } %>
</section>
<script>
var images=document.querySelectorAll('.people-saying-hello img');var nextIndex=0;setInterval(function(){var currentIndex=0;images.forEach(function(image,index){if(image.className==='visible'){currentIndex=index}});nextIndex=currentIndex+1;if(nextIndex===images.length){nextIndex=0}
images.forEach(function(image){image.classList.remove('visible')})
images[nextIndex].classList.add('visible')},1500)
</script>
</body>
</html>

View File

@ -0,0 +1,30 @@
<!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" />
<meta name="robots" content="noindex">
<link href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css?family=Lato:400,700&display=swap" rel="stylesheet" />
<style>
*{-webkit-box-sizing:border-box;text-decoration:none}body,html{margin:0;padding:0;font-size:62.5%;-webkit-font-smoothing:antialiased}body{font-size:1.3rem;font-family:Lato,Helvetica,Arial,Verdana,sans-serif;background:#fafafb;margin:0;padding:80px 0;color:#333740;line-height:1.8rem}strong{font-weight:700}.wrapper{width:684px;margin:auto}h1{text-align:center}h2{font-size:1.8rem;font-weight:700;margin-bottom:1px}.logo{height:40px}.informations{position:relative;overflow:hidden;display:flex;justify-content:space-between;width:100%;height:126px;margin-top:92px;padding:20px 30px;background:#fff;border-radius:2px;box-shadow:0 2px 4px 0 #e3e9f3}.informations:before{position:absolute;top:0;left:0;content:'';display:block;width:100%;height:2px;background:#6dbb1a}.environment{display:inline-block;padding:0 10px;height:20px;margin-bottom:36px;background:#e9f5dd;border:1px solid #6dbb1a;border-radius:2px;text-transform:uppercase;color:#6dbb1a;font-size:1.2rem;font-weight:700;line-height:20px;letter-spacing:.05rem}.cta{display:inline-block;height:30px;padding:0 15px;margin-top:32px;border-radius:2px;color:#fff;font-weight:700;line-height:28px}.cta i{position:relative;display:inline-block;height:100%;vertical-align:middle;font-size:1rem;margin-right:20px}.cta i:before{position:absolute;top:8px}.cta-primary{background:#007eff}.cta-secondary{background:#}.text-align-right{text-align:right}@media only screen and (max-width:768px){.wrapper{width:auto!important;margin:0 20px}.informations{flex-direction:column;height:auto}.informations p{text-align:center}.environment{width:100%;text-align:center;margin-bottom:18px}.text-align-right{margin-top:18px;text-align:center}}
</style>
</head>
<body lang="en">
<section class="wrapper">
<h1><img class="logo" src="https://strapi.io/assets/images/logo_login.png" /></h1>
<div class="informations">
<div>
<span class="environment"><%= strapi.config.environment %></span>
<p>The server is running successfully.</p>
</div>
<div class="text-align-right">
<p><%= serverTime %></p>
</div>
</div>
</section>
</body>
</html>

View File

@ -0,0 +1,3 @@
# To prevent search engines from seeing the site altogether, uncomment the next two lines:
# User-Agent: *
# Disallow: /

View File

10218
backend/yarn.lock Normal file

File diff suppressed because it is too large Load Diff

25
frontend/.gitignore vendored Normal file
View File

@ -0,0 +1,25 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
.env*
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

30
frontend/README.md Normal file
View File

@ -0,0 +1,30 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/zeit/next.js/tree/canary/packages/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
```
Open [http://localhost:3000](http://localhost:3000) with your brSowser to see the result.
You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/zeit/next.js/) - your feedback and contributions are welcome!
## Deploy on ZEIT Now
The easiest way to deploy your Next.js app is to use the [ZEIT Now Platform](https://zeit.co/) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.

View File

@ -0,0 +1,23 @@
import gql from 'graphql-tag'
const ARTICLE_QUERY = gql`
query Article($id: ID!) {
article(id: $id) {
id
title
content
image {
url
}
category {
id
name
}
published_at
}
}
`
export default ARTICLE_QUERY

View File

@ -0,0 +1,21 @@
import gql from 'graphql-tag'
const ARTICLES_QUERY = gql`
query Articles {
articles {
id
title
category {
id
name
}
image {
url
}
}
}
`
export default ARTICLES_QUERY

View File

@ -0,0 +1,23 @@
import gql from 'graphql-tag';
const CATEGORY_ARTICLES_QUERY = gql`
query Category($id: ID!){
category(id: $id) {
name
articles {
id
title
content
image {
url
}
category {
id
name
}
}
}
}
`;
export default CATEGORY_ARTICLES_QUERY;

View File

@ -0,0 +1,14 @@
import gql from 'graphql-tag'
const CATEGORIES_QUERY = gql`
query Categories {
categories {
id
name
}
}
`
export default CATEGORIES_QUERY

View File

@ -0,0 +1,47 @@
@import "~nprogress/nprogress.css";
a {
text-decoration: none;
}
h1 {
font-family: Staatliches;
font-size: 120px;
}
#category {
font-family: Staatliches;
font-weight: 500;
}
#title {
letter-spacing: 0.4px;
font-size: 22px;
font-size: 1.375rem;
line-height: 1.13636;
}
#banner {
margin: 20px;
height: 800px;
}
#editor {
font-size: 16px;
font-size: 1rem;
line-height: 1.75;
}
.uk-navbar-container {
background: #fff !important;
font-family: Staatliches;
}
.uk-card-body {
padding: 15px 30px;
}
img:hover {
opacity: 1;
transition: opacity 0.25s cubic-bezier(0.39, 0.575, 0.565, 1);
}

View File

@ -0,0 +1,29 @@
import Card from "./card";
const Articles = ({ articles }) => {
console.log(articles)
const leftArticlesCount = Math.ceil(articles.length / 5);
const leftArticles = articles.slice(0, leftArticlesCount);
const rightArticles = articles.slice(leftArticlesCount, articles.length);
return (
<div>
<div className="uk-child-width-1-2" data-uk-grid>
<div>
{leftArticles.map((article, i) => {
return <Card article={article} key={`article__${article.id}`} />;
})}
</div>
<div>
<div className="uk-child-width-1-2@m uk-grid-match" data-uk-grid>
{rightArticles.map((article, i) => {
return <Card article={article} key={`article__${article.id}`} />;
})}
</div>
</div>
</div>
</div>
);
};
export default Articles;

View File

@ -0,0 +1,29 @@
import Link from "next/link";
const Card = ({ article }) => {
return (
<Link href='/articles/[id]' as={`/articles/${article.id}`}>
<a className="uk-link-reset">
<div className="uk-card uk-card-muted">
<div className="uk-card-media-top">
<img
src={process.env.API_URL + article.image.url}
alt={article.image.url}
height="100"
/>
</div>
<div className="uk-card-body">
<p id="category" className="uk-text-uppercase">
{article.category.name}
</p>
<p id="title" className="uk-text-large">
{article.title}
</p>
</div>
</div>
</a>
</Link>
);
};
export default Card;

View File

@ -0,0 +1,45 @@
import Link from "next/link"
import Query from "../components/query";
import CATEGORIES_QUERY from "../apollo/queries/category/categories.js";
const Nav = () => {
return (
<div>
<Query query={CATEGORIES_QUERY} id={null}>
{({ data: { categories } }) => {
return (
<div>
<nav className="uk-container uk-container-large uk-navbar-container" data-uk-navbar>
<div className="uk-navbar-left">
<ul className="uk-navbar-nav">
<li>
<Link href="/">
<a>Example Blog</a>
</Link>
</li>
</ul>
</div>
<div className="uk-navbar-right">
<ul className="uk-navbar-nav">
{categories.map((category, i) => {
return (
<li key={category.id}>
<Link href='/categories/[id]' as={`/categories/${category.id}`}>
<a className="uk-link-reset">{category.name}</a>
</Link>
</li>
);
})}
</ul>
</div>
</nav>
</div>
);
}}
</Query>
</div>
);
};
export default Nav;

View File

@ -0,0 +1,13 @@
import { useQuery } from '@apollo/react-hooks'
const Query = ({ children, query, id }) => {
const { data, loading, error } = useQuery(query, {
variables: {id}
})
if (loading) return <p>loading...</p>
if (error) return <p>Error: {JSON.stringify(error)}</p>
return children({ data })
}
export default Query

9
frontend/next.config.js Normal file
View File

@ -0,0 +1,9 @@
require("dotenv").config();
const withCSS = require('@zeit/next-css')
const withFonts = require('next-fonts')
module.exports = withCSS({
env: {
API_URL: process.env.API_URL
}
})

10351
frontend/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

30
frontend/package.json Normal file
View File

@ -0,0 +1,30 @@
{
"name": "frontend",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"dependencies": {
"@apollo/react-hooks": "^3.1.3",
"@zeit/next-css": "^1.0.1",
"apollo-cache-inmemory": "^1.6.5",
"apollo-client": "^2.6.8",
"apollo-link-http": "^1.5.16",
"dotenv": "^8.2.0",
"graphql": "^14.6.0",
"graphql-tag": "^2.10.3",
"isomorphic-unfetch": "^3.0.0",
"moment": "^2.24.0",
"next": "9.2.2",
"next-fonts": "^1.0.3",
"next-with-apollo": "^5.0.0",
"nprogress": "^0.2.0",
"react": "16.13.0",
"react-dom": "16.13.0",
"react-markdown": "^4.3.1",
"react-moment": "^0.9.7"
}
}

39
frontend/pages/_app.js Normal file
View File

@ -0,0 +1,39 @@
import Head from "next/head";
import NProgress from 'nprogress'
import Router from 'next/router'
import "../assets/css/style.css";
import { ApolloProvider } from "@apollo/react-hooks";
import withData from "../utils/apollo";
import Nav from '../components/nav'
Router.events.on('routeChangeStart', url => NProgress.start())
Router.events.on('routeChangeComplete', () => NProgress.done())
Router.events.on('routeChangeError', () => NProgress.done())
const App = ({ Component, pageProps, apollo }) => {
return (
<ApolloProvider client={apollo}>
<Head>
<title>Strapi blog</title>
<meta name="viewport" content="initial-scale=1.0, width=device-width" />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Staatliches"
/>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/uikit@3.2.3/dist/css/uikit.min.css"
/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/uikit/3.2.0/js/uikit.min.js" />
<script src="https://cdn.jsdelivr.net/npm/uikit@3.2.3/dist/js/uikit-icons.min.js" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/uikit/3.2.0/js/uikit.js" />
</Head>
<Nav />
<Component {...pageProps} />
</ApolloProvider>
)
};
// Wraps all components in the tree with the data provider
export default withData(App);

View File

@ -0,0 +1,39 @@
import { useRouter } from "next/router";
import Query from "../../components/query";
import ReactMarkdown from "react-markdown";
import Moment from "react-moment";
import ARTICLE_QUERY from "../../apollo/queries/article/article";
const Article = () => {
const router = useRouter();
return (
<Query query={ARTICLE_QUERY} id={router.query.id}>
{({ data: { article } }) => {
return (
<div>
<div
id="banner"
className="uk-height-medium uk-flex uk-flex-center uk-flex-middle uk-background-cover uk-light uk-padding uk-margin"
data-src={process.env.API_URL + article.image.url}
data-srcset={process.env.API_URL + article.image.url}
data-uk-img
>
<h1>{article.title}</h1>
</div>
<div className="uk-section">
<div className="uk-container uk-container-small">
<ReactMarkdown source={article.content} />
<p>
<Moment format="MMM Do YYYY">{article.published_at}</Moment>
</p>
</div>
</div>
</div>
);
}}
</Query>
);
};
export default Article;

View File

@ -0,0 +1,27 @@
import { useRouter } from "next/router";
import Articles from "../../components/articles";
import Query from "../../components/query";
import CATEGORY_ARTICLES_QUERY from "../../apollo/queries/category/articles";
const Category = () => {
const router = useRouter();
return (
<Query query={CATEGORY_ARTICLES_QUERY} id={router.query.id}>
{({ data: { category } }) => {
return (
<div>
<div className="uk-section">
<div className="uk-container uk-container-large">
<h1>{category.name}</h1>
<Articles articles={category.articles} />
</div>
</div>
</div>
);
}}
</Query>
);
};
export default Category

22
frontend/pages/index.js Normal file
View File

@ -0,0 +1,22 @@
import Articles from "../components/articles";
import Query from "../components/query";
import ARTICLES_QUERY from "../apollo/queries/article/articles";
const Home = () => {
return (
<div>
<div className="uk-section">
<div className="uk-container uk-container-large">
<h1>Example Blog</h1>
<Query query={ARTICLES_QUERY}>
{({ data: { articles } }) => {
return <Articles articles={articles} />;
}}
</Query>
</div>
</div>
</div>
);
};
export default Home

BIN
frontend/public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

10
frontend/public/zeit.svg Normal file
View File

@ -0,0 +1,10 @@
<svg width="82" height="16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill="url(#prefix__paint0_linear)" d="M9.018 0l9.019 16H0L9.018 0z"/>
<path fill="#333" fill-rule="evenodd" d="M51.634 12.028h-6.492V2.052h6.492v1.256H46.61v3.007h4.37V7.57h-4.37v3.202h5.024v1.255zm-14.063 0h-7.235v-1.096l5.342-7.624h-5.253V2.052h7.058v1.097l-5.342 7.623h5.43v1.256zm21.88 0h6.333v-1.256h-2.423V3.308h2.423V2.052h-6.332v1.256h2.441v7.465h-2.441v1.255zm18.22 0h-1.468v-8.72h-3.36V2.052h8.225v1.256H77.67v8.72z" clip-rule="evenodd"/>
<defs>
<linearGradient id="prefix__paint0_linear" x1="28.022" x2="16.189" y1="22.991" y2="8.569" gradientUnits="userSpaceOnUse">
<stop stop-color="#fff"/>
<stop offset="1"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 794 B

22
frontend/utils/apollo.js Normal file
View File

@ -0,0 +1,22 @@
import { ApolloClient } from 'apollo-client'
import { InMemoryCache } from 'apollo-cache-inmemory'
import withApollo from 'next-with-apollo'
import { createHttpLink } from 'apollo-link-http'
import fetch from 'isomorphic-unfetch'
const GRAPHQL_URL = process.env.BACKEND_URL || 'http://localhost:1337/graphql'
const link = new createHttpLink({
fetch,
uri: GRAPHQL_URL
})
export default withApollo(
({initialState}) =>
new ApolloClient({
link,
cache: new InMemoryCache()
.restore(initialState || {})
})
)

6523
frontend/yarn.lock Normal file

File diff suppressed because it is too large Load Diff

391
package-lock.json generated Normal file
View File

@ -0,0 +1,391 @@
{
"name": "Example blog",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"ansi-regex": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
},
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"requires": {
"color-convert": "^1.9.0"
}
},
"camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
},
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
},
"dependencies": {
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"requires": {
"has-flag": "^3.0.0"
}
}
}
},
"cliui": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
"integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
"requires": {
"string-width": "^3.1.0",
"strip-ansi": "^5.2.0",
"wrap-ansi": "^5.1.0"
}
},
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"requires": {
"color-name": "1.1.3"
}
},
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"concurrently": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/concurrently/-/concurrently-5.1.0.tgz",
"integrity": "sha512-9ViZMu3OOCID3rBgU31mjBftro2chOop0G2u1olq1OuwRBVRw/GxHTg80TVJBUTJfoswMmEUeuOg1g1yu1X2dA==",
"requires": {
"chalk": "^2.4.2",
"date-fns": "^2.0.1",
"lodash": "^4.17.15",
"read-pkg": "^4.0.1",
"rxjs": "^6.5.2",
"spawn-command": "^0.0.2-1",
"supports-color": "^6.1.0",
"tree-kill": "^1.2.2",
"yargs": "^13.3.0"
}
},
"date-fns": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.10.0.tgz",
"integrity": "sha512-EhfEKevYGWhWlZbNeplfhIU/+N+x0iCIx7VzKlXma2EdQyznVlZhCptXUY+BegNpPW2kjdx15Rvq503YcXXrcA=="
},
"decamelize": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
},
"emoji-regex": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
"integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA=="
},
"error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
"requires": {
"is-arrayish": "^0.2.1"
}
},
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
},
"find-up": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
"requires": {
"locate-path": "^3.0.0"
}
},
"get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
},
"hosted-git-info": {
"version": "2.8.7",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.7.tgz",
"integrity": "sha512-ChkjQtKJ3GI6SsI4O5jwr8q8EPrWCnxuc4Tbx+vRI5x6mDOpjKKltNo1lRlszw3xwgTOSns1ZRBiMmmwpcvLxg=="
},
"is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
},
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
},
"json-parse-better-errors": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
"integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
},
"locate-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
"requires": {
"p-locate": "^3.0.0",
"path-exists": "^3.0.0"
}
},
"lodash": {
"version": "4.17.15",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
},
"normalize-package-data": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
"integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
"requires": {
"hosted-git-info": "^2.1.4",
"resolve": "^1.10.0",
"semver": "2 || 3 || 4 || 5",
"validate-npm-package-license": "^3.0.1"
}
},
"p-limit": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz",
"integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==",
"requires": {
"p-try": "^2.0.0"
}
},
"p-locate": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
"requires": {
"p-limit": "^2.0.0"
}
},
"p-try": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
},
"parse-json": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
"integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
"requires": {
"error-ex": "^1.3.1",
"json-parse-better-errors": "^1.0.1"
}
},
"path-exists": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
},
"path-parse": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw=="
},
"pify": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
},
"read-pkg": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz",
"integrity": "sha1-ljYlN48+HE1IyFhytabsfV0JMjc=",
"requires": {
"normalize-package-data": "^2.3.2",
"parse-json": "^4.0.0",
"pify": "^3.0.0"
}
},
"require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
},
"require-main-filename": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
},
"resolve": {
"version": "1.15.1",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz",
"integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==",
"requires": {
"path-parse": "^1.0.6"
}
},
"rxjs": {
"version": "6.5.4",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz",
"integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==",
"requires": {
"tslib": "^1.9.0"
}
},
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
},
"set-blocking": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
},
"spawn-command": {
"version": "0.0.2-1",
"resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz",
"integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A="
},
"spdx-correct": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
"integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==",
"requires": {
"spdx-expression-parse": "^3.0.0",
"spdx-license-ids": "^3.0.0"
}
},
"spdx-exceptions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz",
"integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA=="
},
"spdx-expression-parse": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
"integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
"requires": {
"spdx-exceptions": "^2.1.0",
"spdx-license-ids": "^3.0.0"
}
},
"spdx-license-ids": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
"integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q=="
},
"string-width": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
"requires": {
"emoji-regex": "^7.0.1",
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^5.1.0"
}
},
"strip-ansi": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
"requires": {
"ansi-regex": "^4.1.0"
}
},
"supports-color": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
"integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
"requires": {
"has-flag": "^3.0.0"
}
},
"tree-kill": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
"integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="
},
"tslib": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
"integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA=="
},
"validate-npm-package-license": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
"integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
"requires": {
"spdx-correct": "^3.0.0",
"spdx-expression-parse": "^3.0.0"
}
},
"which-module": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
},
"wrap-ansi": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
"integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
"requires": {
"ansi-styles": "^3.2.0",
"string-width": "^3.0.0",
"strip-ansi": "^5.0.0"
}
},
"y18n": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
},
"yargs": {
"version": "13.3.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz",
"integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==",
"requires": {
"cliui": "^5.0.0",
"find-up": "^3.0.0",
"get-caller-file": "^2.0.1",
"require-directory": "^2.1.1",
"require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0",
"string-width": "^3.0.0",
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^13.1.1"
}
},
"yargs-parser": {
"version": "13.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz",
"integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==",
"requires": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
}
}
}
}

14
package.json Normal file
View File

@ -0,0 +1,14 @@
{
"name": "example-blog",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "concurrently \"yarn --cwd ./backend/ develop\" \"yarn --cwd ./frontend/ dev\""
},
"author": "",
"license": "ISC",
"dependencies": {
"concurrently": "^5.1.0"
}
}