@strapi/core 5.0.0-beta.10 → 5.0.0-beta.12

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.
@@ -1,5 +1,6 @@
1
- import strapiUtils from '@strapi/utils';
2
- import type { Schema, Struct } from '@strapi/types';
1
+ import { yup } from '@strapi/utils';
2
+ import type { Schema, Struct, Modules } from '@strapi/types';
3
+ import type { ComponentContext } from '.';
3
4
  interface ValidatorMetas<TAttribute extends Schema.Attribute.AnyAttribute> {
4
5
  attr: TAttribute;
5
6
  model: Struct.ContentTypeSchema;
@@ -7,7 +8,8 @@ interface ValidatorMetas<TAttribute extends Schema.Attribute.AnyAttribute> {
7
8
  name: string;
8
9
  value: unknown;
9
10
  };
10
- entity: Record<string, unknown> | null;
11
+ entity: Modules.EntityValidator.Entity;
12
+ componentContext: ComponentContext;
11
13
  }
12
14
  interface ValidatorOptions {
13
15
  isDraft: boolean;
@@ -22,18 +24,18 @@ declare const _default: {
22
24
  enumeration: ({ attr }: {
23
25
  attr: Schema.Attribute.OfType<"enumeration"> & Schema.Attribute.EnumerationProperties<[]> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<never> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption;
24
26
  }) => import("yup").StringSchema<string | undefined, Record<string, any>, string | undefined>;
25
- boolean: () => strapiUtils.yup.BooleanSchema<boolean | undefined, Record<string, any>, boolean | undefined>;
27
+ boolean: () => yup.BooleanSchema<boolean | undefined, Record<string, any>, boolean | undefined>;
26
28
  uid: (metas: ValidatorMetas<Schema.Attribute.OfType<"uid"> & Schema.Attribute.UIDProperties<string, Schema.Attribute.UIDOptions> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<string> & Schema.Attribute.MinMaxLengthOption & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption>, options: ValidatorOptions) => import("yup").StringSchema<string | undefined, Record<string, any>, string | undefined>;
27
29
  json: () => import("yup/lib/mixed").MixedSchema<any, Record<string, any>, any>;
28
- integer: (metas: ValidatorMetas<(Schema.Attribute.OfType<"biginteger"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<string> & Schema.Attribute.MinMaxOption<string> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption & Schema.Attribute.UniqueOption) | (Schema.Attribute.OfType<"integer"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<number> & Schema.Attribute.MinMaxOption<number> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption & Schema.Attribute.UniqueOption)>, options: ValidatorOptions) => strapiUtils.yup.NumberSchema<number | undefined, Record<string, any>, number | undefined>;
30
+ integer: (metas: ValidatorMetas<(Schema.Attribute.OfType<"biginteger"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<string> & Schema.Attribute.MinMaxOption<string> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption & Schema.Attribute.UniqueOption) | (Schema.Attribute.OfType<"integer"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<number> & Schema.Attribute.MinMaxOption<number> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption & Schema.Attribute.UniqueOption)>, options: ValidatorOptions) => yup.NumberSchema<number | undefined, Record<string, any>, number | undefined>;
29
31
  biginteger: (metas: ValidatorMetas<Schema.Attribute.OfType<"biginteger"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<string> & Schema.Attribute.MinMaxOption<string> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption & Schema.Attribute.UniqueOption>, options: ValidatorOptions) => import("yup/lib/mixed").MixedSchema<any, Record<string, any>, any>;
30
- float: (metas: ValidatorMetas<(Schema.Attribute.OfType<"decimal"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<number> & Schema.Attribute.MinMaxOption<number> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption & Schema.Attribute.UniqueOption) | (Schema.Attribute.OfType<"float"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<number> & Schema.Attribute.MinMaxOption<number> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption & Schema.Attribute.UniqueOption)>, options: ValidatorOptions) => strapiUtils.yup.NumberSchema<number | undefined, Record<string, any>, number | undefined>;
31
- decimal: (metas: ValidatorMetas<(Schema.Attribute.OfType<"decimal"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<number> & Schema.Attribute.MinMaxOption<number> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption & Schema.Attribute.UniqueOption) | (Schema.Attribute.OfType<"float"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<number> & Schema.Attribute.MinMaxOption<number> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption & Schema.Attribute.UniqueOption)>, options: ValidatorOptions) => strapiUtils.yup.NumberSchema<number | undefined, Record<string, any>, number | undefined>;
32
+ float: (metas: ValidatorMetas<(Schema.Attribute.OfType<"decimal"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<number> & Schema.Attribute.MinMaxOption<number> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption & Schema.Attribute.UniqueOption) | (Schema.Attribute.OfType<"float"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<number> & Schema.Attribute.MinMaxOption<number> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption & Schema.Attribute.UniqueOption)>, options: ValidatorOptions) => yup.NumberSchema<number | undefined, Record<string, any>, number | undefined>;
33
+ decimal: (metas: ValidatorMetas<(Schema.Attribute.OfType<"decimal"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<number> & Schema.Attribute.MinMaxOption<number> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption & Schema.Attribute.UniqueOption) | (Schema.Attribute.OfType<"float"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<number> & Schema.Attribute.MinMaxOption<number> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption & Schema.Attribute.UniqueOption)>, options: ValidatorOptions) => yup.NumberSchema<number | undefined, Record<string, any>, number | undefined>;
32
34
  date: (metas: ValidatorMetas<(Schema.Attribute.OfType<"datetime"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<Schema.Attribute.DateTimeValue> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.UniqueOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption) | (Schema.Attribute.OfType<"date"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<Schema.Attribute.DateValue> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.UniqueOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption) | (Schema.Attribute.OfType<"time"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<Schema.Attribute.TimeValue> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.UniqueOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption) | (Schema.Attribute.OfType<"timestamp"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<Schema.Attribute.TimestampValue> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.UniqueOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption)>, options: ValidatorOptions) => import("yup/lib/mixed").MixedSchema<any, Record<string, any>, any>;
33
35
  time: (metas: ValidatorMetas<(Schema.Attribute.OfType<"datetime"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<Schema.Attribute.DateTimeValue> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.UniqueOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption) | (Schema.Attribute.OfType<"date"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<Schema.Attribute.DateValue> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.UniqueOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption) | (Schema.Attribute.OfType<"time"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<Schema.Attribute.TimeValue> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.UniqueOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption) | (Schema.Attribute.OfType<"timestamp"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<Schema.Attribute.TimestampValue> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.UniqueOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption)>, options: ValidatorOptions) => import("yup/lib/mixed").MixedSchema<any, Record<string, any>, any>;
34
36
  datetime: (metas: ValidatorMetas<(Schema.Attribute.OfType<"datetime"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<Schema.Attribute.DateTimeValue> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.UniqueOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption) | (Schema.Attribute.OfType<"date"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<Schema.Attribute.DateValue> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.UniqueOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption) | (Schema.Attribute.OfType<"time"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<Schema.Attribute.TimeValue> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.UniqueOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption) | (Schema.Attribute.OfType<"timestamp"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<Schema.Attribute.TimestampValue> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.UniqueOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption)>, options: ValidatorOptions) => import("yup/lib/mixed").MixedSchema<any, Record<string, any>, any>;
35
37
  timestamp: (metas: ValidatorMetas<(Schema.Attribute.OfType<"datetime"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<Schema.Attribute.DateTimeValue> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.UniqueOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption) | (Schema.Attribute.OfType<"date"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<Schema.Attribute.DateValue> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.UniqueOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption) | (Schema.Attribute.OfType<"time"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<Schema.Attribute.TimeValue> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.UniqueOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption) | (Schema.Attribute.OfType<"timestamp"> & Schema.Attribute.ConfigurableOption & Schema.Attribute.DefaultOption<Schema.Attribute.TimestampValue> & Schema.Attribute.PrivateOption & Schema.Attribute.RequiredOption & Schema.Attribute.UniqueOption & Schema.Attribute.WritableOption & Schema.Attribute.VisibleOption)>, options: ValidatorOptions) => import("yup/lib/mixed").MixedSchema<any, Record<string, any>, any>;
36
- blocks: (metas: any, options: any) => strapiUtils.yup.ArraySchema<any, import("yup/lib/types").AnyObject, any[] | undefined, any[] | undefined>;
38
+ blocks: (metas: any, options: any) => yup.ArraySchema<any, import("yup/lib/types").AnyObject, any[] | undefined, any[] | undefined>;
37
39
  };
38
40
  export default _default;
39
41
  //# sourceMappingURL=validators.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../../src/services/entity-validator/validators.ts"],"names":[],"mappings":"AACA,OAAO,WAAW,MAAM,eAAe,CAAC;AACxC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAKpD,UAAU,cAAc,CAAC,UAAU,SAAS,MAAM,CAAC,SAAS,CAAC,YAAY;IACvE,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC,iBAAiB,CAAC;IAChC,gBAAgB,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IACnD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CACxC;AAED,UAAU,gBAAgB;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;;;;;;;;;;;;;;;;;;;;;;;AAuQD,wBAmBE"}
1
+ {"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../../src/services/entity-validator/validators.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACpC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAG7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,GAAG,CAAC;AAE1C,UAAU,cAAc,CAAC,UAAU,SAAS,MAAM,CAAC,SAAS,CAAC,YAAY;IACvE,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC,iBAAiB,CAAC;IAChC,gBAAgB,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IACnD,MAAM,EAAE,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC;IACvC,gBAAgB,EAAE,gBAAgB,CAAC;CACpC;AAED,UAAU,gBAAgB;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;;;;;;;;;;;;;;;;;;;;;;;AAwVD,wBAmBE"}
@@ -4,8 +4,6 @@ const strapiUtils = require("@strapi/utils");
4
4
  const blocksValidator = require("./blocks-validator.js");
5
5
  const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
6
6
  const ___default = /* @__PURE__ */ _interopDefault(_);
7
- const strapiUtils__default = /* @__PURE__ */ _interopDefault(strapiUtils);
8
- const { yup } = strapiUtils__default.default;
9
7
  const addMinLengthValidator = (validator, {
10
8
  attr
11
9
  }, { isDraft }) => {
@@ -37,7 +35,8 @@ const addUniqueValidator = (validator, {
37
35
  attr,
38
36
  model,
39
37
  updatedAttribute,
40
- entity
38
+ entity,
39
+ componentContext
41
40
  }, options) => {
42
41
  if (attr.type !== "uid" && !attr.unique) {
43
42
  return validator;
@@ -50,19 +49,61 @@ const addUniqueValidator = (validator, {
50
49
  if (!isPublish && value === entity?.[updatedAttribute.name]) {
51
50
  return true;
52
51
  }
53
- const record = await strapi.db.query(model.uid).findOne({
54
- where: {
55
- locale: options.locale,
56
- publishedAt: options.isDraft ? null : { $notNull: true },
57
- [updatedAttribute.name]: value,
58
- ...entity?.id ? { id: { $ne: entity.id } } : {}
52
+ let queryUid;
53
+ let queryWhere = {};
54
+ if (componentContext) {
55
+ const hasRepeatableData = componentContext.repeatableData.length > 0;
56
+ if (hasRepeatableData) {
57
+ const { name: updatedName, value: updatedValue } = updatedAttribute;
58
+ const pathToCheck = [...componentContext.pathToComponent.slice(1), updatedName].join(".");
59
+ const values = componentContext.repeatableData.map((item) => {
60
+ return pathToCheck.split(".").reduce((acc, key) => acc[key], item);
61
+ });
62
+ const isUpdatedAttributeRepeatedInThisEntity = values.filter((value2) => value2 === updatedValue).length > 1;
63
+ if (isUpdatedAttributeRepeatedInThisEntity) {
64
+ return false;
65
+ }
59
66
  }
60
- });
61
- return !record;
67
+ const {
68
+ model: parentModel,
69
+ options: parentOptions,
70
+ id: excludeId
71
+ } = componentContext.parentContent;
72
+ queryUid = parentModel.uid;
73
+ const whereConditions = {};
74
+ const isParentDraft = parentOptions && parentOptions.isDraft;
75
+ whereConditions.publishedAt = isParentDraft ? null : { $notNull: true };
76
+ if (parentOptions?.locale) {
77
+ whereConditions.locale = parentOptions.locale;
78
+ }
79
+ if (excludeId && !Number.isNaN(excludeId)) {
80
+ whereConditions.id = { $ne: excludeId };
81
+ }
82
+ queryWhere = {
83
+ ...componentContext.pathToComponent.reduceRight((acc, key) => ({ [key]: acc }), {
84
+ [updatedAttribute.name]: value
85
+ }),
86
+ ...whereConditions
87
+ };
88
+ } else {
89
+ queryUid = model.uid;
90
+ const scalarAttributeWhere = {
91
+ [updatedAttribute.name]: value
92
+ };
93
+ scalarAttributeWhere.publishedAt = options.isDraft ? null : { $notNull: true };
94
+ if (options?.locale) {
95
+ scalarAttributeWhere.locale = options.locale;
96
+ }
97
+ if (entity?.id) {
98
+ scalarAttributeWhere.id = { $ne: entity.id };
99
+ }
100
+ queryWhere = scalarAttributeWhere;
101
+ }
102
+ return !await strapi.db.query(queryUid).findOne({ where: queryWhere });
62
103
  });
63
104
  };
64
105
  const stringValidator = (metas, options) => {
65
- let schema = yup.string().transform((val, originalVal) => originalVal);
106
+ let schema = strapiUtils.yup.string().transform((val, originalVal) => originalVal);
66
107
  schema = addMinLengthValidator(schema, metas, options);
67
108
  schema = addMaxLengthValidator(schema, metas);
68
109
  schema = addStringRegexValidator(schema, metas);
@@ -78,28 +119,28 @@ const uidValidator = (metas, options) => {
78
119
  return schema.matches(/^[A-Za-z0-9-_.~]*$/);
79
120
  };
80
121
  const enumerationValidator = ({ attr }) => {
81
- return yup.string().oneOf((Array.isArray(attr.enum) ? attr.enum : [attr.enum]).concat(null));
122
+ return strapiUtils.yup.string().oneOf((Array.isArray(attr.enum) ? attr.enum : [attr.enum]).concat(null));
82
123
  };
83
124
  const integerValidator = (metas, options) => {
84
- let schema = yup.number().integer();
125
+ let schema = strapiUtils.yup.number().integer();
85
126
  schema = addMinIntegerValidator(schema, metas);
86
127
  schema = addMaxIntegerValidator(schema, metas);
87
128
  schema = addUniqueValidator(schema, metas, options);
88
129
  return schema;
89
130
  };
90
131
  const floatValidator = (metas, options) => {
91
- let schema = yup.number();
132
+ let schema = strapiUtils.yup.number();
92
133
  schema = addMinFloatValidator(schema, metas);
93
134
  schema = addMaxFloatValidator(schema, metas);
94
135
  schema = addUniqueValidator(schema, metas, options);
95
136
  return schema;
96
137
  };
97
138
  const bigintegerValidator = (metas, options) => {
98
- const schema = yup.mixed();
139
+ const schema = strapiUtils.yup.mixed();
99
140
  return addUniqueValidator(schema, metas, options);
100
141
  };
101
142
  const datesValidator = (metas, options) => {
102
- const schema = yup.mixed();
143
+ const schema = strapiUtils.yup.mixed();
103
144
  return addUniqueValidator(schema, metas, options);
104
145
  };
105
146
  const validators = {
@@ -109,9 +150,9 @@ const validators = {
109
150
  password: stringValidator,
110
151
  email: emailValidator,
111
152
  enumeration: enumerationValidator,
112
- boolean: () => yup.boolean(),
153
+ boolean: () => strapiUtils.yup.boolean(),
113
154
  uid: uidValidator,
114
- json: () => yup.mixed(),
155
+ json: () => strapiUtils.yup.mixed(),
115
156
  integer: integerValidator,
116
157
  biginteger: bigintegerValidator,
117
158
  float: floatValidator,
@@ -1 +1 @@
1
- {"version":3,"file":"validators.js","sources":["../../../src/services/entity-validator/validators.ts"],"sourcesContent":["import _ from 'lodash';\nimport strapiUtils from '@strapi/utils';\nimport type { Schema, Struct } from '@strapi/types';\nimport blocksValidator from './blocks-validator';\n\nconst { yup } = strapiUtils;\n\ninterface ValidatorMetas<TAttribute extends Schema.Attribute.AnyAttribute> {\n attr: TAttribute;\n model: Struct.ContentTypeSchema;\n updatedAttribute: { name: string; value: unknown };\n entity: Record<string, unknown> | null;\n}\n\ninterface ValidatorOptions {\n isDraft: boolean;\n locale?: string;\n}\n\n/* Validator utils */\n\n/**\n * Adds minLength validator\n */\nconst addMinLengthValidator = (\n validator: strapiUtils.yup.StringSchema,\n {\n attr,\n }: {\n attr:\n | Schema.Attribute.String\n | Schema.Attribute.Text\n | Schema.Attribute.RichText\n | Schema.Attribute.Password\n | Schema.Attribute.Email\n | Schema.Attribute.UID;\n },\n { isDraft }: ValidatorOptions\n) => {\n return attr.minLength && _.isInteger(attr.minLength) && !isDraft\n ? validator.min(attr.minLength)\n : validator;\n};\n\n/**\n * Adds maxLength validator\n * @returns {StringSchema}\n */\nconst addMaxLengthValidator = (\n validator: strapiUtils.yup.StringSchema,\n {\n attr,\n }: {\n attr:\n | Schema.Attribute.String\n | Schema.Attribute.Text\n | Schema.Attribute.RichText\n | Schema.Attribute.Password\n | Schema.Attribute.Email\n | Schema.Attribute.UID;\n }\n) => {\n return attr.maxLength && _.isInteger(attr.maxLength) ? validator.max(attr.maxLength) : validator;\n};\n\n/**\n * Adds min integer validator\n * @returns {NumberSchema}\n */\nconst addMinIntegerValidator = (\n validator: strapiUtils.yup.NumberSchema,\n {\n attr,\n }: {\n attr: Schema.Attribute.Integer | Schema.Attribute.BigInteger;\n }\n) => (_.isNumber(attr.min) ? validator.min(_.toInteger(attr.min)) : validator);\n\n/**\n * Adds max integer validator\n */\nconst addMaxIntegerValidator = (\n validator: strapiUtils.yup.NumberSchema,\n {\n attr,\n }: {\n attr: Schema.Attribute.Integer | Schema.Attribute.BigInteger;\n }\n) => (_.isNumber(attr.max) ? validator.max(_.toInteger(attr.max)) : validator);\n\n/**\n * Adds min float/decimal validator\n */\nconst addMinFloatValidator = (\n validator: strapiUtils.yup.NumberSchema,\n {\n attr,\n }: {\n attr: Schema.Attribute.Decimal | Schema.Attribute.Float;\n }\n) => (_.isNumber(attr.min) ? validator.min(attr.min) : validator);\n\n/**\n * Adds max float/decimal validator\n */\nconst addMaxFloatValidator = (\n validator: strapiUtils.yup.NumberSchema,\n {\n attr,\n }: {\n attr: Schema.Attribute.Decimal | Schema.Attribute.Float;\n }\n) => (_.isNumber(attr.max) ? validator.max(attr.max) : validator);\n\n/**\n * Adds regex validator\n */\nconst addStringRegexValidator = (\n validator: strapiUtils.yup.StringSchema,\n {\n attr,\n }: {\n attr:\n | Schema.Attribute.String\n | Schema.Attribute.Text\n | Schema.Attribute.RichText\n | Schema.Attribute.Password\n | Schema.Attribute.Email\n | Schema.Attribute.UID;\n }\n) => {\n return 'regex' in attr && !_.isUndefined(attr.regex)\n ? validator.matches(new RegExp(attr.regex), { excludeEmptyString: !attr.required })\n : validator;\n};\n\n/**\n * Adds unique validator\n */\nconst addUniqueValidator = <T extends strapiUtils.yup.AnySchema>(\n validator: T,\n {\n attr,\n model,\n updatedAttribute,\n entity,\n }: ValidatorMetas<Schema.Attribute.AnyAttribute & Schema.Attribute.UniqueOption>,\n options: ValidatorOptions\n): T => {\n if (attr.type !== 'uid' && !attr.unique) {\n return validator;\n }\n\n return validator.test('unique', 'This attribute must be unique', async (value) => {\n const isPublish = options.isDraft === false;\n\n /**\n * If the attribute value is `null` we want to skip the unique validation.\n * Otherwise it'll only accept a single `null` entry in the database.\n */\n if (_.isNil(value)) {\n return true;\n }\n\n /**\n * If we are updating a draft and the value is unchanged we skip the unique verification. This will\n * prevent the validator to be triggered in case the user activated the\n * unique constraint after already creating multiple entries with\n * the same attribute value for that field.\n */\n if (!isPublish && value === entity?.[updatedAttribute.name]) {\n return true;\n }\n\n /**\n * At this point we know that we are creating a new entry, publishing an entry or that the unique field value has changed\n * We check if there is an entry of this content type in the same locale, publication state and with the same unique field value\n */\n const record = await strapi.db.query(model.uid).findOne({\n where: {\n locale: options.locale,\n publishedAt: options.isDraft ? null : { $notNull: true },\n [updatedAttribute.name]: value,\n ...(entity?.id ? { id: { $ne: entity.id } } : {}),\n },\n });\n\n return !record;\n });\n};\n\n/* Type validators */\n\nconst stringValidator = (\n metas: ValidatorMetas<\n | Schema.Attribute.String\n | Schema.Attribute.Text\n | Schema.Attribute.RichText\n | Schema.Attribute.Password\n | Schema.Attribute.Email\n | Schema.Attribute.UID\n >,\n options: ValidatorOptions\n) => {\n let schema = yup.string().transform((val, originalVal) => originalVal);\n\n schema = addMinLengthValidator(schema, metas, options);\n schema = addMaxLengthValidator(schema, metas);\n schema = addStringRegexValidator(schema, metas);\n schema = addUniqueValidator(schema, metas, options);\n\n return schema;\n};\n\nconst emailValidator = (\n metas: ValidatorMetas<Schema.Attribute.Email>,\n options: ValidatorOptions\n) => {\n const schema = stringValidator(metas, options);\n return schema.email().min(1, '${path} cannot be empty');\n};\n\nconst uidValidator = (metas: ValidatorMetas<Schema.Attribute.UID>, options: ValidatorOptions) => {\n const schema = stringValidator(metas, options);\n\n return schema.matches(/^[A-Za-z0-9-_.~]*$/);\n};\n\nconst enumerationValidator = ({ attr }: { attr: Schema.Attribute.Enumeration }) => {\n return yup\n .string()\n .oneOf((Array.isArray(attr.enum) ? attr.enum : [attr.enum]).concat(null as any));\n};\n\nconst integerValidator = (\n metas: ValidatorMetas<Schema.Attribute.Integer | Schema.Attribute.BigInteger>,\n options: ValidatorOptions\n) => {\n let schema = yup.number().integer();\n\n schema = addMinIntegerValidator(schema, metas);\n schema = addMaxIntegerValidator(schema, metas);\n schema = addUniqueValidator(schema, metas, options);\n\n return schema;\n};\n\nconst floatValidator = (\n metas: ValidatorMetas<Schema.Attribute.Decimal | Schema.Attribute.Float>,\n options: ValidatorOptions\n) => {\n let schema = yup.number();\n schema = addMinFloatValidator(schema, metas);\n schema = addMaxFloatValidator(schema, metas);\n schema = addUniqueValidator(schema, metas, options);\n\n return schema;\n};\n\nconst bigintegerValidator = (\n metas: ValidatorMetas<Schema.Attribute.BigInteger>,\n options: ValidatorOptions\n) => {\n const schema = yup.mixed();\n return addUniqueValidator(schema, metas, options);\n};\n\nconst datesValidator = (\n metas: ValidatorMetas<\n | Schema.Attribute.Date\n | Schema.Attribute.DateTime\n | Schema.Attribute.Time\n | Schema.Attribute.Timestamp\n >,\n options: ValidatorOptions\n) => {\n const schema = yup.mixed();\n return addUniqueValidator(schema, metas, options);\n};\n\nexport default {\n string: stringValidator,\n text: stringValidator,\n richtext: stringValidator,\n password: stringValidator,\n email: emailValidator,\n enumeration: enumerationValidator,\n boolean: () => yup.boolean(),\n uid: uidValidator,\n json: () => yup.mixed(),\n integer: integerValidator,\n biginteger: bigintegerValidator,\n float: floatValidator,\n decimal: floatValidator,\n date: datesValidator,\n time: datesValidator,\n datetime: datesValidator,\n timestamp: datesValidator,\n blocks: blocksValidator,\n};\n"],"names":["strapiUtils","_"],"mappings":"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"}
1
+ {"version":3,"file":"validators.js","sources":["../../../src/services/entity-validator/validators.ts"],"sourcesContent":["import _ from 'lodash';\nimport { yup } from '@strapi/utils';\nimport type { Schema, Struct, Modules } from '@strapi/types';\nimport blocksValidator from './blocks-validator';\n\nimport type { ComponentContext } from '.';\n\ninterface ValidatorMetas<TAttribute extends Schema.Attribute.AnyAttribute> {\n attr: TAttribute;\n model: Struct.ContentTypeSchema;\n updatedAttribute: { name: string; value: unknown };\n entity: Modules.EntityValidator.Entity;\n componentContext: ComponentContext;\n}\n\ninterface ValidatorOptions {\n isDraft: boolean;\n locale?: string;\n}\n\n/* Validator utils */\n\n/**\n * Adds minLength validator\n */\nconst addMinLengthValidator = (\n validator: yup.StringSchema,\n {\n attr,\n }: {\n attr:\n | Schema.Attribute.String\n | Schema.Attribute.Text\n | Schema.Attribute.RichText\n | Schema.Attribute.Password\n | Schema.Attribute.Email\n | Schema.Attribute.UID;\n },\n { isDraft }: ValidatorOptions\n) => {\n return attr.minLength && _.isInteger(attr.minLength) && !isDraft\n ? validator.min(attr.minLength)\n : validator;\n};\n\n/**\n * Adds maxLength validator\n * @returns {StringSchema}\n */\nconst addMaxLengthValidator = (\n validator: yup.StringSchema,\n {\n attr,\n }: {\n attr:\n | Schema.Attribute.String\n | Schema.Attribute.Text\n | Schema.Attribute.RichText\n | Schema.Attribute.Password\n | Schema.Attribute.Email\n | Schema.Attribute.UID;\n }\n) => {\n return attr.maxLength && _.isInteger(attr.maxLength) ? validator.max(attr.maxLength) : validator;\n};\n\n/**\n * Adds min integer validator\n * @returns {NumberSchema}\n */\nconst addMinIntegerValidator = (\n validator: yup.NumberSchema,\n {\n attr,\n }: {\n attr: Schema.Attribute.Integer | Schema.Attribute.BigInteger;\n }\n) => (_.isNumber(attr.min) ? validator.min(_.toInteger(attr.min)) : validator);\n\n/**\n * Adds max integer validator\n */\nconst addMaxIntegerValidator = (\n validator: yup.NumberSchema,\n {\n attr,\n }: {\n attr: Schema.Attribute.Integer | Schema.Attribute.BigInteger;\n }\n) => (_.isNumber(attr.max) ? validator.max(_.toInteger(attr.max)) : validator);\n\n/**\n * Adds min float/decimal validator\n */\nconst addMinFloatValidator = (\n validator: yup.NumberSchema,\n {\n attr,\n }: {\n attr: Schema.Attribute.Decimal | Schema.Attribute.Float;\n }\n) => (_.isNumber(attr.min) ? validator.min(attr.min) : validator);\n\n/**\n * Adds max float/decimal validator\n */\nconst addMaxFloatValidator = (\n validator: yup.NumberSchema,\n {\n attr,\n }: {\n attr: Schema.Attribute.Decimal | Schema.Attribute.Float;\n }\n) => (_.isNumber(attr.max) ? validator.max(attr.max) : validator);\n\n/**\n * Adds regex validator\n */\nconst addStringRegexValidator = (\n validator: yup.StringSchema,\n {\n attr,\n }: {\n attr:\n | Schema.Attribute.String\n | Schema.Attribute.Text\n | Schema.Attribute.RichText\n | Schema.Attribute.Password\n | Schema.Attribute.Email\n | Schema.Attribute.UID;\n }\n) => {\n return 'regex' in attr && !_.isUndefined(attr.regex)\n ? validator.matches(new RegExp(attr.regex), { excludeEmptyString: !attr.required })\n : validator;\n};\n\n/**\n * Adds unique validator\n */\nconst addUniqueValidator = <T extends yup.AnySchema>(\n validator: T,\n {\n attr,\n model,\n updatedAttribute,\n entity,\n componentContext,\n }: ValidatorMetas<Schema.Attribute.AnyAttribute & Schema.Attribute.UniqueOption>,\n options: ValidatorOptions\n): T => {\n if (attr.type !== 'uid' && !attr.unique) {\n return validator;\n }\n\n return validator.test('unique', 'This attribute must be unique', async (value) => {\n const isPublish = options.isDraft === false;\n\n /**\n * If the attribute value is `null` we want to skip the unique validation.\n * Otherwise it'll only accept a single `null` entry in the database.\n */\n if (_.isNil(value)) {\n return true;\n }\n\n /**\n * If we are updating a draft and the value is unchanged we skip the unique verification. This will\n * prevent the validator to be triggered in case the user activated the\n * unique constraint after already creating multiple entries with\n * the same attribute value for that field.\n */\n if (!isPublish && value === entity?.[updatedAttribute.name]) {\n return true;\n }\n\n let queryUid: string;\n let queryWhere: Record<string, any> = {};\n\n if (componentContext) {\n const hasRepeatableData = componentContext.repeatableData.length > 0;\n if (hasRepeatableData) {\n // If we are validating a unique field within a repeatable component,\n // we first need to ensure that the repeatable in the current entity is\n // valid against itself.\n\n const { name: updatedName, value: updatedValue } = updatedAttribute;\n // Construct the full path to the unique field within the component.\n const pathToCheck = [...componentContext.pathToComponent.slice(1), updatedName].join('.');\n\n // Extract the values from the repeatable data using the constructed path\n const values = componentContext.repeatableData.map((item) => {\n return pathToCheck.split('.').reduce((acc, key) => acc[key], item as any);\n });\n\n // Check if the value is repeated in the current entity\n const isUpdatedAttributeRepeatedInThisEntity =\n values.filter((value) => value === updatedValue).length > 1;\n\n if (isUpdatedAttributeRepeatedInThisEntity) {\n return false;\n }\n }\n\n /**\n * When `componentContext` is present it means we are dealing with a unique\n * field within a component.\n *\n * The unique validation must consider the specific context of the\n * component, which will always be contained within a parent content type\n * and may also be nested within another component.\n *\n * We construct a query that takes into account the parent's model UID,\n * dimensions (such as draft and publish state/locale) and excludes the current\n * content type entity by its ID if provided.\n */\n const {\n model: parentModel,\n options: parentOptions,\n id: excludeId,\n } = componentContext.parentContent;\n queryUid = parentModel.uid;\n\n const whereConditions: Record<string, any> = {};\n const isParentDraft = parentOptions && parentOptions.isDraft;\n\n whereConditions.publishedAt = isParentDraft ? null : { $notNull: true };\n\n if (parentOptions?.locale) {\n whereConditions.locale = parentOptions.locale;\n }\n\n if (excludeId && !Number.isNaN(excludeId)) {\n whereConditions.id = { $ne: excludeId };\n }\n\n queryWhere = {\n ...componentContext.pathToComponent.reduceRight((acc, key) => ({ [key]: acc }), {\n [updatedAttribute.name]: value,\n }),\n\n ...whereConditions,\n };\n } else {\n /**\n * Here we are validating a scalar unique field from the content type's schema.\n * We construct a query to check if the value is unique\n * considering dimensions (e.g. locale, publication state) and excluding the current entity by its ID if available.\n */\n queryUid = model.uid;\n const scalarAttributeWhere: Record<string, any> = {\n [updatedAttribute.name]: value,\n };\n\n scalarAttributeWhere.publishedAt = options.isDraft ? null : { $notNull: true };\n\n if (options?.locale) {\n scalarAttributeWhere.locale = options.locale;\n }\n\n if (entity?.id) {\n scalarAttributeWhere.id = { $ne: entity.id };\n }\n\n queryWhere = scalarAttributeWhere;\n }\n\n // The validation should pass if there is no other record found from the query\n // TODO query not working for dynamic zones (type === relation)\n return !(await strapi.db.query(queryUid).findOne({ where: queryWhere }));\n });\n};\n\n/* Type validators */\n\nconst stringValidator = (\n metas: ValidatorMetas<\n | Schema.Attribute.String\n | Schema.Attribute.Text\n | Schema.Attribute.RichText\n | Schema.Attribute.Password\n | Schema.Attribute.Email\n | Schema.Attribute.UID\n >,\n options: ValidatorOptions\n) => {\n let schema = yup.string().transform((val, originalVal) => originalVal);\n\n schema = addMinLengthValidator(schema, metas, options);\n schema = addMaxLengthValidator(schema, metas);\n schema = addStringRegexValidator(schema, metas);\n schema = addUniqueValidator(schema, metas, options);\n\n return schema;\n};\n\nconst emailValidator = (\n metas: ValidatorMetas<Schema.Attribute.Email>,\n options: ValidatorOptions\n) => {\n const schema = stringValidator(metas, options);\n return schema.email().min(1, '${path} cannot be empty');\n};\n\nconst uidValidator = (metas: ValidatorMetas<Schema.Attribute.UID>, options: ValidatorOptions) => {\n const schema = stringValidator(metas, options);\n\n return schema.matches(/^[A-Za-z0-9-_.~]*$/);\n};\n\nconst enumerationValidator = ({ attr }: { attr: Schema.Attribute.Enumeration }) => {\n return yup\n .string()\n .oneOf((Array.isArray(attr.enum) ? attr.enum : [attr.enum]).concat(null as any));\n};\n\nconst integerValidator = (\n metas: ValidatorMetas<Schema.Attribute.Integer | Schema.Attribute.BigInteger>,\n options: ValidatorOptions\n) => {\n let schema = yup.number().integer();\n\n schema = addMinIntegerValidator(schema, metas);\n schema = addMaxIntegerValidator(schema, metas);\n schema = addUniqueValidator(schema, metas, options);\n\n return schema;\n};\n\nconst floatValidator = (\n metas: ValidatorMetas<Schema.Attribute.Decimal | Schema.Attribute.Float>,\n options: ValidatorOptions\n) => {\n let schema = yup.number();\n schema = addMinFloatValidator(schema, metas);\n schema = addMaxFloatValidator(schema, metas);\n schema = addUniqueValidator(schema, metas, options);\n\n return schema;\n};\n\nconst bigintegerValidator = (\n metas: ValidatorMetas<Schema.Attribute.BigInteger>,\n options: ValidatorOptions\n) => {\n const schema = yup.mixed();\n return addUniqueValidator(schema, metas, options);\n};\n\nconst datesValidator = (\n metas: ValidatorMetas<\n | Schema.Attribute.Date\n | Schema.Attribute.DateTime\n | Schema.Attribute.Time\n | Schema.Attribute.Timestamp\n >,\n options: ValidatorOptions\n) => {\n const schema = yup.mixed();\n return addUniqueValidator(schema, metas, options);\n};\n\nexport default {\n string: stringValidator,\n text: stringValidator,\n richtext: stringValidator,\n password: stringValidator,\n email: emailValidator,\n enumeration: enumerationValidator,\n boolean: () => yup.boolean(),\n uid: uidValidator,\n json: () => yup.mixed(),\n integer: integerValidator,\n biginteger: bigintegerValidator,\n float: floatValidator,\n decimal: floatValidator,\n date: datesValidator,\n time: datesValidator,\n datetime: datesValidator,\n timestamp: datesValidator,\n blocks: blocksValidator,\n};\n"],"names":["_","value","yup"],"mappings":"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"}
@@ -1,7 +1,6 @@
1
1
  import _ from "lodash";
2
- import strapiUtils from "@strapi/utils";
2
+ import { yup } from "@strapi/utils";
3
3
  import blocksValidator from "./blocks-validator.mjs";
4
- const { yup } = strapiUtils;
5
4
  const addMinLengthValidator = (validator, {
6
5
  attr
7
6
  }, { isDraft }) => {
@@ -33,7 +32,8 @@ const addUniqueValidator = (validator, {
33
32
  attr,
34
33
  model,
35
34
  updatedAttribute,
36
- entity
35
+ entity,
36
+ componentContext
37
37
  }, options) => {
38
38
  if (attr.type !== "uid" && !attr.unique) {
39
39
  return validator;
@@ -46,15 +46,57 @@ const addUniqueValidator = (validator, {
46
46
  if (!isPublish && value === entity?.[updatedAttribute.name]) {
47
47
  return true;
48
48
  }
49
- const record = await strapi.db.query(model.uid).findOne({
50
- where: {
51
- locale: options.locale,
52
- publishedAt: options.isDraft ? null : { $notNull: true },
53
- [updatedAttribute.name]: value,
54
- ...entity?.id ? { id: { $ne: entity.id } } : {}
49
+ let queryUid;
50
+ let queryWhere = {};
51
+ if (componentContext) {
52
+ const hasRepeatableData = componentContext.repeatableData.length > 0;
53
+ if (hasRepeatableData) {
54
+ const { name: updatedName, value: updatedValue } = updatedAttribute;
55
+ const pathToCheck = [...componentContext.pathToComponent.slice(1), updatedName].join(".");
56
+ const values = componentContext.repeatableData.map((item) => {
57
+ return pathToCheck.split(".").reduce((acc, key) => acc[key], item);
58
+ });
59
+ const isUpdatedAttributeRepeatedInThisEntity = values.filter((value2) => value2 === updatedValue).length > 1;
60
+ if (isUpdatedAttributeRepeatedInThisEntity) {
61
+ return false;
62
+ }
55
63
  }
56
- });
57
- return !record;
64
+ const {
65
+ model: parentModel,
66
+ options: parentOptions,
67
+ id: excludeId
68
+ } = componentContext.parentContent;
69
+ queryUid = parentModel.uid;
70
+ const whereConditions = {};
71
+ const isParentDraft = parentOptions && parentOptions.isDraft;
72
+ whereConditions.publishedAt = isParentDraft ? null : { $notNull: true };
73
+ if (parentOptions?.locale) {
74
+ whereConditions.locale = parentOptions.locale;
75
+ }
76
+ if (excludeId && !Number.isNaN(excludeId)) {
77
+ whereConditions.id = { $ne: excludeId };
78
+ }
79
+ queryWhere = {
80
+ ...componentContext.pathToComponent.reduceRight((acc, key) => ({ [key]: acc }), {
81
+ [updatedAttribute.name]: value
82
+ }),
83
+ ...whereConditions
84
+ };
85
+ } else {
86
+ queryUid = model.uid;
87
+ const scalarAttributeWhere = {
88
+ [updatedAttribute.name]: value
89
+ };
90
+ scalarAttributeWhere.publishedAt = options.isDraft ? null : { $notNull: true };
91
+ if (options?.locale) {
92
+ scalarAttributeWhere.locale = options.locale;
93
+ }
94
+ if (entity?.id) {
95
+ scalarAttributeWhere.id = { $ne: entity.id };
96
+ }
97
+ queryWhere = scalarAttributeWhere;
98
+ }
99
+ return !await strapi.db.query(queryUid).findOne({ where: queryWhere });
58
100
  });
59
101
  };
60
102
  const stringValidator = (metas, options) => {
@@ -1 +1 @@
1
- {"version":3,"file":"validators.mjs","sources":["../../../src/services/entity-validator/validators.ts"],"sourcesContent":["import _ from 'lodash';\nimport strapiUtils from '@strapi/utils';\nimport type { Schema, Struct } from '@strapi/types';\nimport blocksValidator from './blocks-validator';\n\nconst { yup } = strapiUtils;\n\ninterface ValidatorMetas<TAttribute extends Schema.Attribute.AnyAttribute> {\n attr: TAttribute;\n model: Struct.ContentTypeSchema;\n updatedAttribute: { name: string; value: unknown };\n entity: Record<string, unknown> | null;\n}\n\ninterface ValidatorOptions {\n isDraft: boolean;\n locale?: string;\n}\n\n/* Validator utils */\n\n/**\n * Adds minLength validator\n */\nconst addMinLengthValidator = (\n validator: strapiUtils.yup.StringSchema,\n {\n attr,\n }: {\n attr:\n | Schema.Attribute.String\n | Schema.Attribute.Text\n | Schema.Attribute.RichText\n | Schema.Attribute.Password\n | Schema.Attribute.Email\n | Schema.Attribute.UID;\n },\n { isDraft }: ValidatorOptions\n) => {\n return attr.minLength && _.isInteger(attr.minLength) && !isDraft\n ? validator.min(attr.minLength)\n : validator;\n};\n\n/**\n * Adds maxLength validator\n * @returns {StringSchema}\n */\nconst addMaxLengthValidator = (\n validator: strapiUtils.yup.StringSchema,\n {\n attr,\n }: {\n attr:\n | Schema.Attribute.String\n | Schema.Attribute.Text\n | Schema.Attribute.RichText\n | Schema.Attribute.Password\n | Schema.Attribute.Email\n | Schema.Attribute.UID;\n }\n) => {\n return attr.maxLength && _.isInteger(attr.maxLength) ? validator.max(attr.maxLength) : validator;\n};\n\n/**\n * Adds min integer validator\n * @returns {NumberSchema}\n */\nconst addMinIntegerValidator = (\n validator: strapiUtils.yup.NumberSchema,\n {\n attr,\n }: {\n attr: Schema.Attribute.Integer | Schema.Attribute.BigInteger;\n }\n) => (_.isNumber(attr.min) ? validator.min(_.toInteger(attr.min)) : validator);\n\n/**\n * Adds max integer validator\n */\nconst addMaxIntegerValidator = (\n validator: strapiUtils.yup.NumberSchema,\n {\n attr,\n }: {\n attr: Schema.Attribute.Integer | Schema.Attribute.BigInteger;\n }\n) => (_.isNumber(attr.max) ? validator.max(_.toInteger(attr.max)) : validator);\n\n/**\n * Adds min float/decimal validator\n */\nconst addMinFloatValidator = (\n validator: strapiUtils.yup.NumberSchema,\n {\n attr,\n }: {\n attr: Schema.Attribute.Decimal | Schema.Attribute.Float;\n }\n) => (_.isNumber(attr.min) ? validator.min(attr.min) : validator);\n\n/**\n * Adds max float/decimal validator\n */\nconst addMaxFloatValidator = (\n validator: strapiUtils.yup.NumberSchema,\n {\n attr,\n }: {\n attr: Schema.Attribute.Decimal | Schema.Attribute.Float;\n }\n) => (_.isNumber(attr.max) ? validator.max(attr.max) : validator);\n\n/**\n * Adds regex validator\n */\nconst addStringRegexValidator = (\n validator: strapiUtils.yup.StringSchema,\n {\n attr,\n }: {\n attr:\n | Schema.Attribute.String\n | Schema.Attribute.Text\n | Schema.Attribute.RichText\n | Schema.Attribute.Password\n | Schema.Attribute.Email\n | Schema.Attribute.UID;\n }\n) => {\n return 'regex' in attr && !_.isUndefined(attr.regex)\n ? validator.matches(new RegExp(attr.regex), { excludeEmptyString: !attr.required })\n : validator;\n};\n\n/**\n * Adds unique validator\n */\nconst addUniqueValidator = <T extends strapiUtils.yup.AnySchema>(\n validator: T,\n {\n attr,\n model,\n updatedAttribute,\n entity,\n }: ValidatorMetas<Schema.Attribute.AnyAttribute & Schema.Attribute.UniqueOption>,\n options: ValidatorOptions\n): T => {\n if (attr.type !== 'uid' && !attr.unique) {\n return validator;\n }\n\n return validator.test('unique', 'This attribute must be unique', async (value) => {\n const isPublish = options.isDraft === false;\n\n /**\n * If the attribute value is `null` we want to skip the unique validation.\n * Otherwise it'll only accept a single `null` entry in the database.\n */\n if (_.isNil(value)) {\n return true;\n }\n\n /**\n * If we are updating a draft and the value is unchanged we skip the unique verification. This will\n * prevent the validator to be triggered in case the user activated the\n * unique constraint after already creating multiple entries with\n * the same attribute value for that field.\n */\n if (!isPublish && value === entity?.[updatedAttribute.name]) {\n return true;\n }\n\n /**\n * At this point we know that we are creating a new entry, publishing an entry or that the unique field value has changed\n * We check if there is an entry of this content type in the same locale, publication state and with the same unique field value\n */\n const record = await strapi.db.query(model.uid).findOne({\n where: {\n locale: options.locale,\n publishedAt: options.isDraft ? null : { $notNull: true },\n [updatedAttribute.name]: value,\n ...(entity?.id ? { id: { $ne: entity.id } } : {}),\n },\n });\n\n return !record;\n });\n};\n\n/* Type validators */\n\nconst stringValidator = (\n metas: ValidatorMetas<\n | Schema.Attribute.String\n | Schema.Attribute.Text\n | Schema.Attribute.RichText\n | Schema.Attribute.Password\n | Schema.Attribute.Email\n | Schema.Attribute.UID\n >,\n options: ValidatorOptions\n) => {\n let schema = yup.string().transform((val, originalVal) => originalVal);\n\n schema = addMinLengthValidator(schema, metas, options);\n schema = addMaxLengthValidator(schema, metas);\n schema = addStringRegexValidator(schema, metas);\n schema = addUniqueValidator(schema, metas, options);\n\n return schema;\n};\n\nconst emailValidator = (\n metas: ValidatorMetas<Schema.Attribute.Email>,\n options: ValidatorOptions\n) => {\n const schema = stringValidator(metas, options);\n return schema.email().min(1, '${path} cannot be empty');\n};\n\nconst uidValidator = (metas: ValidatorMetas<Schema.Attribute.UID>, options: ValidatorOptions) => {\n const schema = stringValidator(metas, options);\n\n return schema.matches(/^[A-Za-z0-9-_.~]*$/);\n};\n\nconst enumerationValidator = ({ attr }: { attr: Schema.Attribute.Enumeration }) => {\n return yup\n .string()\n .oneOf((Array.isArray(attr.enum) ? attr.enum : [attr.enum]).concat(null as any));\n};\n\nconst integerValidator = (\n metas: ValidatorMetas<Schema.Attribute.Integer | Schema.Attribute.BigInteger>,\n options: ValidatorOptions\n) => {\n let schema = yup.number().integer();\n\n schema = addMinIntegerValidator(schema, metas);\n schema = addMaxIntegerValidator(schema, metas);\n schema = addUniqueValidator(schema, metas, options);\n\n return schema;\n};\n\nconst floatValidator = (\n metas: ValidatorMetas<Schema.Attribute.Decimal | Schema.Attribute.Float>,\n options: ValidatorOptions\n) => {\n let schema = yup.number();\n schema = addMinFloatValidator(schema, metas);\n schema = addMaxFloatValidator(schema, metas);\n schema = addUniqueValidator(schema, metas, options);\n\n return schema;\n};\n\nconst bigintegerValidator = (\n metas: ValidatorMetas<Schema.Attribute.BigInteger>,\n options: ValidatorOptions\n) => {\n const schema = yup.mixed();\n return addUniqueValidator(schema, metas, options);\n};\n\nconst datesValidator = (\n metas: ValidatorMetas<\n | Schema.Attribute.Date\n | Schema.Attribute.DateTime\n | Schema.Attribute.Time\n | Schema.Attribute.Timestamp\n >,\n options: ValidatorOptions\n) => {\n const schema = yup.mixed();\n return addUniqueValidator(schema, metas, options);\n};\n\nexport default {\n string: stringValidator,\n text: stringValidator,\n richtext: stringValidator,\n password: stringValidator,\n email: emailValidator,\n enumeration: enumerationValidator,\n boolean: () => yup.boolean(),\n uid: uidValidator,\n json: () => yup.mixed(),\n integer: integerValidator,\n biginteger: bigintegerValidator,\n float: floatValidator,\n decimal: floatValidator,\n date: datesValidator,\n time: datesValidator,\n datetime: datesValidator,\n timestamp: datesValidator,\n blocks: blocksValidator,\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"validators.mjs","sources":["../../../src/services/entity-validator/validators.ts"],"sourcesContent":["import _ from 'lodash';\nimport { yup } from '@strapi/utils';\nimport type { Schema, Struct, Modules } from '@strapi/types';\nimport blocksValidator from './blocks-validator';\n\nimport type { ComponentContext } from '.';\n\ninterface ValidatorMetas<TAttribute extends Schema.Attribute.AnyAttribute> {\n attr: TAttribute;\n model: Struct.ContentTypeSchema;\n updatedAttribute: { name: string; value: unknown };\n entity: Modules.EntityValidator.Entity;\n componentContext: ComponentContext;\n}\n\ninterface ValidatorOptions {\n isDraft: boolean;\n locale?: string;\n}\n\n/* Validator utils */\n\n/**\n * Adds minLength validator\n */\nconst addMinLengthValidator = (\n validator: yup.StringSchema,\n {\n attr,\n }: {\n attr:\n | Schema.Attribute.String\n | Schema.Attribute.Text\n | Schema.Attribute.RichText\n | Schema.Attribute.Password\n | Schema.Attribute.Email\n | Schema.Attribute.UID;\n },\n { isDraft }: ValidatorOptions\n) => {\n return attr.minLength && _.isInteger(attr.minLength) && !isDraft\n ? validator.min(attr.minLength)\n : validator;\n};\n\n/**\n * Adds maxLength validator\n * @returns {StringSchema}\n */\nconst addMaxLengthValidator = (\n validator: yup.StringSchema,\n {\n attr,\n }: {\n attr:\n | Schema.Attribute.String\n | Schema.Attribute.Text\n | Schema.Attribute.RichText\n | Schema.Attribute.Password\n | Schema.Attribute.Email\n | Schema.Attribute.UID;\n }\n) => {\n return attr.maxLength && _.isInteger(attr.maxLength) ? validator.max(attr.maxLength) : validator;\n};\n\n/**\n * Adds min integer validator\n * @returns {NumberSchema}\n */\nconst addMinIntegerValidator = (\n validator: yup.NumberSchema,\n {\n attr,\n }: {\n attr: Schema.Attribute.Integer | Schema.Attribute.BigInteger;\n }\n) => (_.isNumber(attr.min) ? validator.min(_.toInteger(attr.min)) : validator);\n\n/**\n * Adds max integer validator\n */\nconst addMaxIntegerValidator = (\n validator: yup.NumberSchema,\n {\n attr,\n }: {\n attr: Schema.Attribute.Integer | Schema.Attribute.BigInteger;\n }\n) => (_.isNumber(attr.max) ? validator.max(_.toInteger(attr.max)) : validator);\n\n/**\n * Adds min float/decimal validator\n */\nconst addMinFloatValidator = (\n validator: yup.NumberSchema,\n {\n attr,\n }: {\n attr: Schema.Attribute.Decimal | Schema.Attribute.Float;\n }\n) => (_.isNumber(attr.min) ? validator.min(attr.min) : validator);\n\n/**\n * Adds max float/decimal validator\n */\nconst addMaxFloatValidator = (\n validator: yup.NumberSchema,\n {\n attr,\n }: {\n attr: Schema.Attribute.Decimal | Schema.Attribute.Float;\n }\n) => (_.isNumber(attr.max) ? validator.max(attr.max) : validator);\n\n/**\n * Adds regex validator\n */\nconst addStringRegexValidator = (\n validator: yup.StringSchema,\n {\n attr,\n }: {\n attr:\n | Schema.Attribute.String\n | Schema.Attribute.Text\n | Schema.Attribute.RichText\n | Schema.Attribute.Password\n | Schema.Attribute.Email\n | Schema.Attribute.UID;\n }\n) => {\n return 'regex' in attr && !_.isUndefined(attr.regex)\n ? validator.matches(new RegExp(attr.regex), { excludeEmptyString: !attr.required })\n : validator;\n};\n\n/**\n * Adds unique validator\n */\nconst addUniqueValidator = <T extends yup.AnySchema>(\n validator: T,\n {\n attr,\n model,\n updatedAttribute,\n entity,\n componentContext,\n }: ValidatorMetas<Schema.Attribute.AnyAttribute & Schema.Attribute.UniqueOption>,\n options: ValidatorOptions\n): T => {\n if (attr.type !== 'uid' && !attr.unique) {\n return validator;\n }\n\n return validator.test('unique', 'This attribute must be unique', async (value) => {\n const isPublish = options.isDraft === false;\n\n /**\n * If the attribute value is `null` we want to skip the unique validation.\n * Otherwise it'll only accept a single `null` entry in the database.\n */\n if (_.isNil(value)) {\n return true;\n }\n\n /**\n * If we are updating a draft and the value is unchanged we skip the unique verification. This will\n * prevent the validator to be triggered in case the user activated the\n * unique constraint after already creating multiple entries with\n * the same attribute value for that field.\n */\n if (!isPublish && value === entity?.[updatedAttribute.name]) {\n return true;\n }\n\n let queryUid: string;\n let queryWhere: Record<string, any> = {};\n\n if (componentContext) {\n const hasRepeatableData = componentContext.repeatableData.length > 0;\n if (hasRepeatableData) {\n // If we are validating a unique field within a repeatable component,\n // we first need to ensure that the repeatable in the current entity is\n // valid against itself.\n\n const { name: updatedName, value: updatedValue } = updatedAttribute;\n // Construct the full path to the unique field within the component.\n const pathToCheck = [...componentContext.pathToComponent.slice(1), updatedName].join('.');\n\n // Extract the values from the repeatable data using the constructed path\n const values = componentContext.repeatableData.map((item) => {\n return pathToCheck.split('.').reduce((acc, key) => acc[key], item as any);\n });\n\n // Check if the value is repeated in the current entity\n const isUpdatedAttributeRepeatedInThisEntity =\n values.filter((value) => value === updatedValue).length > 1;\n\n if (isUpdatedAttributeRepeatedInThisEntity) {\n return false;\n }\n }\n\n /**\n * When `componentContext` is present it means we are dealing with a unique\n * field within a component.\n *\n * The unique validation must consider the specific context of the\n * component, which will always be contained within a parent content type\n * and may also be nested within another component.\n *\n * We construct a query that takes into account the parent's model UID,\n * dimensions (such as draft and publish state/locale) and excludes the current\n * content type entity by its ID if provided.\n */\n const {\n model: parentModel,\n options: parentOptions,\n id: excludeId,\n } = componentContext.parentContent;\n queryUid = parentModel.uid;\n\n const whereConditions: Record<string, any> = {};\n const isParentDraft = parentOptions && parentOptions.isDraft;\n\n whereConditions.publishedAt = isParentDraft ? null : { $notNull: true };\n\n if (parentOptions?.locale) {\n whereConditions.locale = parentOptions.locale;\n }\n\n if (excludeId && !Number.isNaN(excludeId)) {\n whereConditions.id = { $ne: excludeId };\n }\n\n queryWhere = {\n ...componentContext.pathToComponent.reduceRight((acc, key) => ({ [key]: acc }), {\n [updatedAttribute.name]: value,\n }),\n\n ...whereConditions,\n };\n } else {\n /**\n * Here we are validating a scalar unique field from the content type's schema.\n * We construct a query to check if the value is unique\n * considering dimensions (e.g. locale, publication state) and excluding the current entity by its ID if available.\n */\n queryUid = model.uid;\n const scalarAttributeWhere: Record<string, any> = {\n [updatedAttribute.name]: value,\n };\n\n scalarAttributeWhere.publishedAt = options.isDraft ? null : { $notNull: true };\n\n if (options?.locale) {\n scalarAttributeWhere.locale = options.locale;\n }\n\n if (entity?.id) {\n scalarAttributeWhere.id = { $ne: entity.id };\n }\n\n queryWhere = scalarAttributeWhere;\n }\n\n // The validation should pass if there is no other record found from the query\n // TODO query not working for dynamic zones (type === relation)\n return !(await strapi.db.query(queryUid).findOne({ where: queryWhere }));\n });\n};\n\n/* Type validators */\n\nconst stringValidator = (\n metas: ValidatorMetas<\n | Schema.Attribute.String\n | Schema.Attribute.Text\n | Schema.Attribute.RichText\n | Schema.Attribute.Password\n | Schema.Attribute.Email\n | Schema.Attribute.UID\n >,\n options: ValidatorOptions\n) => {\n let schema = yup.string().transform((val, originalVal) => originalVal);\n\n schema = addMinLengthValidator(schema, metas, options);\n schema = addMaxLengthValidator(schema, metas);\n schema = addStringRegexValidator(schema, metas);\n schema = addUniqueValidator(schema, metas, options);\n\n return schema;\n};\n\nconst emailValidator = (\n metas: ValidatorMetas<Schema.Attribute.Email>,\n options: ValidatorOptions\n) => {\n const schema = stringValidator(metas, options);\n return schema.email().min(1, '${path} cannot be empty');\n};\n\nconst uidValidator = (metas: ValidatorMetas<Schema.Attribute.UID>, options: ValidatorOptions) => {\n const schema = stringValidator(metas, options);\n\n return schema.matches(/^[A-Za-z0-9-_.~]*$/);\n};\n\nconst enumerationValidator = ({ attr }: { attr: Schema.Attribute.Enumeration }) => {\n return yup\n .string()\n .oneOf((Array.isArray(attr.enum) ? attr.enum : [attr.enum]).concat(null as any));\n};\n\nconst integerValidator = (\n metas: ValidatorMetas<Schema.Attribute.Integer | Schema.Attribute.BigInteger>,\n options: ValidatorOptions\n) => {\n let schema = yup.number().integer();\n\n schema = addMinIntegerValidator(schema, metas);\n schema = addMaxIntegerValidator(schema, metas);\n schema = addUniqueValidator(schema, metas, options);\n\n return schema;\n};\n\nconst floatValidator = (\n metas: ValidatorMetas<Schema.Attribute.Decimal | Schema.Attribute.Float>,\n options: ValidatorOptions\n) => {\n let schema = yup.number();\n schema = addMinFloatValidator(schema, metas);\n schema = addMaxFloatValidator(schema, metas);\n schema = addUniqueValidator(schema, metas, options);\n\n return schema;\n};\n\nconst bigintegerValidator = (\n metas: ValidatorMetas<Schema.Attribute.BigInteger>,\n options: ValidatorOptions\n) => {\n const schema = yup.mixed();\n return addUniqueValidator(schema, metas, options);\n};\n\nconst datesValidator = (\n metas: ValidatorMetas<\n | Schema.Attribute.Date\n | Schema.Attribute.DateTime\n | Schema.Attribute.Time\n | Schema.Attribute.Timestamp\n >,\n options: ValidatorOptions\n) => {\n const schema = yup.mixed();\n return addUniqueValidator(schema, metas, options);\n};\n\nexport default {\n string: stringValidator,\n text: stringValidator,\n richtext: stringValidator,\n password: stringValidator,\n email: emailValidator,\n enumeration: enumerationValidator,\n boolean: () => yup.boolean(),\n uid: uidValidator,\n json: () => yup.mixed(),\n integer: integerValidator,\n biginteger: bigintegerValidator,\n float: floatValidator,\n decimal: floatValidator,\n date: datesValidator,\n time: datesValidator,\n datetime: datesValidator,\n timestamp: datesValidator,\n blocks: blocksValidator,\n};\n"],"names":["value"],"mappings":"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"}
@@ -17,7 +17,7 @@ const healthCheck = async (ctx) => {
17
17
  };
18
18
  const createServer = (strapi) => {
19
19
  const app = koa({
20
- proxy: strapi.config.get("server.proxy"),
20
+ proxy: strapi.config.get("server.proxy.koa"),
21
21
  keys: strapi.config.get("server.app.keys")
22
22
  });
23
23
  app.use((ctx, next) => requestContext.run(ctx, () => next()));
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../src/services/server/index.ts"],"sourcesContent":["import Router from '@koa/router';\nimport type { Core, Modules } from '@strapi/types';\n\nimport { createHTTPServer } from './http-server';\nimport { createRouteManager } from './routing';\nimport { createAdminAPI } from './admin-api';\nimport { createContentAPI } from './content-api';\nimport registerAllRoutes from './register-routes';\nimport registerApplicationMiddlewares from './register-middlewares';\nimport createKoaApp from './koa';\nimport requestCtx from '../request-context';\n\nconst healthCheck: Core.MiddlewareHandler = async (ctx) => {\n ctx.set('strapi', 'You are so French!');\n ctx.status = 204;\n};\n\nconst createServer = (strapi: Core.Strapi): Modules.Server.Server => {\n const app = createKoaApp({\n proxy: strapi.config.get('server.proxy'),\n keys: strapi.config.get('server.app.keys'),\n });\n\n app.use((ctx, next) => requestCtx.run(ctx, () => next()));\n\n const router = new Router();\n\n const routeManager = createRouteManager(strapi);\n\n const httpServer = createHTTPServer(strapi, app);\n\n const apis = {\n 'content-api': createContentAPI(strapi),\n admin: createAdminAPI(strapi),\n };\n\n // init health check\n router.all('/_health', healthCheck);\n\n const state = {\n mounted: false,\n };\n\n return {\n app,\n router,\n httpServer,\n\n api(name) {\n return apis[name];\n },\n\n use(...args) {\n app.use(...args);\n return this;\n },\n\n routes(routes: Core.Router | Omit<Core.Route, 'info'>[]) {\n if (!Array.isArray(routes) && routes.type) {\n const api = apis[routes.type];\n if (!api) {\n throw new Error(`API ${routes.type} not found. Possible APIs are ${Object.keys(apis)}`);\n }\n\n apis[routes.type].routes(routes);\n return this;\n }\n\n routeManager.addRoutes(routes, router);\n return this;\n },\n\n mount() {\n state.mounted = true;\n\n Object.values(apis).forEach((api) => api.mount(router));\n app.use(router.routes()).use(router.allowedMethods());\n\n return this;\n },\n\n initRouting() {\n registerAllRoutes(strapi);\n\n return this;\n },\n\n async initMiddlewares() {\n await registerApplicationMiddlewares(strapi);\n\n return this;\n },\n\n listRoutes() {\n return [...router.stack];\n },\n\n listen(...args: any[]) {\n if (!state.mounted) {\n this.mount();\n }\n\n return httpServer.listen(...args);\n },\n\n async destroy() {\n await httpServer.destroy();\n },\n };\n};\n\nexport { createServer };\n"],"names":["createKoaApp","requestCtx","Router","createRouteManager","httpServer","createHTTPServer","createContentAPI","createAdminAPI","registerAllRoutes","registerApplicationMiddlewares"],"mappings":";;;;;;;;;;;;;AAYA,MAAM,cAAsC,OAAO,QAAQ;AACrD,MAAA,IAAI,UAAU,oBAAoB;AACtC,MAAI,SAAS;AACf;AAEM,MAAA,eAAe,CAAC,WAA+C;AACnE,QAAM,MAAMA,IAAa;AAAA,IACvB,OAAO,OAAO,OAAO,IAAI,cAAc;AAAA,IACvC,MAAM,OAAO,OAAO,IAAI,iBAAiB;AAAA,EAAA,CAC1C;AAEG,MAAA,IAAI,CAAC,KAAK,SAASC,eAAW,IAAI,KAAK,MAAM,KAAM,CAAA,CAAC;AAElD,QAAA,SAAS,IAAIC,gBAAAA;AAEb,QAAA,eAAeC,2BAAmB,MAAM;AAExC,QAAAC,eAAaC,WAAAA,iBAAiB,QAAQ,GAAG;AAE/C,QAAM,OAAO;AAAA,IACX,eAAeC,4BAAiB,MAAM;AAAA,IACtC,OAAOC,wBAAe,MAAM;AAAA,EAAA;AAIvB,SAAA,IAAI,YAAY,WAAW;AAElC,QAAM,QAAQ;AAAA,IACZ,SAAS;AAAA,EAAA;AAGJ,SAAA;AAAA,IACL;AAAA,IACA;AAAA,IAAA,YACAH;AAAAA,IAEA,IAAI,MAAM;AACR,aAAO,KAAK,IAAI;AAAA,IAClB;AAAA,IAEA,OAAO,MAAM;AACP,UAAA,IAAI,GAAG,IAAI;AACR,aAAA;AAAA,IACT;AAAA,IAEA,OAAO,QAAkD;AACvD,UAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,OAAO,MAAM;AACnC,cAAA,MAAM,KAAK,OAAO,IAAI;AAC5B,YAAI,CAAC,KAAK;AACF,gBAAA,IAAI,MAAM,OAAO,OAAO,IAAI,iCAAiC,OAAO,KAAK,IAAI,CAAC,EAAE;AAAA,QACxF;AAEA,aAAK,OAAO,IAAI,EAAE,OAAO,MAAM;AACxB,eAAA;AAAA,MACT;AAEa,mBAAA,UAAU,QAAQ,MAAM;AAC9B,aAAA;AAAA,IACT;AAAA,IAEA,QAAQ;AACN,YAAM,UAAU;AAET,aAAA,OAAO,IAAI,EAAE,QAAQ,CAAC,QAAQ,IAAI,MAAM,MAAM,CAAC;AAClD,UAAA,IAAI,OAAO,OAAO,CAAC,EAAE,IAAI,OAAO,gBAAgB;AAE7C,aAAA;AAAA,IACT;AAAA,IAEA,cAAc;AACZI,qBAAkB,MAAM;AAEjB,aAAA;AAAA,IACT;AAAA,IAEA,MAAM,kBAAkB;AACtB,YAAMC,oBAA+B,MAAM;AAEpC,aAAA;AAAA,IACT;AAAA,IAEA,aAAa;AACJ,aAAA,CAAC,GAAG,OAAO,KAAK;AAAA,IACzB;AAAA,IAEA,UAAU,MAAa;AACjB,UAAA,CAAC,MAAM,SAAS;AAClB,aAAK,MAAM;AAAA,MACb;AAEO,aAAAL,aAAW,OAAO,GAAG,IAAI;AAAA,IAClC;AAAA,IAEA,MAAM,UAAU;AACd,YAAMA,aAAW;IACnB;AAAA,EAAA;AAEJ;;"}
1
+ {"version":3,"file":"index.js","sources":["../../../src/services/server/index.ts"],"sourcesContent":["import Router from '@koa/router';\nimport type { Core, Modules } from '@strapi/types';\n\nimport { createHTTPServer } from './http-server';\nimport { createRouteManager } from './routing';\nimport { createAdminAPI } from './admin-api';\nimport { createContentAPI } from './content-api';\nimport registerAllRoutes from './register-routes';\nimport registerApplicationMiddlewares from './register-middlewares';\nimport createKoaApp from './koa';\nimport requestCtx from '../request-context';\n\nconst healthCheck: Core.MiddlewareHandler = async (ctx) => {\n ctx.set('strapi', 'You are so French!');\n ctx.status = 204;\n};\n\nconst createServer = (strapi: Core.Strapi): Modules.Server.Server => {\n const app = createKoaApp({\n proxy: strapi.config.get('server.proxy.koa'),\n keys: strapi.config.get('server.app.keys'),\n });\n\n app.use((ctx, next) => requestCtx.run(ctx, () => next()));\n\n const router = new Router();\n\n const routeManager = createRouteManager(strapi);\n\n const httpServer = createHTTPServer(strapi, app);\n\n const apis = {\n 'content-api': createContentAPI(strapi),\n admin: createAdminAPI(strapi),\n };\n\n // init health check\n router.all('/_health', healthCheck);\n\n const state = {\n mounted: false,\n };\n\n return {\n app,\n router,\n httpServer,\n\n api(name) {\n return apis[name];\n },\n\n use(...args) {\n app.use(...args);\n return this;\n },\n\n routes(routes: Core.Router | Omit<Core.Route, 'info'>[]) {\n if (!Array.isArray(routes) && routes.type) {\n const api = apis[routes.type];\n if (!api) {\n throw new Error(`API ${routes.type} not found. Possible APIs are ${Object.keys(apis)}`);\n }\n\n apis[routes.type].routes(routes);\n return this;\n }\n\n routeManager.addRoutes(routes, router);\n return this;\n },\n\n mount() {\n state.mounted = true;\n\n Object.values(apis).forEach((api) => api.mount(router));\n app.use(router.routes()).use(router.allowedMethods());\n\n return this;\n },\n\n initRouting() {\n registerAllRoutes(strapi);\n\n return this;\n },\n\n async initMiddlewares() {\n await registerApplicationMiddlewares(strapi);\n\n return this;\n },\n\n listRoutes() {\n return [...router.stack];\n },\n\n listen(...args: any[]) {\n if (!state.mounted) {\n this.mount();\n }\n\n return httpServer.listen(...args);\n },\n\n async destroy() {\n await httpServer.destroy();\n },\n };\n};\n\nexport { createServer };\n"],"names":["createKoaApp","requestCtx","Router","createRouteManager","httpServer","createHTTPServer","createContentAPI","createAdminAPI","registerAllRoutes","registerApplicationMiddlewares"],"mappings":";;;;;;;;;;;;;AAYA,MAAM,cAAsC,OAAO,QAAQ;AACrD,MAAA,IAAI,UAAU,oBAAoB;AACtC,MAAI,SAAS;AACf;AAEM,MAAA,eAAe,CAAC,WAA+C;AACnE,QAAM,MAAMA,IAAa;AAAA,IACvB,OAAO,OAAO,OAAO,IAAI,kBAAkB;AAAA,IAC3C,MAAM,OAAO,OAAO,IAAI,iBAAiB;AAAA,EAAA,CAC1C;AAEG,MAAA,IAAI,CAAC,KAAK,SAASC,eAAW,IAAI,KAAK,MAAM,KAAM,CAAA,CAAC;AAElD,QAAA,SAAS,IAAIC,gBAAAA;AAEb,QAAA,eAAeC,2BAAmB,MAAM;AAExC,QAAAC,eAAaC,WAAAA,iBAAiB,QAAQ,GAAG;AAE/C,QAAM,OAAO;AAAA,IACX,eAAeC,4BAAiB,MAAM;AAAA,IACtC,OAAOC,wBAAe,MAAM;AAAA,EAAA;AAIvB,SAAA,IAAI,YAAY,WAAW;AAElC,QAAM,QAAQ;AAAA,IACZ,SAAS;AAAA,EAAA;AAGJ,SAAA;AAAA,IACL;AAAA,IACA;AAAA,IAAA,YACAH;AAAAA,IAEA,IAAI,MAAM;AACR,aAAO,KAAK,IAAI;AAAA,IAClB;AAAA,IAEA,OAAO,MAAM;AACP,UAAA,IAAI,GAAG,IAAI;AACR,aAAA;AAAA,IACT;AAAA,IAEA,OAAO,QAAkD;AACvD,UAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,OAAO,MAAM;AACnC,cAAA,MAAM,KAAK,OAAO,IAAI;AAC5B,YAAI,CAAC,KAAK;AACF,gBAAA,IAAI,MAAM,OAAO,OAAO,IAAI,iCAAiC,OAAO,KAAK,IAAI,CAAC,EAAE;AAAA,QACxF;AAEA,aAAK,OAAO,IAAI,EAAE,OAAO,MAAM;AACxB,eAAA;AAAA,MACT;AAEa,mBAAA,UAAU,QAAQ,MAAM;AAC9B,aAAA;AAAA,IACT;AAAA,IAEA,QAAQ;AACN,YAAM,UAAU;AAET,aAAA,OAAO,IAAI,EAAE,QAAQ,CAAC,QAAQ,IAAI,MAAM,MAAM,CAAC;AAClD,UAAA,IAAI,OAAO,OAAO,CAAC,EAAE,IAAI,OAAO,gBAAgB;AAE7C,aAAA;AAAA,IACT;AAAA,IAEA,cAAc;AACZI,qBAAkB,MAAM;AAEjB,aAAA;AAAA,IACT;AAAA,IAEA,MAAM,kBAAkB;AACtB,YAAMC,oBAA+B,MAAM;AAEpC,aAAA;AAAA,IACT;AAAA,IAEA,aAAa;AACJ,aAAA,CAAC,GAAG,OAAO,KAAK;AAAA,IACzB;AAAA,IAEA,UAAU,MAAa;AACjB,UAAA,CAAC,MAAM,SAAS;AAClB,aAAK,MAAM;AAAA,MACb;AAEO,aAAAL,aAAW,OAAO,GAAG,IAAI;AAAA,IAClC;AAAA,IAEA,MAAM,UAAU;AACd,YAAMA,aAAW;IACnB;AAAA,EAAA;AAEJ;;"}
@@ -13,7 +13,7 @@ const healthCheck = async (ctx) => {
13
13
  };
14
14
  const createServer = (strapi) => {
15
15
  const app = createKoaApp({
16
- proxy: strapi.config.get("server.proxy"),
16
+ proxy: strapi.config.get("server.proxy.koa"),
17
17
  keys: strapi.config.get("server.app.keys")
18
18
  });
19
19
  app.use((ctx, next) => requestCtx.run(ctx, () => next()));
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../../../src/services/server/index.ts"],"sourcesContent":["import Router from '@koa/router';\nimport type { Core, Modules } from '@strapi/types';\n\nimport { createHTTPServer } from './http-server';\nimport { createRouteManager } from './routing';\nimport { createAdminAPI } from './admin-api';\nimport { createContentAPI } from './content-api';\nimport registerAllRoutes from './register-routes';\nimport registerApplicationMiddlewares from './register-middlewares';\nimport createKoaApp from './koa';\nimport requestCtx from '../request-context';\n\nconst healthCheck: Core.MiddlewareHandler = async (ctx) => {\n ctx.set('strapi', 'You are so French!');\n ctx.status = 204;\n};\n\nconst createServer = (strapi: Core.Strapi): Modules.Server.Server => {\n const app = createKoaApp({\n proxy: strapi.config.get('server.proxy'),\n keys: strapi.config.get('server.app.keys'),\n });\n\n app.use((ctx, next) => requestCtx.run(ctx, () => next()));\n\n const router = new Router();\n\n const routeManager = createRouteManager(strapi);\n\n const httpServer = createHTTPServer(strapi, app);\n\n const apis = {\n 'content-api': createContentAPI(strapi),\n admin: createAdminAPI(strapi),\n };\n\n // init health check\n router.all('/_health', healthCheck);\n\n const state = {\n mounted: false,\n };\n\n return {\n app,\n router,\n httpServer,\n\n api(name) {\n return apis[name];\n },\n\n use(...args) {\n app.use(...args);\n return this;\n },\n\n routes(routes: Core.Router | Omit<Core.Route, 'info'>[]) {\n if (!Array.isArray(routes) && routes.type) {\n const api = apis[routes.type];\n if (!api) {\n throw new Error(`API ${routes.type} not found. Possible APIs are ${Object.keys(apis)}`);\n }\n\n apis[routes.type].routes(routes);\n return this;\n }\n\n routeManager.addRoutes(routes, router);\n return this;\n },\n\n mount() {\n state.mounted = true;\n\n Object.values(apis).forEach((api) => api.mount(router));\n app.use(router.routes()).use(router.allowedMethods());\n\n return this;\n },\n\n initRouting() {\n registerAllRoutes(strapi);\n\n return this;\n },\n\n async initMiddlewares() {\n await registerApplicationMiddlewares(strapi);\n\n return this;\n },\n\n listRoutes() {\n return [...router.stack];\n },\n\n listen(...args: any[]) {\n if (!state.mounted) {\n this.mount();\n }\n\n return httpServer.listen(...args);\n },\n\n async destroy() {\n await httpServer.destroy();\n },\n };\n};\n\nexport { createServer };\n"],"names":[],"mappings":";;;;;;;;;AAYA,MAAM,cAAsC,OAAO,QAAQ;AACrD,MAAA,IAAI,UAAU,oBAAoB;AACtC,MAAI,SAAS;AACf;AAEM,MAAA,eAAe,CAAC,WAA+C;AACnE,QAAM,MAAM,aAAa;AAAA,IACvB,OAAO,OAAO,OAAO,IAAI,cAAc;AAAA,IACvC,MAAM,OAAO,OAAO,IAAI,iBAAiB;AAAA,EAAA,CAC1C;AAEG,MAAA,IAAI,CAAC,KAAK,SAAS,WAAW,IAAI,KAAK,MAAM,KAAM,CAAA,CAAC;AAElD,QAAA,SAAS,IAAI;AAEb,QAAA,eAAe,mBAAmB,MAAM;AAExC,QAAA,aAAa,iBAAiB,QAAQ,GAAG;AAE/C,QAAM,OAAO;AAAA,IACX,eAAe,iBAAiB,MAAM;AAAA,IACtC,OAAO,eAAe,MAAM;AAAA,EAAA;AAIvB,SAAA,IAAI,YAAY,WAAW;AAElC,QAAM,QAAQ;AAAA,IACZ,SAAS;AAAA,EAAA;AAGJ,SAAA;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IAEA,IAAI,MAAM;AACR,aAAO,KAAK,IAAI;AAAA,IAClB;AAAA,IAEA,OAAO,MAAM;AACP,UAAA,IAAI,GAAG,IAAI;AACR,aAAA;AAAA,IACT;AAAA,IAEA,OAAO,QAAkD;AACvD,UAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,OAAO,MAAM;AACnC,cAAA,MAAM,KAAK,OAAO,IAAI;AAC5B,YAAI,CAAC,KAAK;AACF,gBAAA,IAAI,MAAM,OAAO,OAAO,IAAI,iCAAiC,OAAO,KAAK,IAAI,CAAC,EAAE;AAAA,QACxF;AAEA,aAAK,OAAO,IAAI,EAAE,OAAO,MAAM;AACxB,eAAA;AAAA,MACT;AAEa,mBAAA,UAAU,QAAQ,MAAM;AAC9B,aAAA;AAAA,IACT;AAAA,IAEA,QAAQ;AACN,YAAM,UAAU;AAET,aAAA,OAAO,IAAI,EAAE,QAAQ,CAAC,QAAQ,IAAI,MAAM,MAAM,CAAC;AAClD,UAAA,IAAI,OAAO,OAAO,CAAC,EAAE,IAAI,OAAO,gBAAgB;AAE7C,aAAA;AAAA,IACT;AAAA,IAEA,cAAc;AACZ,wBAAkB,MAAM;AAEjB,aAAA;AAAA,IACT;AAAA,IAEA,MAAM,kBAAkB;AACtB,YAAM,+BAA+B,MAAM;AAEpC,aAAA;AAAA,IACT;AAAA,IAEA,aAAa;AACJ,aAAA,CAAC,GAAG,OAAO,KAAK;AAAA,IACzB;AAAA,IAEA,UAAU,MAAa;AACjB,UAAA,CAAC,MAAM,SAAS;AAClB,aAAK,MAAM;AAAA,MACb;AAEO,aAAA,WAAW,OAAO,GAAG,IAAI;AAAA,IAClC;AAAA,IAEA,MAAM,UAAU;AACd,YAAM,WAAW;IACnB;AAAA,EAAA;AAEJ;"}
1
+ {"version":3,"file":"index.mjs","sources":["../../../src/services/server/index.ts"],"sourcesContent":["import Router from '@koa/router';\nimport type { Core, Modules } from '@strapi/types';\n\nimport { createHTTPServer } from './http-server';\nimport { createRouteManager } from './routing';\nimport { createAdminAPI } from './admin-api';\nimport { createContentAPI } from './content-api';\nimport registerAllRoutes from './register-routes';\nimport registerApplicationMiddlewares from './register-middlewares';\nimport createKoaApp from './koa';\nimport requestCtx from '../request-context';\n\nconst healthCheck: Core.MiddlewareHandler = async (ctx) => {\n ctx.set('strapi', 'You are so French!');\n ctx.status = 204;\n};\n\nconst createServer = (strapi: Core.Strapi): Modules.Server.Server => {\n const app = createKoaApp({\n proxy: strapi.config.get('server.proxy.koa'),\n keys: strapi.config.get('server.app.keys'),\n });\n\n app.use((ctx, next) => requestCtx.run(ctx, () => next()));\n\n const router = new Router();\n\n const routeManager = createRouteManager(strapi);\n\n const httpServer = createHTTPServer(strapi, app);\n\n const apis = {\n 'content-api': createContentAPI(strapi),\n admin: createAdminAPI(strapi),\n };\n\n // init health check\n router.all('/_health', healthCheck);\n\n const state = {\n mounted: false,\n };\n\n return {\n app,\n router,\n httpServer,\n\n api(name) {\n return apis[name];\n },\n\n use(...args) {\n app.use(...args);\n return this;\n },\n\n routes(routes: Core.Router | Omit<Core.Route, 'info'>[]) {\n if (!Array.isArray(routes) && routes.type) {\n const api = apis[routes.type];\n if (!api) {\n throw new Error(`API ${routes.type} not found. Possible APIs are ${Object.keys(apis)}`);\n }\n\n apis[routes.type].routes(routes);\n return this;\n }\n\n routeManager.addRoutes(routes, router);\n return this;\n },\n\n mount() {\n state.mounted = true;\n\n Object.values(apis).forEach((api) => api.mount(router));\n app.use(router.routes()).use(router.allowedMethods());\n\n return this;\n },\n\n initRouting() {\n registerAllRoutes(strapi);\n\n return this;\n },\n\n async initMiddlewares() {\n await registerApplicationMiddlewares(strapi);\n\n return this;\n },\n\n listRoutes() {\n return [...router.stack];\n },\n\n listen(...args: any[]) {\n if (!state.mounted) {\n this.mount();\n }\n\n return httpServer.listen(...args);\n },\n\n async destroy() {\n await httpServer.destroy();\n },\n };\n};\n\nexport { createServer };\n"],"names":[],"mappings":";;;;;;;;;AAYA,MAAM,cAAsC,OAAO,QAAQ;AACrD,MAAA,IAAI,UAAU,oBAAoB;AACtC,MAAI,SAAS;AACf;AAEM,MAAA,eAAe,CAAC,WAA+C;AACnE,QAAM,MAAM,aAAa;AAAA,IACvB,OAAO,OAAO,OAAO,IAAI,kBAAkB;AAAA,IAC3C,MAAM,OAAO,OAAO,IAAI,iBAAiB;AAAA,EAAA,CAC1C;AAEG,MAAA,IAAI,CAAC,KAAK,SAAS,WAAW,IAAI,KAAK,MAAM,KAAM,CAAA,CAAC;AAElD,QAAA,SAAS,IAAI;AAEb,QAAA,eAAe,mBAAmB,MAAM;AAExC,QAAA,aAAa,iBAAiB,QAAQ,GAAG;AAE/C,QAAM,OAAO;AAAA,IACX,eAAe,iBAAiB,MAAM;AAAA,IACtC,OAAO,eAAe,MAAM;AAAA,EAAA;AAIvB,SAAA,IAAI,YAAY,WAAW;AAElC,QAAM,QAAQ;AAAA,IACZ,SAAS;AAAA,EAAA;AAGJ,SAAA;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IAEA,IAAI,MAAM;AACR,aAAO,KAAK,IAAI;AAAA,IAClB;AAAA,IAEA,OAAO,MAAM;AACP,UAAA,IAAI,GAAG,IAAI;AACR,aAAA;AAAA,IACT;AAAA,IAEA,OAAO,QAAkD;AACvD,UAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,OAAO,MAAM;AACnC,cAAA,MAAM,KAAK,OAAO,IAAI;AAC5B,YAAI,CAAC,KAAK;AACF,gBAAA,IAAI,MAAM,OAAO,OAAO,IAAI,iCAAiC,OAAO,KAAK,IAAI,CAAC,EAAE;AAAA,QACxF;AAEA,aAAK,OAAO,IAAI,EAAE,OAAO,MAAM;AACxB,eAAA;AAAA,MACT;AAEa,mBAAA,UAAU,QAAQ,MAAM;AAC9B,aAAA;AAAA,IACT;AAAA,IAEA,QAAQ;AACN,YAAM,UAAU;AAET,aAAA,OAAO,IAAI,EAAE,QAAQ,CAAC,QAAQ,IAAI,MAAM,MAAM,CAAC;AAClD,UAAA,IAAI,OAAO,OAAO,CAAC,EAAE,IAAI,OAAO,gBAAgB;AAE7C,aAAA;AAAA,IACT;AAAA,IAEA,cAAc;AACZ,wBAAkB,MAAM;AAEjB,aAAA;AAAA,IACT;AAAA,IAEA,MAAM,kBAAkB;AACtB,YAAM,+BAA+B,MAAM;AAEpC,aAAA;AAAA,IACT;AAAA,IAEA,aAAa;AACJ,aAAA,CAAC,GAAG,OAAO,KAAK;AAAA,IACzB;AAAA,IAEA,UAAU,MAAa;AACjB,UAAA,CAAC,MAAM,SAAS;AAClB,aAAK,MAAM;AAAA,MACb;AAEO,aAAA,WAAW,OAAO,GAAG,IAAI;AAAA,IAClC;AAAA,IAEA,MAAM,UAAU;AACd,YAAM,WAAW;IACnB;AAAA,EAAA;AAEJ;"}
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/utils/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAMnD,eAAO,MAAM,iBAAiB,WAAY,KAAK,MAAM,KAAG,aAAa,MAkBpE,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC"}
1
+ {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/utils/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAMnD,eAAO,MAAM,iBAAiB,WAAY,KAAK,MAAM,KAAG,aAAa,MAoBpE,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC"}
@@ -10,9 +10,10 @@ const createStrapiFetch = (strapi) => {
10
10
  strapi.log.debug(`Making request for ${url}`);
11
11
  return fetch(url, fetchOptions);
12
12
  }
13
- const globalProxy = strapi.config.get("server.globalProxy");
14
- if (globalProxy) {
15
- strapiFetch.dispatcher = new undici.ProxyAgent(globalProxy);
13
+ const proxy = strapi.config.get("server.proxy.fetch") || strapi.config.get("server.proxy.global");
14
+ if (proxy) {
15
+ strapi.log.info(`Using proxy for Fetch requests: ${proxy}`);
16
+ strapiFetch.dispatcher = new undici.ProxyAgent(proxy);
16
17
  }
17
18
  return strapiFetch;
18
19
  };
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.js","sources":["../../src/utils/fetch.ts"],"sourcesContent":["import type { Core, Modules } from '@strapi/types';\nimport { ProxyAgent } from 'undici';\n\n// TODO: once core Node exposes a stable way to create a ProxyAgent we will use that instead of undici\n\n// Create a wrapper for Node's Fetch API that applies a global proxy\nexport const createStrapiFetch = (strapi: Core.Strapi): Modules.Fetch.Fetch => {\n function strapiFetch(url: RequestInfo | URL, options?: RequestInit) {\n const fetchOptions = {\n ...(strapiFetch.dispatcher ? { dispatcher: strapiFetch.dispatcher } : {}),\n ...options,\n };\n strapi.log.debug(`Making request for ${url}`);\n return fetch(url, fetchOptions);\n }\n\n const globalProxy =\n strapi.config.get<ConstructorParameters<typeof ProxyAgent>[0]>('server.globalProxy');\n\n if (globalProxy) {\n strapiFetch.dispatcher = new ProxyAgent(globalProxy);\n }\n\n return strapiFetch;\n};\n\nexport type Fetch = Modules.Fetch.Fetch;\n"],"names":["ProxyAgent"],"mappings":";;;AAMa,MAAA,oBAAoB,CAAC,WAA6C;AACpE,WAAA,YAAY,KAAwB,SAAuB;AAClE,UAAM,eAAe;AAAA,MACnB,GAAI,YAAY,aAAa,EAAE,YAAY,YAAY,WAAA,IAAe,CAAC;AAAA,MACvE,GAAG;AAAA,IAAA;AAEL,WAAO,IAAI,MAAM,sBAAsB,GAAG,EAAE;AACrC,WAAA,MAAM,KAAK,YAAY;AAAA,EAChC;AAEA,QAAM,cACJ,OAAO,OAAO,IAAiD,oBAAoB;AAErF,MAAI,aAAa;AACH,gBAAA,aAAa,IAAIA,OAAA,WAAW,WAAW;AAAA,EACrD;AAEO,SAAA;AACT;;"}
1
+ {"version":3,"file":"fetch.js","sources":["../../src/utils/fetch.ts"],"sourcesContent":["import type { Core, Modules } from '@strapi/types';\nimport { ProxyAgent } from 'undici';\n\n// TODO: once core Node exposes a stable way to create a ProxyAgent we will use that instead of undici\n\n// Create a wrapper for Node's Fetch API that applies a global proxy\nexport const createStrapiFetch = (strapi: Core.Strapi): Modules.Fetch.Fetch => {\n function strapiFetch(url: RequestInfo | URL, options?: RequestInit) {\n const fetchOptions = {\n ...(strapiFetch.dispatcher ? { dispatcher: strapiFetch.dispatcher } : {}),\n ...options,\n };\n strapi.log.debug(`Making request for ${url}`);\n return fetch(url, fetchOptions);\n }\n\n const proxy =\n strapi.config.get<ConstructorParameters<typeof ProxyAgent>[0]>('server.proxy.fetch') ||\n strapi.config.get<string>('server.proxy.global');\n\n if (proxy) {\n strapi.log.info(`Using proxy for Fetch requests: ${proxy}`);\n strapiFetch.dispatcher = new ProxyAgent(proxy);\n }\n\n return strapiFetch;\n};\n\nexport type Fetch = Modules.Fetch.Fetch;\n"],"names":["ProxyAgent"],"mappings":";;;AAMa,MAAA,oBAAoB,CAAC,WAA6C;AACpE,WAAA,YAAY,KAAwB,SAAuB;AAClE,UAAM,eAAe;AAAA,MACnB,GAAI,YAAY,aAAa,EAAE,YAAY,YAAY,WAAA,IAAe,CAAC;AAAA,MACvE,GAAG;AAAA,IAAA;AAEL,WAAO,IAAI,MAAM,sBAAsB,GAAG,EAAE;AACrC,WAAA,MAAM,KAAK,YAAY;AAAA,EAChC;AAEM,QAAA,QACJ,OAAO,OAAO,IAAiD,oBAAoB,KACnF,OAAO,OAAO,IAAY,qBAAqB;AAEjD,MAAI,OAAO;AACT,WAAO,IAAI,KAAK,mCAAmC,KAAK,EAAE;AAC9C,gBAAA,aAAa,IAAIA,OAAA,WAAW,KAAK;AAAA,EAC/C;AAEO,SAAA;AACT;;"}
@@ -8,9 +8,10 @@ const createStrapiFetch = (strapi) => {
8
8
  strapi.log.debug(`Making request for ${url}`);
9
9
  return fetch(url, fetchOptions);
10
10
  }
11
- const globalProxy = strapi.config.get("server.globalProxy");
12
- if (globalProxy) {
13
- strapiFetch.dispatcher = new ProxyAgent(globalProxy);
11
+ const proxy = strapi.config.get("server.proxy.fetch") || strapi.config.get("server.proxy.global");
12
+ if (proxy) {
13
+ strapi.log.info(`Using proxy for Fetch requests: ${proxy}`);
14
+ strapiFetch.dispatcher = new ProxyAgent(proxy);
14
15
  }
15
16
  return strapiFetch;
16
17
  };
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.mjs","sources":["../../src/utils/fetch.ts"],"sourcesContent":["import type { Core, Modules } from '@strapi/types';\nimport { ProxyAgent } from 'undici';\n\n// TODO: once core Node exposes a stable way to create a ProxyAgent we will use that instead of undici\n\n// Create a wrapper for Node's Fetch API that applies a global proxy\nexport const createStrapiFetch = (strapi: Core.Strapi): Modules.Fetch.Fetch => {\n function strapiFetch(url: RequestInfo | URL, options?: RequestInit) {\n const fetchOptions = {\n ...(strapiFetch.dispatcher ? { dispatcher: strapiFetch.dispatcher } : {}),\n ...options,\n };\n strapi.log.debug(`Making request for ${url}`);\n return fetch(url, fetchOptions);\n }\n\n const globalProxy =\n strapi.config.get<ConstructorParameters<typeof ProxyAgent>[0]>('server.globalProxy');\n\n if (globalProxy) {\n strapiFetch.dispatcher = new ProxyAgent(globalProxy);\n }\n\n return strapiFetch;\n};\n\nexport type Fetch = Modules.Fetch.Fetch;\n"],"names":[],"mappings":";AAMa,MAAA,oBAAoB,CAAC,WAA6C;AACpE,WAAA,YAAY,KAAwB,SAAuB;AAClE,UAAM,eAAe;AAAA,MACnB,GAAI,YAAY,aAAa,EAAE,YAAY,YAAY,WAAA,IAAe,CAAC;AAAA,MACvE,GAAG;AAAA,IAAA;AAEL,WAAO,IAAI,MAAM,sBAAsB,GAAG,EAAE;AACrC,WAAA,MAAM,KAAK,YAAY;AAAA,EAChC;AAEA,QAAM,cACJ,OAAO,OAAO,IAAiD,oBAAoB;AAErF,MAAI,aAAa;AACH,gBAAA,aAAa,IAAI,WAAW,WAAW;AAAA,EACrD;AAEO,SAAA;AACT;"}
1
+ {"version":3,"file":"fetch.mjs","sources":["../../src/utils/fetch.ts"],"sourcesContent":["import type { Core, Modules } from '@strapi/types';\nimport { ProxyAgent } from 'undici';\n\n// TODO: once core Node exposes a stable way to create a ProxyAgent we will use that instead of undici\n\n// Create a wrapper for Node's Fetch API that applies a global proxy\nexport const createStrapiFetch = (strapi: Core.Strapi): Modules.Fetch.Fetch => {\n function strapiFetch(url: RequestInfo | URL, options?: RequestInit) {\n const fetchOptions = {\n ...(strapiFetch.dispatcher ? { dispatcher: strapiFetch.dispatcher } : {}),\n ...options,\n };\n strapi.log.debug(`Making request for ${url}`);\n return fetch(url, fetchOptions);\n }\n\n const proxy =\n strapi.config.get<ConstructorParameters<typeof ProxyAgent>[0]>('server.proxy.fetch') ||\n strapi.config.get<string>('server.proxy.global');\n\n if (proxy) {\n strapi.log.info(`Using proxy for Fetch requests: ${proxy}`);\n strapiFetch.dispatcher = new ProxyAgent(proxy);\n }\n\n return strapiFetch;\n};\n\nexport type Fetch = Modules.Fetch.Fetch;\n"],"names":[],"mappings":";AAMa,MAAA,oBAAoB,CAAC,WAA6C;AACpE,WAAA,YAAY,KAAwB,SAAuB;AAClE,UAAM,eAAe;AAAA,MACnB,GAAI,YAAY,aAAa,EAAE,YAAY,YAAY,WAAA,IAAe,CAAC;AAAA,MACvE,GAAG;AAAA,IAAA;AAEL,WAAO,IAAI,MAAM,sBAAsB,GAAG,EAAE;AACrC,WAAA,MAAM,KAAK,YAAY;AAAA,EAChC;AAEM,QAAA,QACJ,OAAO,OAAO,IAAiD,oBAAoB,KACnF,OAAO,OAAO,IAAY,qBAAqB;AAEjD,MAAI,OAAO;AACT,WAAO,IAAI,KAAK,mCAAmC,KAAK,EAAE;AAC9C,gBAAA,aAAa,IAAI,WAAW,KAAK;AAAA,EAC/C;AAEO,SAAA;AACT;"}