@strapi/strapi 4.0.0-beta.17 → 4.0.0-beta.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,11 +9,11 @@
9
9
  <br />
10
10
 
11
11
  <p align="center">
12
- <a href="https://www.npmjs.org/package/strapi">
13
- <img src="https://img.shields.io/npm/v/strapi/latest.svg" alt="NPM Version" />
12
+ <a href="https://www.npmjs.org/package/@strapi/strapi">
13
+ <img src="https://img.shields.io/npm/v/@strapi/strapi/latest.svg" alt="NPM Version" />
14
14
  </a>
15
- <a href="https://www.npmjs.org/package/strapi">
16
- <img src="https://img.shields.io/npm/dm/strapi.svg" alt="Monthly download on NPM" />
15
+ <a href="https://github.com/strapi/strapi/actions/workflows/tests.yml">
16
+ <img src="https://github.com/strapi/strapi/actions/workflows/tests.yml/badge.svg?branch=master" alt="Tests" />
17
17
  </a>
18
18
  <a href="https://discord.strapi.io">
19
19
  <img src="https://img.shields.io/discord/811989166782021633?label=Discord" alt="Strapi on Discord" />
@@ -24,7 +24,7 @@
24
24
 
25
25
  <p align="center">
26
26
  <a href="https://strapi.io">
27
- <img src="https://raw.githubusercontent.com/strapi/strapi/master/public/assets/administration_panel.png" alt="Administration panel" />
27
+ <img src="https://raw.githubusercontent.com/strapi/strapi/0bcebf77b37182fe021cb59cc19be8f5db4a18ac/public/assets/administration_panel.png" alt="Administration panel" />
28
28
  </a>
29
29
  </p>
30
30
 
@@ -39,7 +39,7 @@ Strapi is a free and open-source headless CMS delivering your content anywhere y
39
39
 
40
40
  ## Getting Started
41
41
 
42
- <a href="https://strapi.io/documentation/developer-docs/latest/getting-started/quick-start.html" target="_blank">Read the Getting Started tutorial</a> or follow the steps below:
42
+ <a href="https://docs.strapi.io/developer-docs/latest/getting-started/quick-start.html" target="_blank">Read the Getting Started tutorial</a> or follow the steps below:
43
43
 
44
44
  ### ⏳ Installation
45
45
 
@@ -65,7 +65,7 @@ Enjoy 🎉
65
65
 
66
66
  ### 🖐 Requirements
67
67
 
68
- Complete installation requirements can be found in the documentation under <a href="https://strapi.io/documentation/developer-docs/latest/setup-deployment-guides/deployment.html#recommended-requirements">Installation Requirements</a>.
68
+ Complete installation requirements can be found in the documentation under <a href="https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/deployment.html">Installation Requirements</a>.
69
69
 
70
70
  **Supported operating systems**:
71
71
 
@@ -79,7 +79,7 @@ Complete installation requirements can be found in the documentation under <a hr
79
79
 
80
80
  **Node:**
81
81
 
82
- - NodeJS >= 10.16 <=14
82
+ - NodeJS >= 12 <= 16
83
83
  - NPM >= 6.x
84
84
 
85
85
  **Database:**
@@ -109,7 +109,7 @@ Please read our [Contributing Guide](./CONTRIBUTING.md) before submitting a Pull
109
109
 
110
110
  ## Community support
111
111
 
112
- For general help using Strapi, please refer to [the official Strapi documentation](https://strapi.io/documentation/). For additional help, you can use one of these channels to ask a question:
112
+ For general help using Strapi, please refer to [the official Strapi documentation](https://docs.strapi.io). For additional help, you can use one of these channels to ask a question:
113
113
 
114
114
  - [Discord](https://discord.strapi.io) (For live discussion with the Community and Strapi team)
115
115
  - [GitHub](https://github.com/strapi/strapi) (Bug reports, Contributions)
@@ -122,7 +122,7 @@ For general help using Strapi, please refer to [the official Strapi documentatio
122
122
 
123
123
  ## Migration
124
124
 
125
- Follow our [migration guides](https://strapi.io/documentation/developer-docs/latest/update-migration-guides/migration-guides.html) on the documentation to keep your projects up-to-date.
125
+ Follow our [migration guides](https://docs.strapi.io/developer-docs/latest/update-migration-guides/migration-guides.html) on the documentation to keep your projects up-to-date.
126
126
 
127
127
  ## Roadmap
128
128
 
@@ -132,8 +132,8 @@ Check out our [roadmap](https://portal.productboard.com/strapi) to get informed
132
132
 
133
133
  See our dedicated [repository](https://github.com/strapi/documentation) for the Strapi documentation, or view our documentation live:
134
134
 
135
- - [Developer docs](https://strapi.io/documentation/developer-docs/latest/getting-started/introduction.html)
136
- - [User docs](https://strapi.io/documentation/user-docs/latest/getting-started/introduction.html)
135
+ - [Developer docs](https://docs.strapi.io/developer-docs/latest/getting-started/introduction.html)
136
+ - [User guide](https://docs.strapi.io/user-docs/latest/getting-started/introduction.html)
137
137
 
138
138
  ## Try live demo
139
139
 
@@ -39,7 +39,11 @@ const applyUserExtension = async plugins => {
39
39
  for (const ctName in plugin.contentTypes) {
40
40
  const extendedSchema = get([pluginName, 'content-types', ctName, 'schema'], extendedSchemas);
41
41
  if (extendedSchema) {
42
- plugin.contentTypes[ctName].schema = extendedSchema;
42
+ plugin.contentTypes[ctName].schema = Object.assign(
43
+ {},
44
+ plugin.contentTypes[ctName].schema,
45
+ extendedSchema
46
+ );
43
47
  }
44
48
  }
45
49
  // second: execute strapi-server extension
@@ -202,9 +202,14 @@ const createDefaultImplementation = ({ strapi, db, eventHub, entityValidator })
202
202
 
203
203
  const isDraft = contentTypesUtils.isDraft(entityToUpdate, model);
204
204
 
205
- const validData = await entityValidator.validateEntityUpdate(model, data, {
206
- isDraft,
207
- });
205
+ const validData = await entityValidator.validateEntityUpdate(
206
+ model,
207
+ data,
208
+ {
209
+ isDraft,
210
+ },
211
+ entityToUpdate
212
+ );
208
213
 
209
214
  const query = transformParamsToQuery(uid, pickSelectionParams(wrappedParams));
210
215
 
@@ -12,8 +12,11 @@ const { yup, validateYupSchema } = strapiUtils;
12
12
  const { isMediaAttribute, isScalarAttribute, getWritableAttributes } = strapiUtils.contentTypes;
13
13
  const { ValidationError } = strapiUtils.errors;
14
14
 
15
- const addMinMax = (attr, validator, data) => {
16
- if (Number.isInteger(attr.min) && (attr.required || (Array.isArray(data) && data.length > 0))) {
15
+ const addMinMax = (validator, { attr, updatedAttribute }) => {
16
+ if (
17
+ Number.isInteger(attr.min) &&
18
+ (attr.required || (Array.isArray(updatedAttribute.value) && updatedAttribute.value.length > 0))
19
+ ) {
17
20
  validator = validator.min(attr.min);
18
21
  }
19
22
  if (Number.isInteger(attr.max)) {
@@ -22,7 +25,7 @@ const addMinMax = (attr, validator, data) => {
22
25
  return validator;
23
26
  };
24
27
 
25
- const addRequiredValidation = createOrUpdate => (required, validator) => {
28
+ const addRequiredValidation = createOrUpdate => (validator, { attr: { required } }) => {
26
29
  if (required) {
27
30
  if (createOrUpdate === 'creation') {
28
31
  validator = validator.notNil();
@@ -35,7 +38,7 @@ const addRequiredValidation = createOrUpdate => (required, validator) => {
35
38
  return validator;
36
39
  };
37
40
 
38
- const addDefault = createOrUpdate => (attr, validator) => {
41
+ const addDefault = createOrUpdate => (validator, { attr }) => {
39
42
  if (createOrUpdate === 'creation') {
40
43
  if (
41
44
  ((attr.type === 'component' && attr.repeatable) || attr.type === 'dynamiczone') &&
@@ -54,7 +57,7 @@ const addDefault = createOrUpdate => (attr, validator) => {
54
57
 
55
58
  const preventCast = validator => validator.transform((val, originalVal) => originalVal);
56
59
 
57
- const createComponentValidator = createOrUpdate => (attr, data, { isDraft }) => {
60
+ const createComponentValidator = createOrUpdate => ({ attr, updatedAttribute }, { isDraft }) => {
58
61
  let validator;
59
62
 
60
63
  const model = strapi.getModel(attr.component);
@@ -66,19 +69,23 @@ const createComponentValidator = createOrUpdate => (attr, data, { isDraft }) =>
66
69
  validator = yup
67
70
  .array()
68
71
  .of(
69
- yup.lazy(item => createModelValidator(createOrUpdate)(model, item, { isDraft }).notNull())
72
+ yup.lazy(item =>
73
+ createModelValidator(createOrUpdate)({ model, data: item }, { isDraft }).notNull()
74
+ )
70
75
  );
71
- validator = addRequiredValidation(createOrUpdate)(true, validator);
72
- validator = addMinMax(attr, validator, data);
76
+ validator = addRequiredValidation(createOrUpdate)(validator, { attr: { required: true } });
77
+ validator = addMinMax(validator, { attr, updatedAttribute });
73
78
  } else {
74
- validator = createModelValidator(createOrUpdate)(model, data, { isDraft });
75
- validator = addRequiredValidation(createOrUpdate)(!isDraft && attr.required, validator);
79
+ validator = createModelValidator(createOrUpdate)({ model, updatedAttribute }, { isDraft });
80
+ validator = addRequiredValidation(createOrUpdate)(validator, {
81
+ attr: { required: !isDraft && attr.required },
82
+ });
76
83
  }
77
84
 
78
85
  return validator;
79
86
  };
80
87
 
81
- const createDzValidator = createOrUpdate => (attr, data, { isDraft }) => {
88
+ const createDzValidator = createOrUpdate => ({ attr, updatedAttribute }, { isDraft }) => {
82
89
  let validator;
83
90
 
84
91
  validator = yup.array().of(
@@ -95,76 +102,85 @@ const createDzValidator = createOrUpdate => (attr, data, { isDraft }) => {
95
102
  .notNull();
96
103
 
97
104
  return model
98
- ? schema.concat(createModelValidator(createOrUpdate)(model, item, { isDraft }))
105
+ ? schema.concat(createModelValidator(createOrUpdate)({ model, data: item }, { isDraft }))
99
106
  : schema;
100
107
  })
101
108
  );
102
- validator = addRequiredValidation(createOrUpdate)(true, validator);
103
- validator = addMinMax(attr, validator, data);
109
+ validator = addRequiredValidation(createOrUpdate)(validator, { attr: { required: true } });
110
+ validator = addMinMax(validator, { attr, updatedAttribute });
104
111
 
105
112
  return validator;
106
113
  };
107
114
 
108
- const createRelationValidator = createOrUpdate => (attr, data, { isDraft }) => {
115
+ const createRelationValidator = createOrUpdate => ({ attr, updatedAttribute }, { isDraft }) => {
109
116
  let validator;
110
117
 
111
- if (Array.isArray(data)) {
118
+ if (Array.isArray(updatedAttribute.value)) {
112
119
  validator = yup.array().of(yup.mixed());
113
120
  } else {
114
121
  validator = yup.mixed();
115
122
  }
116
- validator = addRequiredValidation(createOrUpdate)(!isDraft && attr.required, validator);
123
+
124
+ validator = addRequiredValidation(createOrUpdate)(validator, {
125
+ attr: { required: !isDraft && attr.required },
126
+ });
117
127
 
118
128
  return validator;
119
129
  };
120
130
 
121
- const createScalarAttributeValidator = createOrUpdate => (attr, { isDraft }) => {
131
+ const createScalarAttributeValidator = createOrUpdate => (metas, options) => {
122
132
  let validator;
123
133
 
124
- if (has(attr.type, validators)) {
125
- validator = validators[attr.type](attr, { isDraft });
134
+ if (has(metas.attr.type, validators)) {
135
+ validator = validators[metas.attr.type](metas, options);
126
136
  } else {
127
137
  // No validators specified - fall back to mixed
128
138
  validator = yup.mixed();
129
139
  }
130
140
 
131
- validator = addRequiredValidation(createOrUpdate)(!isDraft && attr.required, validator);
141
+ validator = addRequiredValidation(createOrUpdate)(validator, {
142
+ attr: { required: !options.isDraft && metas.attr.required },
143
+ });
132
144
 
133
145
  return validator;
134
146
  };
135
147
 
136
- const createAttributeValidator = createOrUpdate => (attr, data, { isDraft }) => {
148
+ const createAttributeValidator = createOrUpdate => (metas, options) => {
137
149
  let validator;
138
150
 
139
- if (isMediaAttribute(attr)) {
151
+ if (isMediaAttribute(metas.attr)) {
140
152
  validator = yup.mixed();
141
- } else if (isScalarAttribute(attr)) {
142
- validator = createScalarAttributeValidator(createOrUpdate)(attr, { isDraft });
153
+ } else if (isScalarAttribute(metas.attr)) {
154
+ validator = createScalarAttributeValidator(createOrUpdate)(metas, options);
143
155
  } else {
144
- if (attr.type === 'component') {
145
- validator = createComponentValidator(createOrUpdate)(attr, data, { isDraft });
146
- } else if (attr.type === 'dynamiczone') {
147
- validator = createDzValidator(createOrUpdate)(attr, data, { isDraft });
156
+ if (metas.attr.type === 'component') {
157
+ validator = createComponentValidator(createOrUpdate)(metas, options);
158
+ } else if (metas.attr.type === 'dynamiczone') {
159
+ validator = createDzValidator(createOrUpdate)(metas, options);
148
160
  } else {
149
- validator = createRelationValidator(createOrUpdate)(attr, data, { isDraft });
161
+ validator = createRelationValidator(createOrUpdate)(metas, options);
150
162
  }
151
163
 
152
164
  validator = preventCast(validator);
153
165
  }
154
166
 
155
- validator = addDefault(createOrUpdate)(attr, validator);
167
+ validator = addDefault(createOrUpdate)(validator, metas);
156
168
 
157
169
  return validator;
158
170
  };
159
171
 
160
- const createModelValidator = createOrUpdate => (model, data, { isDraft }) => {
172
+ const createModelValidator = createOrUpdate => ({ model, data, entity }, options) => {
161
173
  const writableAttributes = model ? getWritableAttributes(model) : [];
162
174
 
163
175
  const schema = writableAttributes.reduce((validators, attributeName) => {
164
176
  const validator = createAttributeValidator(createOrUpdate)(
165
- model.attributes[attributeName],
166
- prop(attributeName, data),
167
- { isDraft }
177
+ {
178
+ attr: model.attributes[attributeName],
179
+ updatedAttribute: { name: attributeName, value: prop(attributeName, data) },
180
+ model,
181
+ entity,
182
+ },
183
+ options
168
184
  );
169
185
 
170
186
  return assoc(attributeName, validator)(validators);
@@ -173,7 +189,12 @@ const createModelValidator = createOrUpdate => (model, data, { isDraft }) => {
173
189
  return yup.object().shape(schema);
174
190
  };
175
191
 
176
- const createValidateEntity = createOrUpdate => async (model, data, { isDraft = false } = {}) => {
192
+ const createValidateEntity = createOrUpdate => async (
193
+ model,
194
+ data,
195
+ { isDraft = false } = {},
196
+ entity = null
197
+ ) => {
177
198
  if (!isObject(data)) {
178
199
  const { displayName } = model.info;
179
200
 
@@ -182,7 +203,14 @@ const createValidateEntity = createOrUpdate => async (model, data, { isDraft = f
182
203
  );
183
204
  }
184
205
 
185
- const validator = createModelValidator(createOrUpdate)(model, data, { isDraft }).required();
206
+ const validator = createModelValidator(createOrUpdate)(
207
+ {
208
+ model,
209
+ data,
210
+ entity,
211
+ },
212
+ { isDraft }
213
+ ).required();
186
214
  return validateYupSchema(validator, { strict: false, abortEarly: false })(data);
187
215
  };
188
216
 
@@ -4,72 +4,155 @@ const _ = require('lodash');
4
4
 
5
5
  const { yup } = require('@strapi/utils');
6
6
 
7
+ /**
8
+ * @type {import('yup').StringSchema} StringSchema
9
+ * @type {import('yup').NumberSchema} NumberSchema
10
+ * @type {import('yup').AnySchema} AnySchema
11
+ */
12
+
7
13
  /**
8
14
  * Utility function to compose validators
9
15
  */
10
- const composeValidators = (...fns) => (attr, { isDraft }) => {
11
- return fns.reduce((validator, fn) => {
12
- return fn(attr, validator, { isDraft });
13
- }, yup.mixed());
16
+ const composeValidators = (...fns) => (...args) => {
17
+ let validator = yup.mixed();
18
+
19
+ // if we receive a schema then use it as base schema for nested composition
20
+ if (yup.isSchema(args[0])) {
21
+ validator = args[0];
22
+ args = args.slice(1);
23
+ }
24
+
25
+ return fns.reduce((validator, fn) => fn(validator, ...args), validator);
14
26
  };
15
27
 
16
28
  /* Validator utils */
17
29
 
18
30
  /**
19
31
  * Adds minLength validator
20
- * @param {Object} attribute model attribute
21
- * @param {Object} validator yup validator
32
+ * @param {StringSchema} validator yup validator
33
+ * @param {Object} metas
34
+ * @param {{ minLength: Number }} metas.attr model attribute
35
+ * @param {Object} options
36
+ * @param {boolean} options.isDraft
37
+ *
38
+ * @returns {StringSchema}
22
39
  */
23
- const addMinLengthValidator = ({ minLength }, validator, { isDraft }) =>
24
- _.isInteger(minLength) && !isDraft ? validator.min(minLength) : validator;
40
+ const addMinLengthValidator = (validator, { attr }, { isDraft }) =>
41
+ _.isInteger(attr.minLength) && !isDraft ? validator.min(attr.minLength) : validator;
25
42
 
26
43
  /**
27
44
  * Adds maxLength validator
28
- * @param {Object} attribute model attribute
29
- * @param {Object} validator yup validator
45
+ * @param {StringSchema} validator yup validator
46
+ * @param {Object} metas
47
+ * @param {{ maxLength: Number }} metas.attr model attribute
48
+ *
49
+ * @returns {StringSchema}
30
50
  */
31
- const addMaxLengthValidator = ({ maxLength }, validator) =>
32
- _.isInteger(maxLength) ? validator.max(maxLength) : validator;
51
+ const addMaxLengthValidator = (validator, { attr }) =>
52
+ _.isInteger(attr.maxLength) ? validator.max(attr.maxLength) : validator;
33
53
 
34
54
  /**
35
55
  * Adds min integer validator
36
- * @param {Object} attribute model attribute
37
- * @param {Object} validator yup validator
56
+ * @param {NumberSchema} validator yup validator
57
+ * @param {Object} metas
58
+ * @param {{ min: Number }} metas.attr model attribute
59
+ *
60
+ * @returns {NumberSchema}
38
61
  */
39
- const addMinIntegerValidator = ({ min }, validator) =>
40
- _.isNumber(min) ? validator.min(_.toInteger(min)) : validator;
62
+ const addMinIntegerValidator = (validator, { attr }) =>
63
+ _.isNumber(attr.min) ? validator.min(_.toInteger(attr.min)) : validator;
41
64
 
42
65
  /**
43
66
  * Adds max integer validator
44
- * @param {Object} attribute model attribute
45
- * @param {Object} validator yup validator
67
+ * @param {NumberSchema} validator yup validator
68
+ * @param {Object} metas
69
+ * @param {{ max: Number }} metas.attr model attribute
70
+ *
71
+ * @returns {NumberSchema}
46
72
  */
47
- const addMaxIntegerValidator = ({ max }, validator) =>
48
- _.isNumber(max) ? validator.max(_.toInteger(max)) : validator;
73
+ const addMaxIntegerValidator = (validator, { attr }) =>
74
+ _.isNumber(attr.max) ? validator.max(_.toInteger(attr.max)) : validator;
49
75
 
50
76
  /**
51
77
  * Adds min float/decimal validator
52
- * @param {Object} attribute model attribute
53
- * @param {Object} validator yup validator
78
+ * @param {NumberSchema} validator yup validator
79
+ * @param {Object} metas
80
+ * @param {{ min: Number }} metas.attr model attribute
81
+ *
82
+ * @returns {NumberSchema}
54
83
  */
55
- const addMinFloatValidator = ({ min }, validator) =>
56
- _.isNumber(min) ? validator.min(min) : validator;
84
+ const addMinFloatValidator = (validator, { attr }) =>
85
+ _.isNumber(attr.min) ? validator.min(attr.min) : validator;
57
86
 
58
87
  /**
59
88
  * Adds max float/decimal validator
60
- * @param {Object} attribute model attribute
61
- * @param {Object} validator yup validator
89
+ * @param {NumberSchema} validator yup validator
90
+ * @param {Object} metas model attribute
91
+ * @param {{ max: Number }} metas.attr
92
+ *
93
+ * @returns {NumberSchema}
62
94
  */
63
- const addMaxFloatValidator = ({ max }, validator) =>
64
- _.isNumber(max) ? validator.max(max) : validator;
95
+ const addMaxFloatValidator = (validator, { attr }) =>
96
+ _.isNumber(attr.max) ? validator.max(attr.max) : validator;
65
97
 
66
98
  /**
67
99
  * Adds regex validator
68
- * @param {Object} attribute model attribute
69
- * @param {Object} validator yup validator
100
+ * @param {StringSchema} validator yup validator
101
+ * @param {Object} metas model attribute
102
+ * @param {{ regex: RegExp }} metas.attr
103
+ *
104
+ * @returns {StringSchema}
70
105
  */
71
- const addStringRegexValidator = ({ regex }, validator) =>
72
- _.isUndefined(regex) ? validator : validator.matches(new RegExp(regex));
106
+ const addStringRegexValidator = (validator, { attr }) =>
107
+ _.isUndefined(attr.regex) ? validator : validator.matches(new RegExp(attr.regex));
108
+
109
+ /**
110
+ *
111
+ * @param {AnySchema} validator
112
+ * @param {Object} metas
113
+ * @param {{ unique: Boolean, type: String }} metas.attr
114
+ * @param {{ uid: String }} metas.model
115
+ * @param {{ name: String, value: any }} metas.updatedAttribute
116
+ * @param {Object} metas.entity
117
+ *
118
+ * @returns {AnySchema}
119
+ */
120
+ const addUniqueValidator = (validator, { attr, model, updatedAttribute, entity }) => {
121
+ if (!attr.unique && attr.type !== 'uid') {
122
+ return validator;
123
+ }
124
+
125
+ return validator.test('unique', 'This attribute must be unique', async value => {
126
+ /**
127
+ * If the attribute value is `null` we want to skip the unique validation.
128
+ * Otherwise it'll only accept a single `null` entry in the database.
129
+ */
130
+ if (updatedAttribute.value === null) {
131
+ return true;
132
+ }
133
+
134
+ /**
135
+ * If the attribute is unchanged we skip the unique verification. This will
136
+ * prevent the validator to be triggered in case the user activated the
137
+ * unique constraint after already creating multiple entries with
138
+ * the same attribute value for that field.
139
+ */
140
+ if (entity && updatedAttribute.value === entity[updatedAttribute.name]) {
141
+ return true;
142
+ }
143
+
144
+ let whereParams = entity
145
+ ? { $and: [{ [updatedAttribute.name]: value }, { $not: { id: entity.id } }] }
146
+ : { [updatedAttribute.name]: value };
147
+
148
+ const record = await strapi.db.query(model.uid).findOne({
149
+ select: ['id'],
150
+ where: whereParams,
151
+ });
152
+
153
+ return !record;
154
+ });
155
+ };
73
156
 
74
157
  /* Type validators */
75
158
 
@@ -77,29 +160,32 @@ const stringValidator = composeValidators(
77
160
  () => yup.string().transform((val, originalVal) => originalVal),
78
161
  addMinLengthValidator,
79
162
  addMaxLengthValidator,
80
- addStringRegexValidator
163
+ addStringRegexValidator,
164
+ addUniqueValidator
81
165
  );
82
166
 
83
- const emailValidator = composeValidators(stringValidator, (attr, validator) => validator.email());
167
+ const emailValidator = composeValidators(stringValidator, validator => validator.email());
84
168
 
85
- const uidValidator = composeValidators(stringValidator, (attr, validator) =>
169
+ const uidValidator = composeValidators(stringValidator, validator =>
86
170
  validator.matches(new RegExp('^[A-Za-z0-9-_.~]*$'))
87
171
  );
88
172
 
89
- const enumerationValidator = attr => {
173
+ const enumerationValidator = ({ attr }) => {
90
174
  return yup.string().oneOf((Array.isArray(attr.enum) ? attr.enum : [attr.enum]).concat(null));
91
175
  };
92
176
 
93
177
  const integerValidator = composeValidators(
94
178
  () => yup.number().integer(),
95
179
  addMinIntegerValidator,
96
- addMaxIntegerValidator
180
+ addMaxIntegerValidator,
181
+ addUniqueValidator
97
182
  );
98
183
 
99
184
  const floatValidator = composeValidators(
100
185
  () => yup.number(),
101
186
  addMinFloatValidator,
102
- addMaxFloatValidator
187
+ addMaxFloatValidator,
188
+ addUniqueValidator
103
189
  );
104
190
 
105
191
  module.exports = {
@@ -113,11 +199,11 @@ module.exports = {
113
199
  uid: uidValidator,
114
200
  json: () => yup.mixed(),
115
201
  integer: integerValidator,
116
- biginteger: () => yup.mixed(),
202
+ biginteger: composeValidators(addUniqueValidator),
117
203
  float: floatValidator,
118
204
  decimal: floatValidator,
119
- date: () => yup.mixed(),
120
- time: () => yup.mixed(),
121
- datetime: () => yup.mixed(),
122
- timestamp: () => yup.mixed(),
205
+ date: composeValidators(addUniqueValidator),
206
+ time: composeValidators(addUniqueValidator),
207
+ datetime: composeValidators(addUniqueValidator),
208
+ timestamp: composeValidators(addUniqueValidator),
123
209
  };
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
  /**
3
3
  * Strapi telemetry package.
4
- * You can learn more at https://strapi.io/documentation/developer-docs/latest/getting-started/usage-information.html
4
+ * You can learn more at https://docs.strapi.io/developer-docs/latest/getting-started/usage-information.html
5
5
  */
6
6
 
7
7
  const crypto = require('crypto');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/strapi",
3
- "version": "4.0.0-beta.17",
3
+ "version": "4.0.0-beta.20",
4
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: MySQL, MariaDB, PostgreSQL, SQLite",
5
5
  "keywords": [
6
6
  "strapi",
@@ -53,13 +53,13 @@
53
53
  },
54
54
  "license": "SEE LICENSE IN LICENSE",
55
55
  "author": {
56
- "name": "Strapi team",
56
+ "name": "Strapi Solutions SAS",
57
57
  "email": "hi@strapi.io",
58
58
  "url": "https://strapi.io"
59
59
  },
60
60
  "maintainers": [
61
61
  {
62
- "name": "Strapi team",
62
+ "name": "Strapi Solutions SAS",
63
63
  "email": "hi@strapi.io",
64
64
  "url": "https://strapi.io"
65
65
  }
@@ -79,16 +79,16 @@
79
79
  "dependencies": {
80
80
  "@koa/cors": "3.1.0",
81
81
  "@koa/router": "10.1.1",
82
- "@strapi/admin": "4.0.0-beta.17",
83
- "@strapi/database": "4.0.0-beta.17",
84
- "@strapi/generate-new": "4.0.0-beta.17",
85
- "@strapi/generators": "4.0.0-beta.17",
86
- "@strapi/logger": "4.0.0-beta.17",
87
- "@strapi/plugin-content-manager": "4.0.0-beta.17",
88
- "@strapi/plugin-content-type-builder": "4.0.0-beta.17",
89
- "@strapi/plugin-email": "4.0.0-beta.17",
90
- "@strapi/plugin-upload": "4.0.0-beta.17",
91
- "@strapi/utils": "4.0.0-beta.17",
82
+ "@strapi/admin": "4.0.0-beta.20",
83
+ "@strapi/database": "4.0.0-beta.20",
84
+ "@strapi/generate-new": "4.0.0-beta.20",
85
+ "@strapi/generators": "4.0.0-beta.20",
86
+ "@strapi/logger": "4.0.0-beta.20",
87
+ "@strapi/plugin-content-manager": "4.0.0-beta.20",
88
+ "@strapi/plugin-content-type-builder": "4.0.0-beta.20",
89
+ "@strapi/plugin-email": "4.0.0-beta.20",
90
+ "@strapi/plugin-upload": "4.0.0-beta.20",
91
+ "@strapi/utils": "4.0.0-beta.20",
92
92
  "bcryptjs": "2.4.3",
93
93
  "boxen": "5.1.2",
94
94
  "chalk": "4.1.2",
@@ -134,5 +134,5 @@
134
134
  "node": ">=12.x.x <=16.x.x",
135
135
  "npm": ">=6.0.0"
136
136
  },
137
- "gitHead": "8f9cf3803464d3dbfc8c1090c16bb5f53a60c6c3"
137
+ "gitHead": "b4993dab9f6dbc583709167f459b6f00e0b4baa6"
138
138
  }