Merge branch 'master' into chore/routing-x-forwarded

This commit is contained in:
Alexandre BODIN 2019-09-18 13:27:39 +02:00 committed by GitHub
commit 7a94d9dad9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
102 changed files with 460 additions and 336 deletions

View File

@ -42,6 +42,7 @@ module.exports = {
rules: {
'generator-star-spacing': 0,
'no-console': 0,
'require-atomic-updates': 0,
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
},

View File

@ -71,6 +71,8 @@ jobs:
- <<: *e2e_tests
name: 'E2E Mysql'
before_install:
- sudo cp $TRAVIS_BUILD_DIR/_travis/mysql.cnf /etc/mysql/conf.d/
- sudo service mysql restart
- mysql -e 'CREATE DATABASE strapi_test;'
env:
- DB_STRING='--dbclient=mysql --dbhost=localhost --dbport=3306 --dbname=strapi_test --dbusername=travis --dbpassword='

3
_travis/mysql.cnf Normal file
View File

@ -0,0 +1,3 @@
[mysqld]
collation-server=utf8_unicode_ci
character-set-server=utf8

View File

@ -23,6 +23,9 @@
"group": "dish",
"type": "group",
"repeatable": true
},
"menu": {
"model": "menu"
}
}
}

View File

@ -14,6 +14,12 @@
},
"price": {
"type": "float"
},
"picture": {
"model": "file",
"via": "related",
"plugin": "upload",
"required": false
}
}
}

View File

@ -1,7 +1,7 @@
{
"name": "getstarted",
"private": true,
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "A Strapi application.",
"scripts": {
"develop": "strapi develop",
@ -15,23 +15,23 @@
"mysql": "^2.17.1",
"pg": "^7.10.0",
"sqlite3": "^4.0.6",
"strapi": "3.0.0-beta.16.3",
"strapi-admin": "3.0.0-beta.16.3",
"strapi-hook-bookshelf": "3.0.0-beta.16.3",
"strapi-hook-knex": "3.0.0-beta.16.3",
"strapi-hook-mongoose": "3.0.0-beta.16.3",
"strapi-middleware-views": "3.0.0-beta.16.3",
"strapi-plugin-content-manager": "3.0.0-beta.16.3",
"strapi-plugin-content-type-builder": "3.0.0-beta.16.3",
"strapi-plugin-documentation": "3.0.0-beta.16.3",
"strapi-plugin-email": "3.0.0-beta.16.3",
"strapi-plugin-graphql": "3.0.0-beta.16.3",
"strapi-plugin-settings-manager": "3.0.0-beta.16.3",
"strapi-plugin-upload": "3.0.0-beta.16.3",
"strapi-plugin-users-permissions": "3.0.0-beta.16.3",
"strapi-provider-email-mailgun": "3.0.0-beta.16.3",
"strapi-provider-upload-aws-s3": "3.0.0-beta.16.3",
"strapi-utils": "3.0.0-beta.16.3"
"strapi": "3.0.0-beta.16.4",
"strapi-admin": "3.0.0-beta.16.4",
"strapi-hook-bookshelf": "3.0.0-beta.16.4",
"strapi-hook-knex": "3.0.0-beta.16.4",
"strapi-hook-mongoose": "3.0.0-beta.16.4",
"strapi-middleware-views": "3.0.0-beta.16.4",
"strapi-plugin-content-manager": "3.0.0-beta.16.4",
"strapi-plugin-content-type-builder": "3.0.0-beta.16.4",
"strapi-plugin-documentation": "3.0.0-beta.16.4",
"strapi-plugin-email": "3.0.0-beta.16.4",
"strapi-plugin-graphql": "3.0.0-beta.16.4",
"strapi-plugin-settings-manager": "3.0.0-beta.16.4",
"strapi-plugin-upload": "3.0.0-beta.16.4",
"strapi-plugin-users-permissions": "3.0.0-beta.16.4",
"strapi-provider-email-mailgun": "3.0.0-beta.16.4",
"strapi-provider-upload-aws-s3": "3.0.0-beta.16.4",
"strapi-utils": "3.0.0-beta.16.4"
},
"strapi": {
"uuid": "getstarted"

View File

@ -1,5 +1,5 @@
{
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"packages": [
"packages/*",
"examples/*"

View File

@ -3,25 +3,25 @@
"dependencies": {},
"devDependencies": {
"@testing-library/jest-dom": "^4.0.0",
"@testing-library/react": "^9.1.1",
"@testing-library/react-hooks": "^2.0.1",
"babel-eslint": "^10.0.1",
"@testing-library/react": "^9.1.0",
"@testing-library/react-hooks": "^2.0.0",
"babel-eslint": "^10.0.0",
"cross-env": "^5.2.0",
"cypress": "3.1.2",
"enzyme": "^3.9.0",
"enzyme-adapter-react-16": "^1.12.1",
"eslint": "^5.16.0",
"eslint-config-prettier": "^6.0.0",
"eslint": "^6.3.0",
"eslint-config-prettier": "^6.2.0",
"eslint-plugin-react": "^7.14.0",
"eslint-plugin-react-hooks": "^1.6.1",
"eslint-plugin-redux-saga": "^1.0.0",
"eslint-plugin-react-hooks": "^2.0.0",
"eslint-plugin-redux-saga": "^1.1.0",
"execa": "^1.0.0",
"husky": "^3.0.0",
"istanbul": "~0.4.2",
"jest": "^24.5.0",
"jest-cli": "^24.5.0",
"lerna": "^3.13.1",
"lint-staged": "^9.1.0",
"lint-staged": "^9.2.0",
"npm-run-all": "^4.1.5",
"prettier": "^1.18.2",
"react-test-renderer": "^16.9.0",

View File

@ -1,6 +1,6 @@
{
"name": "create-strapi-app",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Generate a new Strapi application.",
"license": "MIT",
"homepage": "http://strapi.io",
@ -21,7 +21,7 @@
],
"dependencies": {
"commander": "^2.20.0",
"strapi-generate-new": "3.0.0-beta.16.3"
"strapi-generate-new": "3.0.0-beta.16.4"
},
"scripts": {
"test": "echo \"no tests yet\""

View File

@ -177,7 +177,7 @@ if (NODE_ENV !== 'test') {
import('intl/locale-data/jsonp/en.js'),
import('intl/locale-data/jsonp/de.js'),
])
) // eslint-disable-line prettier/prettier
)
.then(() => render(translationMessages))
.catch(err => {
throw err;

View File

@ -15,7 +15,6 @@ import Reddit from '../../assets/images/social_reddit.png';
import { SocialLinkWrapper } from './components';
/* eslint-disable jsx-a11y/alt-text */
function getSrc(name) {
switch (name) {
case 'GitHub':

View File

@ -92,7 +92,6 @@ export class Onboarding extends React.Component {
this.props.setVideoEnd(index, true);
};
// eslint-disable-line jsx-handler-names
render() {
const { videos, onClick, setVideoDuration } = this.props;
const { showVideos } = this.state;

View File

@ -1,6 +1,6 @@
{
"name": "strapi-admin",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Strapi Admin",
"repository": {
"type": "git",
@ -72,8 +72,8 @@
"sanitize.css": "^4.1.0",
"sass-loader": "^7.1.0",
"shelljs": "^0.7.8",
"strapi-helper-plugin": "3.0.0-beta.16.3",
"strapi-utils": "3.0.0-beta.16.3",
"strapi-helper-plugin": "3.0.0-beta.16.4",
"strapi-utils": "3.0.0-beta.16.4",
"style-loader": "^0.23.1",
"styled-components": "^4.2.0",
"terser-webpack-plugin": "^1.2.3",

View File

@ -1,6 +1,6 @@
{
"name": "strapi-generate-api",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Generate an API for a Strapi application.",
"homepage": "http://strapi.io",
"keywords": [

View File

@ -1,6 +1,6 @@
{
"name": "strapi-generate-controller",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Generate a controller for a Strapi API.",
"homepage": "http://strapi.io",
"keywords": [

View File

@ -1,6 +1,6 @@
{
"name": "strapi-generate-model",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Generate a model for a Strapi API.",
"homepage": "http://strapi.io",
"keywords": [

View File

@ -29,8 +29,8 @@ module.exports = opts => {
},
devDependencies: {
'babel-eslint': '^10.0.0',
eslint: '^6.0.0',
'eslint-config-airbnb': '^17.1.0',
eslint: '^6.3.0',
'eslint-config-airbnb': '^18.0.0',
'eslint-plugin-import': '^2.18.0',
'eslint-plugin-react': '^7.14.0',
},

View File

@ -1,6 +1,6 @@
{
"name": "strapi-generate-new",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Generate a new Strapi application.",
"homepage": "http://strapi.io",
"keywords": [

View File

@ -1,6 +1,6 @@
{
"name": "strapi-generate-plugin",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Generate an plugin for a Strapi application.",
"homepage": "http://strapi.io",
"keywords": [

View File

@ -1,6 +1,6 @@
{
"name": "strapi-generate-policy",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Generate a policy for a Strapi API.",
"homepage": "http://strapi.io",
"keywords": [

View File

@ -1,6 +1,6 @@
{
"name": "strapi-generate-service",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Generate a service for a Strapi API.",
"homepage": "http://strapi.io",
"keywords": [

View File

@ -1,6 +1,6 @@
{
"name": "strapi-generate",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Master of ceremonies for the Strapi generators.",
"homepage": "http://strapi.io",
"keywords": [
@ -20,7 +20,7 @@
"fs-extra": "^8.0.1",
"lodash": "^4.17.11",
"reportback": "^2.0.2",
"strapi-utils": "3.0.0-beta.16.3"
"strapi-utils": "3.0.0-beta.16.4"
},
"author": {
"name": "Strapi team",

View File

@ -30,7 +30,7 @@ import App from 'containers/App';
const layout = (() => {
try {
return require('../../../../config/layout.js'); // eslint-disable-line import/no-unresolved
return require('../../../../config/layout.js');
} catch (err) {
return null;
}
@ -38,7 +38,7 @@ const layout = (() => {
const injectedComponents = (() => {
try {
return require('injectedComponents').default; // eslint-disable-line import/no-unresolved
return require('injectedComponents').default;
} catch (err) {
return [];
}
@ -80,7 +80,7 @@ if (module.hot) {
// Require the Initializer component
const initializer = (() => {
try {
return require('../../../../admin/src/initializer.js'); // eslint-disable-line import/no-unresolved
return require('../../../../admin/src/initializer.js');
} catch (err) {
return null;
}
@ -89,7 +89,7 @@ const initializer = (() => {
// Require the plugin's lifecycle
const lifecycles = (() => {
try {
return require('../../../../admin/src/lifecycles.js'); // eslint-disable-line import/no-unresolved
return require('../../../../admin/src/lifecycles.js');
} catch (err) {
return null;
}

View File

@ -10,7 +10,6 @@ import PropTypes from 'prop-types';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/anchor-is-valid */
class GlobalPagination extends React.Component {
getLastPageNumber = () => Math.ceil(this.props.count / this.props.params._limit) || 1;

View File

@ -11,7 +11,6 @@ import cn from 'classnames';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/no-autofocus */
class InputAddon extends React.Component {
state = { isFocused: false };

View File

@ -12,8 +12,6 @@ import cn from 'classnames';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/no-autofocus */
/* eslint-disable jsx-a11y/label-has-for */
class InputCheckbox extends React.Component {
handleChange = () => {
const target = {

View File

@ -11,7 +11,6 @@ import cn from 'classnames';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/no-autofocus */
class InputEmail extends React.Component {
state = { isFocused: false };

View File

@ -17,7 +17,6 @@ import InputFileDetails from '../InputFileDetails';
import styles from './styles.scss';
/* eslint-disable react/jsx-handler-names */
/* eslint-disable jsx-a11y/label-has-for */
class InputFile extends React.Component {
state = {
didDeleteFile: false,
@ -60,7 +59,7 @@ class InputFile extends React.Component {
type: 'file',
value,
};
this.inputFile.value = '';
this.setState({ isUploading: !this.state.isUploading });
this.props.onChange({ target });
@ -105,7 +104,7 @@ class InputFile extends React.Component {
const {value} = this.props;
if (!value ||
(isArray(value) && value.length === 0) ||
(isArray(value) && value.length === 0) ||
(isObject(value) && Object.keys(value).length === 0)
) {
return false;

View File

@ -6,10 +6,9 @@ import cn from 'classnames';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/no-autofocus */
function InputNumber(props) {
const formattedPlaceholder = props.placeholder === '' ? 'app.utils.placeholder.defaultMessage' : props.placeholder;
return (
<FormattedMessage id={formattedPlaceholder} defaultMessage={formattedPlaceholder}>
{(message) => (

View File

@ -12,7 +12,6 @@ import cn from 'classnames';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/no-autofocus */
class InputPassword extends React.Component {
state = { showPassword: false };

View File

@ -12,7 +12,6 @@ import cn from 'classnames';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/no-autofocus */
class InputSearch extends React.Component {
state = { isFocused: false };

View File

@ -15,7 +15,6 @@ import SelectOption from '../SelectOption';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/no-autofocus */
function InputSelect(props) {
return (
<select

View File

@ -4,7 +4,6 @@ import { isEmpty } from 'lodash';
import { FormattedMessage } from 'react-intl';
import cn from 'classnames';
/* eslint-disable jsx-a11y/no-autofocus */
import styles from './styles.scss';
function InputText(props) {

View File

@ -4,7 +4,6 @@
*
*/
/* eslint-disable jsx-a11y/no-autofocus */
import React from 'react';
import { FormattedMessage } from 'react-intl';
import { isEmpty } from 'lodash';

View File

@ -15,7 +15,6 @@ import InputSpacer from '../InputSpacer';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/no-autofocus */
class InputTextWithErrors extends React.Component {
// eslint-disable-line react/prefer-stateless-function
state = { errors: [], hasInitialValue: false };

View File

@ -9,7 +9,6 @@ import { isEmpty } from 'lodash';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/no-autofocus */
class InputToggle extends React.Component {
handleClick = (e) => {
const target = {

View File

@ -6,7 +6,6 @@ import cn from 'classnames';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/label-has-for */
function Label(props) {
let content = props.children;

View File

@ -14,7 +14,6 @@ import GlobalPagination from '../GlobalPagination';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/label-has-for */
function PageFooter(props) {
return (
<div className={cn('row', styles.pageFooter)} style={props.style}>

View File

@ -1,6 +1,6 @@
{
"name": "strapi-helper-plugin",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Helper for Strapi plugins development",
"files": [
"dist"

View File

@ -161,9 +161,9 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
const FK = _.findKey(target.attributes, details => {
if (
details.hasOwnProperty('model') &&
_.has(details, 'model') &&
details.model === model &&
details.hasOwnProperty('via') &&
_.has(details, 'via') &&
details.via === name
) {
return details;
@ -841,7 +841,7 @@ module.exports = ({ models, target, plugin = false }, ctx) => {
_.keyBy(
_.filter(definition.attributes, (value, key) => {
if (
value.hasOwnProperty('columnName') &&
_.has(value, 'columnName') &&
!_.isEmpty(value.columnName) &&
value.columnName !== key
) {

View File

@ -490,7 +490,7 @@ module.exports = function createQueryBuilder({ model, modelKey, strapi }) {
* @param {*} params
*/
const buildSearchQuery = (qb, model, params) => {
const query = (params._q || '').replace(/[^a-zA-Z0-9.-\s]+/g, '');
const query = params._q;
const associations = model.associations.map(x => x.alias);
@ -550,7 +550,7 @@ const buildSearchQuery = (qb, model, params) => {
: `to_tsvector('${attribute}')`
);
qb.orWhereRaw(`${searchQuery.join(' || ')} @@ to_tsquery(?)`, query);
qb.orWhereRaw(`${searchQuery.join(' || ')} @@ plainto_tsquery(?)`, query);
break;
}
}

View File

@ -1,6 +1,6 @@
{
"name": "strapi-hook-bookshelf",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Bookshelf hook for the Strapi framework",
"homepage": "http://strapi.io",
"keywords": [
@ -22,8 +22,8 @@
"lodash": "^4.17.11",
"pluralize": "^7.0.0",
"rimraf": "^2.6.3",
"strapi-hook-knex": "3.0.0-beta.16.3",
"strapi-utils": "3.0.0-beta.16.3"
"strapi-hook-knex": "3.0.0-beta.16.4",
"strapi-utils": "3.0.0-beta.16.4"
},
"strapi": {
"dependencies": [

View File

@ -9,7 +9,7 @@ const path = require('path');
// Externals
const co = require('co');
const render = require('koa-ejs'); // eslint-disable-line import/no-unresolved
const render = require('koa-ejs');
/**
* EJS hook

View File

@ -1,6 +1,6 @@
{
"name": "strapi-hook-ejs",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "EJS hook for the Strapi framework",
"homepage": "http://strapi.io",
"keywords": [

View File

@ -1,6 +1,6 @@
{
"name": "strapi-hook-knex",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Knex hook for the Strapi framework",
"homepage": "http://strapi.io",
"keywords": [

View File

@ -356,14 +356,56 @@ const createOnFetchPopulateFn = ({
});
groupAttributes.forEach(name => {
const attr = definition.attributes[name];
const group = strapi.groups[attr.group];
const assocs = (group.associations || []).filter(
assoc => assoc.autoPopulate === true
);
let subpopulates = [];
assocs.forEach(assoc => {
if (isPolymorphic({ assoc })) {
if (
assoc.nature === 'oneToManyMorph' ||
assoc.nature === 'manyToManyMorph'
) {
subpopulates.push({
path: assoc.alias,
match: {
[`${assoc.via}.${assoc.filter}`]: assoc.alias,
[`${assoc.via}.kind`]: definition.globalId,
},
options: {
sort: '-createdAt',
},
select: undefined,
model: undefined,
_docs: {},
});
} else {
subpopulates.push({ path: `${assoc.alias}.ref`, _docs: {} });
}
} else {
subpopulates.push({
path: assoc.alias,
_docs: {},
});
}
});
if (
this._mongooseOptions.populate &&
this._mongooseOptions.populate[name]
) {
this._mongooseOptions.populate[name].path = `${name}.ref`;
this._mongooseOptions.populate[name].populate = subpopulates;
} else {
_.set(this._mongooseOptions, ['populate', name], {
path: `${name}.ref`,
populate: subpopulates,
_docs: {},
});
}
@ -373,6 +415,10 @@ const createOnFetchPopulateFn = ({
};
};
const isPolymorphic = ({ assoc }) => {
return assoc.nature.toLowerCase().indexOf('morph') !== -1;
};
const buildRelation = ({ definition, model, instance, attribute, name }) => {
const { nature, verbose } =
utilsModels.getNature(attribute, name, undefined, model.toLowerCase()) ||

View File

@ -1,6 +1,6 @@
{
"name": "strapi-hook-mongoose",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Mongoose hook for the Strapi framework",
"homepage": "http://strapi.io",
"keywords": [
@ -20,7 +20,7 @@
"mongoose-float": "^1.0.4",
"mongoose-long": "^0.2.1",
"pluralize": "^7.0.0",
"strapi-utils": "3.0.0-beta.16.3"
"strapi-utils": "3.0.0-beta.16.4"
},
"author": {
"email": "hi@strapi.io",

View File

@ -7,7 +7,6 @@
// Core
const util = require('util');
/* eslint-disable prefer-template */
/* eslint-disable import/no-unresolved */
// Public node modules.
const _ = require('lodash');

View File

@ -1,6 +1,6 @@
{
"name": "strapi-hook-redis",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Redis hook for the Strapi framework",
"homepage": "http://strapi.io",
"keywords": [
@ -19,7 +19,7 @@
"lodash": "^4.17.11",
"rimraf": "^2.6.3",
"stack-trace": "0.0.10",
"strapi-utils": "3.0.0-beta.16.3"
"strapi-utils": "3.0.0-beta.16.4"
},
"author": {
"email": "hi@strapi.io",

View File

@ -27,7 +27,7 @@ module.exports = strapi => {
if (_.isPlainObject(views) && !_.isEmpty(views)) {
const opts = _.clone(views);
if (opts.hasOwnProperty('default')) {
if (_.has(opts, 'default')) {
opts.extension = opts.default;
delete opts.default;
}

View File

@ -1,6 +1,6 @@
{
"name": "strapi-middleware-views",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Views middleware to enable server-side rendering for the Strapi framework",
"homepage": "http://strapi.io",
"keywords": [

View File

@ -30,6 +30,7 @@ const Form = ({
<SelectWrapper
{...currentFieldMeta}
name={keys}
plugin={currentField.plugin}
relationType={currentField.relationType}
targetModel={currentField.targetModel}
value={get(modifiedData, keys)}

View File

@ -7,7 +7,6 @@
import React from 'react';
import PropTypes from 'prop-types';
/* eslint-disable jsx-a11y/media-has-caption */
const Video = props => {
const { height, src, width } = props.contentState.getEntity(props.entityKey).getData();

View File

@ -9,7 +9,7 @@ import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/label-has-for */
const WysiwygBottomControls = ({ isPreviewMode, onChange, onClick }) => {
const browse = (
<FormattedMessage id="components.WysiwygBottomControls.uploadFiles.browse">

View File

@ -7,7 +7,6 @@
import React from 'react';
import styles from './styles.scss';
/* eslint-disable jsx-a11y/label-has-for */
const WysiwygDropUpload = (props) => {
return (
<label

View File

@ -134,6 +134,9 @@ function EditView({
}
};
// Force state to be cleared when navigation from one entry to another
dispatch({ type: 'RESET_PROPS' });
if (!isCreatingEntry) {
fetchData();
} else {

View File

@ -175,6 +175,8 @@ function reducer(state, action) {
.update('errors', () => fromJS({}))
.update('didCheckErrors', v => !v);
}
case 'RESET_PROPS':
return initialState;
case 'SET_COLLAPSES_COMPONENTS_STATE':
return state.update('collapses', () => fromJS(action.collapses));
case 'SET_ERRORS':

View File

@ -1,6 +1,6 @@
{
"name": "strapi-plugin-content-manager",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "A powerful UI to easily manage your data.",
"strapi": {
"name": "Content Manager",
@ -32,8 +32,8 @@
"redux-immutable": "^4.0.0",
"reselect": "^3.0.1",
"showdown": "^1.9.0",
"strapi-helper-plugin": "3.0.0-beta.16.3",
"strapi-utils": "3.0.0-beta.16.3",
"strapi-helper-plugin": "3.0.0-beta.16.4",
"strapi-utils": "3.0.0-beta.16.4",
"styled-components": "^4.2.0",
"yup": "^0.27.0"
},

View File

@ -6,6 +6,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { has } from 'lodash';
import { FormattedMessage } from 'react-intl';
import pluginId from '../../pluginId';
@ -53,7 +54,7 @@ class AttributesPickerModal extends React.Component {
const appPlugins = plugins;
return attributes.filter(attr => {
if (appPlugins.hasOwnProperty('upload')) {
if (has(appPlugins, 'upload')) {
return true;
}

View File

@ -1,6 +1,6 @@
{
"name": "strapi-plugin-content-type-builder",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Strapi plugin to create content type (API).",
"strapi": {
"name": "Content Type Builder",
@ -29,9 +29,9 @@
"redux": "^4.0.1",
"redux-immutable": "^4.0.0",
"reselect": "^3.0.1",
"strapi-generate": "3.0.0-beta.16.3",
"strapi-generate-api": "3.0.0-beta.16.3",
"strapi-helper-plugin": "3.0.0-beta.16.3",
"strapi-generate": "3.0.0-beta.16.4",
"strapi-generate-api": "3.0.0-beta.16.4",
"strapi-helper-plugin": "3.0.0-beta.16.4",
"yup": "^0.27.0"
},
"author": {

View File

@ -1,6 +1,6 @@
{
"name": "strapi-plugin-documentation",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "This is the description of the plugin.",
"strapi": {
"name": "Documentation",
@ -32,7 +32,7 @@
"redux": "^4.0.1",
"redux-immutable": "^4.0.0",
"reselect": "^4.0.0",
"strapi-helper-plugin": "3.0.0-beta.16.3",
"strapi-helper-plugin": "3.0.0-beta.16.4",
"swagger-ui-dist": "3.22.1"
},
"author": {

View File

@ -381,8 +381,8 @@ module.exports = {
(acc, curr) => {
const attribute = attributes[curr];
const isField =
!attribute.hasOwnProperty('model') &&
!attribute.hasOwnProperty('collection');
!_.has(attribute, 'model') &&
!_.has(attribute, 'collection');
if (attribute.required) {
acc.required.push(curr);
@ -660,7 +660,8 @@ module.exports = {
const { repeatable, group, min, max } = attribute;
const cmp = this.generateMainComponent(
strapi.groups[group].attributes
strapi.groups[group].attributes,
strapi.groups[group].associations
);
if (repeatable) {
@ -1550,8 +1551,8 @@ module.exports = {
.map(attr => {
const attribute = modelAttributes[attr];
const isField =
!attribute.hasOwnProperty('model') &&
!attribute.hasOwnProperty('collection');
!_.has(attribute, 'model') &&
!_.has(attribute, 'collection');
if (!isField) {
const name = attribute.model || attribute.collection;
@ -1758,7 +1759,7 @@ module.exports = {
mergeComponents: (initObj, srcObj) => {
const cleanedObj = Object.keys(_.get(initObj, 'schemas', {})).reduce(
(acc, current) => {
const targetObj = _.get(srcObj, ['schemas'], {}).hasOwnProperty(current)
const targetObj = _.has(_.get(srcObj, ['schemas'], {}), current)
? srcObj
: initObj;
@ -1778,7 +1779,7 @@ module.exports = {
mergePaths: function(initObj, srcObj) {
return Object.keys(initObj.paths).reduce((acc, current) => {
if (_.get(srcObj, ['paths'], {}).hasOwnProperty(current)) {
if (_.has(_.get(srcObj, ['paths'], {}), current)) {
const verbs = Object.keys(initObj.paths[current]).reduce(
(acc1, curr) => {
const verb = this.mergeVerbObject(

View File

@ -1,6 +1,6 @@
{
"name": "strapi-plugin-email",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "This is the description of the plugin.",
"strapi": {
"name": "Email",
@ -12,13 +12,13 @@
"test": "echo \"no tests yet\""
},
"dependencies": {
"strapi-provider-email-sendmail": "3.0.0-beta.16.3",
"strapi-utils": "3.0.0-beta.16.3"
"strapi-provider-email-sendmail": "3.0.0-beta.16.4",
"strapi-utils": "3.0.0-beta.16.4"
},
"devDependencies": {
"react-copy-to-clipboard": "5.0.1",
"rimraf": "^2.6.3",
"strapi-helper-plugin": "3.0.0-beta.16.3"
"strapi-helper-plugin": "3.0.0-beta.16.4"
},
"author": {
"name": "Strapi team",

View File

@ -1,6 +1,6 @@
{
"name": "strapi-plugin-graphql",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "This is the description of the plugin.",
"strapi": {
"name": "graphql",
@ -23,7 +23,7 @@
"graphql-type-long": "^0.1.1",
"koa-compose": "^4.1.0",
"pluralize": "^7.0.0",
"strapi-utils": "3.0.0-beta.16.3"
"strapi-utils": "3.0.0-beta.16.4"
},
"devDependencies": {
"cross-env": "^5.2.0",

View File

@ -143,8 +143,8 @@ const extractType = function(_type, attributeType) {
return isPrimitiveType(_type)
? _type.replace('!', '')
: isEnumType(attributeType)
? 'String'
: 'ID';
? 'String'
: 'ID';
};
/**
@ -169,11 +169,20 @@ const extractType = function(_type, attributeType) {
* age: function ageResolver() { .... }
* }
*/
const createAggregationFieldsResolver = function(model, fields, operation, typeCheck) {
const createAggregationFieldsResolver = function(
model,
fields,
operation,
typeCheck
) {
return createFieldsResolver(
fields,
async (filters, options, context, fieldResolver, fieldKey) => {
// eslint-disable-line no-unused-vars
async (obj, options, context, fieldResolver, fieldKey) => {
const filters = convertRestQueryParams({
...GraphQLQuery.convertToParams(_.omit(obj, 'where')),
...GraphQLQuery.convertToQuery(obj.where),
});
return buildQuery({ model, filters, aggregate: true })
.group({
_id: null,
@ -194,7 +203,16 @@ const preProcessGroupByData = function({ result, fieldKey, filters, model }) {
return _.map(_result, value => {
return {
key: value._id,
connection: () => filters,
connection: () => {
// filter by the grouped by value in next connection
return {
...filters,
where: {
...(filters.where || {}),
[fieldKey]: value._id,
},
};
},
};
});
};
@ -219,7 +237,13 @@ const preProcessGroupByData = function({ result, fieldKey, filters, model }) {
* }
*/
const createGroupByFieldsResolver = function(model, fields, name) {
const resolver = async (filters, options, context, fieldResolver, fieldKey) => {
const resolver = async (
filters,
options,
context,
fieldResolver,
fieldKey
) => {
const params = {
...GraphQLQuery.convertToParams(_.omit(filters, 'where')),
...GraphQLQuery.convertToQuery(filters.where),
@ -250,8 +274,10 @@ const createGroupByFieldsResolver = function(model, fields, name) {
*/
const generateConnectionFieldsTypes = function(fields, model) {
const { globalId, attributes } = model;
const primitiveFields = getFieldsByTypes(fields, isNotOfTypeArray, (type, name) =>
extractType(type, (attributes[name] || {}).type)
const primitiveFields = getFieldsByTypes(
fields,
isNotOfTypeArray,
(type, name) => extractType(type, (attributes[name] || {}).type)
);
const connectionFields = _.mapValues(primitiveFields, fieldType => ({
@ -262,9 +288,9 @@ const generateConnectionFieldsTypes = function(fields, model) {
return Object.keys(primitiveFields)
.map(
fieldKey =>
`type ${globalId}Connection${_.upperFirst(fieldKey)} {${Schema.formatGQL(
connectionFields[fieldKey]
)}}`
`type ${globalId}Connection${_.upperFirst(
fieldKey
)} {${Schema.formatGQL(connectionFields[fieldKey])}}`
)
.join('\n\n');
};
@ -277,23 +303,30 @@ const formatConnectionGroupBy = function(fields, model, name) {
const groupByFields = getFieldsByTypes(
fields,
isNotOfTypeArray,
(fieldType, fieldName) => `[${globalId}Connection${_.upperFirst(fieldName)}]`
(fieldType, fieldName) =>
`[${globalId}Connection${_.upperFirst(fieldName)}]`
);
// Get the generated field types
let groupByTypes = `type ${groupByGlobalId} {${Schema.formatGQL(groupByFields)}}\n\n`;
let groupByTypes = `type ${groupByGlobalId} {${Schema.formatGQL(
groupByFields
)}}\n\n`;
groupByTypes += generateConnectionFieldsTypes(fields, model);
return {
globalId: groupByGlobalId,
type: groupByTypes,
resolver: {
[groupByGlobalId]: createGroupByFieldsResolver(model, groupByFields, name),
[groupByGlobalId]: createGroupByFieldsResolver(
model,
groupByFields,
name
),
},
};
};
const formatConnectionAggregator = function(fields, model) {
const formatConnectionAggregator = function(fields, model, modelName) {
const { globalId } = model;
// Extract all fields of type Integer and Float and change their type to Float
@ -314,26 +347,22 @@ const formatConnectionAggregator = function(fields, model) {
}
const gqlNumberFormat = Schema.formatGQL(numericFields);
let aggregatorTypes = `type ${aggregatorGlobalId} {${Schema.formatGQL(initialFields)}}\n\n`;
let aggregatorTypes = `type ${aggregatorGlobalId} {${Schema.formatGQL(
initialFields
)}}\n\n`;
let resolvers = {
[aggregatorGlobalId]: {
count: async (obj, options, context) => {
return buildQuery({
model,
filters: {
limit: obj.limit,
where: obj.where,
},
}).count();
count(obj, options, context) {
const opts = GraphQLQuery.convertToQuery(obj.where);
if (opts._q) { // allow search param
return strapi.query(modelName).countSearch(opts);
}
return strapi.query(modelName).count(opts);
},
totalCount: async (obj, options, context) => {
return buildQuery({
model,
filters: {
where: obj.where,
},
}).count();
totalCount(obj, options, context) {
return strapi.query(modelName).count({});
},
},
};
@ -483,12 +512,7 @@ const formatModelConnectionsGQL = function(fields, model, name, modelResolver) {
return obj;
},
aggregate(obj, options, context) {
const params = {
...GraphQLQuery.convertToParams(_.omit(obj, 'where')),
...GraphQLQuery.convertToQuery(obj.where),
};
return convertRestQueryParams(params);
return obj;
},
},
...aggregatorFormat.resolver,

View File

@ -59,6 +59,7 @@ module.exports = {
this.loaders[name] = new DataLoader(
keys => {
// eslint-disable-next-line no-async-promise-executor
return new Promise(async (resolve, reject) => {
try {
// Extract queries from keys and merge similar queries.

View File

@ -23,10 +23,11 @@ module.exports = {
// Extract custom resolver or type description.
const { resolver: handler = {} } = _schema;
let queryName = `${action}${_.capitalize(name)}`;
let queryName;
if (_.has(handler, `Mutation.${action}`)) {
queryName = action;
} else {
queryName = `${action}${_.capitalize(name)}`;
}
// Retrieve policies.
@ -201,19 +202,8 @@ module.exports = {
if (_.isFunction(resolver)) {
const normalizedName = _.toLower(name);
let primaryKey;
if (plugin) {
primaryKey = strapi.plugins[plugin].models[normalizedName].primaryKey;
} else {
primaryKey = strapi.models[normalizedName].primaryKey;
}
if (options.input && options.input.where) {
context.params = Query.convertToParams(
options.input.where || {},
primaryKey
);
context.params = Query.convertToParams(options.input.where || {});
} else {
context.params = {};
}

View File

@ -18,9 +18,9 @@ module.exports = {
* @return Object
*/
convertToParams: (params, primaryKey) => {
convertToParams: params => {
return Object.keys(params).reduce((acc, current) => {
const key = current === 'id' ? primaryKey : `_${current}`;
const key = current === 'id' ? 'id' : `_${current}`;
acc[key] = params[current];
return acc;
}, {});
@ -74,10 +74,6 @@ module.exports = {
model: name,
};
const model = plugin
? strapi.plugins[plugin].models[name]
: strapi.models[name];
// Extract custom resolver or type description.
const { resolver: handler = {} } = _schema;
@ -190,7 +186,7 @@ module.exports = {
return async (ctx, next) => {
ctx.params = {
...params,
[model.primaryKey]: ctx.query[model.primaryKey],
id: ctx.query.id,
};
// Return the controller.
@ -282,24 +278,12 @@ module.exports = {
// cause a lost of the Object prototype.
const opts = this.amountLimiting(_options);
Object.defineProperties(ctx, {
query: {
value: {
...this.convertToParams(
_.omit(opts, 'where'),
model ? model.primaryKey : 'id'
),
...this.convertToQuery(opts.where),
},
writable: true,
configurable: true,
},
params: {
value: this.convertToParams(opts, model ? model.primaryKey : 'id'),
writable: true,
configurable: true,
},
});
ctx.query = {
...this.convertToParams(_.omit(opts, 'where')),
...this.convertToQuery(opts.where),
};
ctx.params = this.convertToParams(opts);
if (isController) {
const values = await resolver.call(null, ctx, null);

View File

@ -224,14 +224,20 @@ const schemaBuilder = {
switch (type) {
case 'Mutation': {
// TODO: Verify this...
const [name, action] = acc[type][resolver].split('.');
const normalizedName = _.toLower(name);
let name, action;
if (_.isString(acc[type][resolver])) {
[name, action] = acc[type][resolver].split('.');
} else if (
_.isPlainObject(acc[type][resolver]) &&
_.isString(acc[type][resolver].handler)
) {
[name, action] = acc[type][resolver].handler.split('.');
}
acc[type][resolver] = Mutation.composeMutationResolver({
_schema: strapi.plugins.graphql.config._schema.graphql,
plugin,
name: normalizedName,
name: _.toLower(name),
action,
});
break;

View File

@ -21,7 +21,6 @@ import WithInput from '../WithInput';
/* eslint-disable react/require-default-props */
class InputPassword extends React.Component {
// eslint-disable-line react/prefer-stateless-function
/* eslint-disable jsx-a11y/no-static-element-interactions */
constructor(props) {
super(props);
this.state = {

View File

@ -45,7 +45,7 @@ class RowLanguage extends React.Component {
onClick={this.handleToggleWarning}
id={this.props.name}
/>
); // eslint-disable-line jsx-a11y/no-static-element-interactions
);
// format the locale to
const defaultLanguageArray = formatLanguageLocale(this.props.name);
const flag = getFlag(defaultLanguageArray);

View File

@ -153,7 +153,6 @@ export class HomePage extends React.Component {
}
/* eslint-disable react/sort-comp */
/* eslint-disable jsx-a11y/no-static-element-interactions */
addConnection = e => {
e.preventDefault();
const newData = {};

View File

@ -1,6 +1,6 @@
{
"name": "strapi-plugin-settings-manager",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Strapi plugin to manage settings.",
"strapi": {
"name": "Settings Manager",
@ -27,7 +27,7 @@
"redux": "^4.0.1",
"reselect": "^3.0.1",
"shelljs": "^0.7.8",
"strapi-helper-plugin": "3.0.0-beta.16.3"
"strapi-helper-plugin": "3.0.0-beta.16.4"
},
"author": {
"name": "Strapi team",

View File

@ -11,7 +11,6 @@ import Label from './Label';
import P from './P';
/* eslint-disable react/no-string-refs */
/* eslint-disable jsx-a11y/label-has-for */
/* eslint-disable react/jsx-tag-spacing */
class PluginInputFile extends React.PureComponent {
state = { isDraging: false };

View File

@ -23,7 +23,10 @@ module.exports = {
Query: {
file: false,
files: {
resolver: 'Upload.find',
resolver: {
plugin: 'upload',
handler: 'Upload.find'
}
},
},
Mutation: {

View File

@ -1,6 +1,6 @@
{
"name": "strapi-plugin-upload",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "This is the description of the plugin.",
"strapi": {
"name": "Files Upload",
@ -23,9 +23,9 @@
"react-router-dom": "^5.0.0",
"react-transition-group": "^2.5.0",
"reactstrap": "^5.0.0",
"strapi-helper-plugin": "3.0.0-beta.16.3",
"strapi-provider-upload-local": "3.0.0-beta.16.3",
"strapi-utils": "3.0.0-beta.16.3",
"strapi-helper-plugin": "3.0.0-beta.16.4",
"strapi-provider-upload-local": "3.0.0-beta.16.4",
"strapi-utils": "3.0.0-beta.16.4",
"stream-to-array": "^2.3.0",
"uuid": "^3.2.1"
},

View File

@ -1,6 +1,6 @@
{
"name": "strapi-plugin-users-permissions",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Protect your API with a full-authentication process based on JWT",
"strapi": {
"name": "Roles & Permissions",
@ -31,8 +31,8 @@
"reactstrap": "^5.0.0",
"redux-saga": "^0.16.0",
"request": "^2.83.0",
"strapi-helper-plugin": "3.0.0-beta.16.3",
"strapi-utils": "3.0.0-beta.16.3",
"strapi-helper-plugin": "3.0.0-beta.16.4",
"strapi-utils": "3.0.0-beta.16.4",
"uuid": "^3.1.0"
},
"devDependencies": {

View File

@ -4,7 +4,6 @@
* Module dependencies
*/
/* eslint-disable import/no-unresolved */
/* eslint-disable prefer-template */
// Public node modules.
const _ = require('lodash');

View File

@ -1,6 +1,6 @@
{
"name": "strapi-provider-email-amazon-ses",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Amazon SES provider for strapi email",
"homepage": "http://strapi.io",
"keywords": [

View File

@ -4,7 +4,6 @@
* Module dependencies
*/
/* eslint-disable import/no-unresolved */
/* eslint-disable prefer-template */
// Public node modules.
const _ = require('lodash');

View File

@ -1,6 +1,6 @@
{
"name": "strapi-provider-email-mailgun",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Mailgun provider for strapi email plugin",
"homepage": "http://strapi.io",
"keywords": [

View File

@ -4,7 +4,6 @@
* Module dependencies
*/
/* eslint-disable import/no-unresolved */
/* eslint-disable prefer-template */
// Public node modules.
const _ = require('lodash');

View File

@ -1,6 +1,6 @@
{
"name": "strapi-provider-email-sendgrid",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Sendgrid provider for strapi email",
"homepage": "http://strapi.io",
"keywords": [

View File

@ -1,6 +1,6 @@
{
"name": "strapi-provider-email-sendmail",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Sendmail provider for strapi email",
"homepage": "http://strapi.io",
"keywords": [

View File

@ -4,7 +4,6 @@
* Module dependencies
*/
/* eslint-disable import/no-unresolved */
/* eslint-disable no-unused-vars */
// Public node modules.
const _ = require('lodash');

View File

@ -1,6 +1,6 @@
{
"name": "strapi-provider-upload-aws-s3",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "AWS S3 provider for strapi upload",
"homepage": "http://strapi.io",
"keywords": [

View File

@ -5,7 +5,6 @@
*/
// Public node modules.
/* eslint-disable import/no-unresolved */
/* eslint-disable prefer-template */
const cloudinary = require('cloudinary').v2;
const intoStream = require('into-stream');

View File

@ -1,6 +1,6 @@
{
"name": "strapi-provider-upload-cloudinary",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Cloudinary provider for strapi upload",
"homepage": "http://strapi.io",
"keywords": [

View File

@ -1,6 +1,6 @@
{
"name": "strapi-provider-upload-local",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Local provider for strapi upload",
"homepage": "http://strapi.io",
"keywords": [

View File

@ -4,7 +4,6 @@
* Module dependencies
*/
/* eslint-disable import/no-unresolved */
// Public node modules.
const pkgcloud = require('pkgcloud');
const streamifier = require('streamifier');

View File

@ -1,6 +1,6 @@
{
"name": "strapi-provider-upload-rackspace",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Rackspace provider for strapi upload",
"main": "./lib",
"keywords": [],

View File

@ -15,7 +15,7 @@ module.exports = (api, controller) => {
throw new Error('Should be an object');
}
if (_.isObject(controller) && controller.hasOwnProperty('identity')) {
if (_.isObject(controller) && _.has(controller, 'identity')) {
controller = controller.identity.toLowerCase();
} else if (_.isString(controller)) {
controller = controller.toLowerCase();

View File

@ -52,9 +52,9 @@ module.exports = {
}
if (
(association.hasOwnProperty('collection') &&
(_.has(association, 'collection') &&
association.collection === '*') ||
(association.hasOwnProperty('model') && association.model === '*')
(_.has(association, 'model') && association.model === '*')
) {
if (association.model) {
types.current = 'morphToD';
@ -80,16 +80,16 @@ module.exports = {
_.forIn(allModels, model => {
_.forIn(model.attributes, attribute => {
if (
attribute.hasOwnProperty('via') &&
_.has(attribute, 'via') &&
attribute.via === key &&
attribute.model === currentModelName
) {
if (attribute.hasOwnProperty('collection')) {
if (_.has(attribute, 'collection')) {
types.other = 'collection';
// Break loop
return false;
} else if (attribute.hasOwnProperty('model')) {
} else if (_.has(attribute, 'model')) {
types.other = 'model';
// Break loop
@ -99,8 +99,8 @@ module.exports = {
});
});
} else if (
association.hasOwnProperty('via') &&
association.hasOwnProperty('collection')
_.has(association, 'via') &&
_.has(association, 'collection')
) {
const relatedAttribute =
models[association.collection].attributes[association.via];
@ -120,31 +120,31 @@ module.exports = {
types.current = 'collection';
if (
relatedAttribute.hasOwnProperty('collection') &&
_.has(relatedAttribute, 'collection') &&
relatedAttribute.collection !== '*' &&
relatedAttribute.hasOwnProperty('via')
_.has(relatedAttribute, 'via')
) {
types.other = 'collection';
} else if (
relatedAttribute.hasOwnProperty('collection') &&
_.has(relatedAttribute, 'collection') &&
relatedAttribute.collection !== '*' &&
!relatedAttribute.hasOwnProperty('via')
!_.has(relatedAttribute, 'via')
) {
types.other = 'collectionD';
} else if (
relatedAttribute.hasOwnProperty('model') &&
_.has(relatedAttribute, 'model') &&
relatedAttribute.model !== '*'
) {
types.other = 'model';
} else if (
relatedAttribute.hasOwnProperty('collection') ||
relatedAttribute.hasOwnProperty('model')
_.has(relatedAttribute, 'collection') ||
_.has(relatedAttribute, 'model')
) {
types.other = 'morphTo';
}
} else if (
association.hasOwnProperty('via') &&
association.hasOwnProperty('model')
_.has(association, 'via') &&
_.has(association, 'model')
) {
types.current = 'modelD';
@ -153,32 +153,32 @@ module.exports = {
const attribute = model.attributes[association.via];
if (
attribute.hasOwnProperty('via') &&
_.has(attribute, 'via') &&
attribute.via === key &&
attribute.hasOwnProperty('collection') &&
_.has(attribute, 'collection') &&
attribute.collection !== '*'
) {
types.other = 'collection';
} else if (
attribute.hasOwnProperty('model') &&
_.has(attribute, 'model') &&
attribute.model !== '*'
) {
types.other = 'model';
} else if (
attribute.hasOwnProperty('collection') ||
attribute.hasOwnProperty('model')
_.has(attribute, 'collection') ||
_.has(attribute, 'model')
) {
types.other = 'morphTo';
}
} else if (association.hasOwnProperty('model')) {
} else if (_.has(association, 'model')) {
types.current = 'model';
// We have to find if they are a model linked to this key
_.forIn(models, model => {
_.forIn(model.attributes, attribute => {
if (attribute.hasOwnProperty('via') && attribute.via === key) {
if (_.has(attribute, 'via') && attribute.via === key) {
if (
attribute.hasOwnProperty('collection') &&
_.has(attribute, 'collection') &&
attribute.collection === currentModelName
) {
types.other = 'collection';
@ -186,7 +186,7 @@ module.exports = {
// Break loop
return false;
} else if (
attribute.hasOwnProperty('model') &&
_.has(attribute, 'model') &&
attribute.model === currentModelName
) {
types.other = 'modelD';
@ -197,15 +197,15 @@ module.exports = {
}
});
});
} else if (association.hasOwnProperty('collection')) {
} else if (_.has(association, 'collection')) {
types.current = 'collectionD';
// We have to find if they are a model linked to this key
_.forIn(models, model => {
_.forIn(model.attributes, attribute => {
if (attribute.hasOwnProperty('via') && attribute.via === key) {
if (_.has(attribute, 'via') && attribute.via === key) {
if (
attribute.hasOwnProperty('collection') &&
_.has(attribute, 'collection') &&
attribute.collection === currentModelName
) {
types.other = 'collection';
@ -213,7 +213,7 @@ module.exports = {
// Break loop
return false;
} else if (
attribute.hasOwnProperty('model') &&
_.has(attribute, 'model') &&
attribute.model === currentModelName
) {
types.other = 'modelD';
@ -258,7 +258,7 @@ module.exports = {
};
} else if (
types.current === 'morphTo' &&
(types.other === 'model' || association.hasOwnProperty('model'))
(types.other === 'model' || _.has(association, 'model'))
) {
return {
nature: 'manyMorphToOne',
@ -267,7 +267,7 @@ module.exports = {
} else if (
types.current === 'morphTo' &&
(types.other === 'collection' ||
association.hasOwnProperty('collection'))
_.has(association, 'collection'))
) {
return {
nature: 'manyMorphToMany',
@ -557,7 +557,7 @@ module.exports = {
}, {})
);
if (!models.hasOwnProperty(model)) {
if (!_.has(models, model)) {
return this.log.error(`The model ${model} can't be found.`);
}

View File

@ -1,6 +1,6 @@
{
"name": "strapi-utils",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "Shared utilities for the Strapi packages",
"homepage": "http://strapi.io",
"keywords": [

View File

@ -89,6 +89,14 @@ const productFixtures = [
rank: 99,
big_rank: '999999999999',
},
{
name: 'Продукт 5, Product 5',
description: 'Опис на продукт 5',
price: null,
decimal_field: 142.43,
rank: 142,
big_rank: 345678912983,
},
];
async function createFixtures() {
@ -203,7 +211,7 @@ describe('Filtering API', () => {
});
describe('Filter null', () => {
test('Should return only one match', async () => {
test('Should return only matching items', async () => {
const res = await rq({
method: 'GET',
url: '/products',
@ -212,9 +220,12 @@ describe('Filtering API', () => {
},
});
const matching = data.products.filter(x => x.price === null);
res.body.sort((a, b) => (a.id > b.id ? 1 : -1));
expect(Array.isArray(res.body)).toBe(true);
expect(res.body.length).toBe(1);
expect(res.body[0]).toMatchObject(data.products[3]);
expect(res.body.length).toBe(matching.length);
expect(res.body).toMatchObject(matching);
expect(res.body).toEqual(expect.arrayContaining(matching));
});
test('Should return three matches', async () => {
@ -983,7 +994,9 @@ describe('Filtering API', () => {
});
expect(res.body).toEqual(
data.products.slice(0).sort((a, b) => a.rank - b.rank)
expect.arrayContaining(
data.products.slice(0).sort((a, b) => a.rank - b.rank)
)
);
});
@ -997,7 +1010,9 @@ describe('Filtering API', () => {
});
expect(res.body).toEqual(
data.products.slice(0).sort((a, b) => a.rank - b.rank)
expect.arrayContaining(
data.products.slice(0).sort((a, b) => a.rank - b.rank)
)
);
const res2 = await rq({
@ -1009,7 +1024,9 @@ describe('Filtering API', () => {
});
expect(res2.body).toEqual(
data.products.slice(0).sort((a, b) => b.rank - a.rank)
expect.arrayContaining(
data.products.slice(0).sort((a, b) => b.rank - a.rank)
)
);
});
@ -1043,7 +1060,7 @@ describe('Filtering API', () => {
},
});
expect(res.body).toEqual([data.products[0]]);
expect(res.body).toEqual(expect.arrayContaining([data.products[0]]));
});
test('Limit with sorting', async () => {
@ -1056,7 +1073,9 @@ describe('Filtering API', () => {
},
});
expect(res.body).toEqual([data.products[data.products.length - 1]]);
expect(res.body).toEqual(
expect.arrayContaining([data.products[data.products.length - 1]])
);
});
test('Offset', async () => {
@ -1068,7 +1087,7 @@ describe('Filtering API', () => {
},
});
expect(res.body).toEqual(data.products.slice(1));
expect(res.body).toEqual(expect.arrayContaining(data.products.slice(1)));
});
test('Offset with limit', async () => {
@ -1081,7 +1100,47 @@ describe('Filtering API', () => {
},
});
expect(res.body).toEqual(data.products.slice(1, 2));
expect(res.body).toEqual(
expect.arrayContaining(data.products.slice(1, 2))
);
});
});
describe('Text query', () => {
test('Cyrillic query', async () => {
const res = await rq({
method: 'GET',
url: '/products',
qs: {
_q: 'Опис',
},
});
expect(res.body).toEqual(expect.arrayContaining([data.products[4]]));
});
test('Multi word query', async () => {
const res = await rq({
method: 'GET',
url: '/products',
qs: {
_q: 'Product description',
},
});
expect(res.body).toEqual(expect.arrayContaining([data.products[0]]));
});
test('Multi word cyrillic query', async () => {
const res = await rq({
method: 'GET',
url: '/products',
qs: {
_q: 'Опис на продукт',
},
});
expect(res.body).toEqual(expect.arrayContaining([data.products[4]]));
});
});
});

View File

@ -265,7 +265,7 @@ module.exports = function(strapi) {
);
acc[current] = !_.isObject(currentSettings) ? {} : currentSettings;
if (!acc[current].hasOwnProperty('enabled')) {
if (!_.has(acc[current], 'enabled')) {
strapi.log.warn(
`(middleware:${current}) wasn't loaded due to missing key \`enabled\` in the configuration`
);
@ -291,7 +291,7 @@ module.exports = function(strapi) {
acc[current] = !_.isObject(currentSettings) ? {} : currentSettings;
if (!acc[current].hasOwnProperty('enabled')) {
if (!_.has(acc[current], 'enabled')) {
strapi.log.warn(
`(hook:${current}) wasn't loaded due to missing key \`enabled\` in the configuration`
);

View File

@ -54,7 +54,7 @@ module.exports = strapi => {
// Exclude routes with prefix.
const excludedRoutes = _.omitBy(
plugin.config.routes,
o => !o.config.hasOwnProperty('prefix')
o => !_.has(o.config, 'prefix')
);
_.forEach(

View File

@ -24,7 +24,7 @@ module.exports = strapi => {
strapi.config.hooks.session.secretKeys;
if (
strapi.config.middleware.settings.session.hasOwnProperty('client') &&
_.has(strapi.config.middleware.settings.session, 'client') &&
_.isString(strapi.config.middleware.settings.session.client) &&
strapi.config.middleware.settings.session.client !== 'cookie'
) {
@ -52,7 +52,7 @@ module.exports = strapi => {
});
}
} else if (
strapi.config.middleware.settings.session.hasOwnProperty('client') &&
_.has(strapi.config.middleware.settings.session, 'client') &&
_.isString(strapi.config.middleware.settings.session.client) &&
strapi.config.middleware.settings.session.client === 'cookie'
) {
@ -159,6 +159,7 @@ module.exports = strapi => {
},
requireStore(store) {
// eslint-disable-next-line no-useless-catch
try {
return require(path.resolve(
strapi.config.appPath,

View File

@ -1,12 +1,11 @@
'use strict';
/* eslint-disable import/order */
/* eslint-disable no-unused-vars */
/* eslint-disable prefer-template */
// Dependencies.
const fs = require('fs');
const path = require('path');
const { map } = require('async'); // eslint-disable-line import/order
const { map } = require('async');
const {
setWith,
merge,

View File

@ -1,6 +1,6 @@
{
"name": "strapi",
"version": "3.0.0-beta.16.3",
"version": "3.0.0-beta.16.4",
"description": "An open source headless CMS solution to create and manage your own API. It provides a powerful dashboard and features to make your life easier. Databases supported: MongoDB, MySQL, MariaDB, PostgreSQL, SQLite",
"homepage": "http://strapi.io",
"directories": {
@ -47,15 +47,15 @@
"resolve-cwd": "^3.0.0",
"rimraf": "^2.6.2",
"shelljs": "^0.8.3",
"strapi-generate": "3.0.0-beta.16.3",
"strapi-generate-api": "3.0.0-beta.16.3",
"strapi-generate-controller": "3.0.0-beta.16.3",
"strapi-generate-model": "3.0.0-beta.16.3",
"strapi-generate-new": "3.0.0-beta.16.3",
"strapi-generate-plugin": "3.0.0-beta.16.3",
"strapi-generate-policy": "3.0.0-beta.16.3",
"strapi-generate-service": "3.0.0-beta.16.3",
"strapi-utils": "3.0.0-beta.16.3"
"strapi-generate": "3.0.0-beta.16.4",
"strapi-generate-api": "3.0.0-beta.16.4",
"strapi-generate-controller": "3.0.0-beta.16.4",
"strapi-generate-model": "3.0.0-beta.16.4",
"strapi-generate-new": "3.0.0-beta.16.4",
"strapi-generate-plugin": "3.0.0-beta.16.4",
"strapi-generate-policy": "3.0.0-beta.16.4",
"strapi-generate-service": "3.0.0-beta.16.4",
"strapi-utils": "3.0.0-beta.16.4"
},
"scripts": {
"test": "jest --verbose",

Some files were not shown because too many files have changed in this diff Show More