@strapi/content-manager 5.44.0 → 5.45.0

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.
Files changed (66) hide show
  1. package/dist/admin/index.js.map +1 -1
  2. package/dist/admin/index.mjs.map +1 -1
  3. package/dist/admin/pages/EditView/utils/data.js +8 -0
  4. package/dist/admin/pages/EditView/utils/data.js.map +1 -1
  5. package/dist/admin/pages/EditView/utils/data.mjs +8 -0
  6. package/dist/admin/pages/EditView/utils/data.mjs.map +1 -1
  7. package/dist/admin/pages/ListView/ListViewPage.js +17 -2
  8. package/dist/admin/pages/ListView/ListViewPage.js.map +1 -1
  9. package/dist/admin/pages/ListView/ListViewPage.mjs +17 -2
  10. package/dist/admin/pages/ListView/ListViewPage.mjs.map +1 -1
  11. package/dist/admin/src/index.d.ts +2 -1
  12. package/dist/server/controllers/collection-types.js +78 -1
  13. package/dist/server/controllers/collection-types.js.map +1 -1
  14. package/dist/server/controllers/collection-types.mjs +78 -1
  15. package/dist/server/controllers/collection-types.mjs.map +1 -1
  16. package/dist/server/controllers/validation/dimensions.js +17 -18
  17. package/dist/server/controllers/validation/dimensions.js.map +1 -1
  18. package/dist/server/controllers/validation/dimensions.mjs +18 -19
  19. package/dist/server/controllers/validation/dimensions.mjs.map +1 -1
  20. package/dist/server/controllers/validation/index.js +25 -23
  21. package/dist/server/controllers/validation/index.js.map +1 -1
  22. package/dist/server/controllers/validation/index.mjs +26 -24
  23. package/dist/server/controllers/validation/index.mjs.map +1 -1
  24. package/dist/server/controllers/validation/relations.js +21 -24
  25. package/dist/server/controllers/validation/relations.js.map +1 -1
  26. package/dist/server/controllers/validation/relations.mjs +22 -25
  27. package/dist/server/controllers/validation/relations.mjs.map +1 -1
  28. package/dist/server/history/controllers/validation/history-version.js +4 -24
  29. package/dist/server/history/controllers/validation/history-version.js.map +1 -1
  30. package/dist/server/history/controllers/validation/history-version.mjs +5 -6
  31. package/dist/server/history/controllers/validation/history-version.mjs.map +1 -1
  32. package/dist/server/history/services/lifecycles.js +1 -1
  33. package/dist/server/history/services/lifecycles.js.map +1 -1
  34. package/dist/server/history/services/lifecycles.mjs +1 -1
  35. package/dist/server/history/services/lifecycles.mjs.map +1 -1
  36. package/dist/server/homepage/controllers/homepage.js +6 -26
  37. package/dist/server/homepage/controllers/homepage.js.map +1 -1
  38. package/dist/server/homepage/controllers/homepage.mjs +7 -8
  39. package/dist/server/homepage/controllers/homepage.mjs.map +1 -1
  40. package/dist/server/preview/controllers/validation/preview.js +6 -26
  41. package/dist/server/preview/controllers/validation/preview.js.map +1 -1
  42. package/dist/server/preview/controllers/validation/preview.mjs +7 -8
  43. package/dist/server/preview/controllers/validation/preview.mjs.map +1 -1
  44. package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
  45. package/dist/server/src/controllers/validation/dimensions.d.ts.map +1 -1
  46. package/dist/server/src/controllers/validation/index.d.ts +16 -15
  47. package/dist/server/src/controllers/validation/index.d.ts.map +1 -1
  48. package/dist/server/src/controllers/validation/relations.d.ts +17 -2
  49. package/dist/server/src/controllers/validation/relations.d.ts.map +1 -1
  50. package/dist/server/src/history/controllers/validation/history-version.d.ts +3 -1
  51. package/dist/server/src/history/controllers/validation/history-version.d.ts.map +1 -1
  52. package/dist/server/src/homepage/controllers/homepage.d.ts.map +1 -1
  53. package/dist/server/src/preview/controllers/validation/preview.d.ts.map +1 -1
  54. package/dist/server/src/validation/policies/hasPermissions.d.ts +4 -1
  55. package/dist/server/src/validation/policies/hasPermissions.d.ts.map +1 -1
  56. package/dist/server/src/validation/zod.d.ts +34 -0
  57. package/dist/server/src/validation/zod.d.ts.map +1 -0
  58. package/dist/server/validation/policies/hasPermissions.js +4 -4
  59. package/dist/server/validation/policies/hasPermissions.js.map +1 -1
  60. package/dist/server/validation/policies/hasPermissions.mjs +5 -5
  61. package/dist/server/validation/policies/hasPermissions.mjs.map +1 -1
  62. package/dist/server/validation/zod.js +60 -0
  63. package/dist/server/validation/zod.js.map +1 -0
  64. package/dist/server/validation/zod.mjs +56 -0
  65. package/dist/server/validation/zod.mjs.map +1 -0
  66. package/package.json +5 -5
@@ -1,5 +1,6 @@
1
1
  import _ from 'lodash';
2
- import { errors, yup, validateYupSchema } from '@strapi/utils';
2
+ import { errors, z } from '@strapi/utils';
3
+ import { strapiID, validateZodAsync } from '../../validation/zod.mjs';
3
4
  import '@strapi/types';
4
5
  import '../../services/utils/configuration/attributes.mjs';
5
6
  import '../../services/utils/configuration/settings.mjs';
@@ -11,22 +12,25 @@ const TYPES = [
11
12
  ];
12
13
  /**
13
14
  * Validates type kind
14
- */ const kindSchema = yup.string().oneOf(TYPES).nullable();
15
- const bulkActionInputSchema = yup.object({
16
- documentIds: yup.array().of(yup.strapiID()).min(1).required()
17
- }).required();
18
- const generateUIDInputSchema = yup.object({
19
- contentTypeUID: yup.string().required(),
20
- field: yup.string().required(),
21
- data: yup.object().required()
15
+ */ const kindSchema = z.enum(TYPES).nullable().optional();
16
+ const bulkActionInputSchema = z.object({
17
+ documentIds: z.array(strapiID).min(1)
22
18
  });
23
- const checkUIDAvailabilityInputSchema = yup.object({
24
- contentTypeUID: yup.string().required(),
25
- field: yup.string().required(),
26
- value: yup.string().required().test('isValueMatchingRegex', `\${path} must match the custom regex or the default one "/^[A-Za-z0-9-_.~]*$/"`, function(value, context) {
27
- return value === '' || (context.options.context?.regex ? new RegExp(context.options?.context.regex).test(value) : /^[A-Za-z0-9-_.~]*$/.test(value));
28
- })
19
+ const generateUIDInputSchema = z.object({
20
+ contentTypeUID: z.string(),
21
+ field: z.string(),
22
+ data: z.looseObject({})
29
23
  });
24
+ const createCheckUIDAvailabilityInputSchema = (regex)=>{
25
+ const pattern = regex ? new RegExp(regex) : /^[A-Za-z0-9-_.~]*$/;
26
+ return z.object({
27
+ contentTypeUID: z.string(),
28
+ field: z.string(),
29
+ value: z.string().refine((value)=>value === '' || pattern.test(value), {
30
+ error: `Must match the custom regex or the default one "/^[A-Za-z0-9-_.~]*$/"`
31
+ })
32
+ });
33
+ };
30
34
  const validateUIDField = (contentTypeUID, field)=>{
31
35
  const model = strapi.contentTypes[contentTypeUID];
32
36
  if (!model) {
@@ -43,19 +47,17 @@ const validateUIDField = (contentTypeUID, field)=>{
43
47
  throw new ValidationError(`${field} must be a valid \`uid\` attribute`);
44
48
  }
45
49
  };
46
- const validateKind = validateYupSchema(kindSchema);
47
- const validateBulkActionInput = validateYupSchema(bulkActionInputSchema);
48
- const validateGenerateUIDInput = validateYupSchema(generateUIDInputSchema);
50
+ const validateKind = validateZodAsync(kindSchema);
51
+ const validateBulkActionInput = validateZodAsync(bulkActionInputSchema);
52
+ const validateGenerateUIDInput = validateZodAsync(generateUIDInputSchema);
49
53
  const validateCheckUIDAvailabilityInput = (body)=>{
50
- const options = {};
54
+ let regex;
51
55
  const contentType = body.contentTypeUID in strapi.contentTypes ? strapi.contentTypes[body.contentTypeUID] : null;
52
56
  if (contentType?.attributes[body.field] && `regex` in contentType.attributes[body.field] && contentType.attributes[body.field].regex) {
53
- options.context = {
54
- regex: (contentType?.attributes[body.field]).regex
55
- };
57
+ regex = (contentType?.attributes[body.field]).regex;
56
58
  }
57
- const validator = validateYupSchema(checkUIDAvailabilityInputSchema, options);
58
- return validator(body);
59
+ const schema = createCheckUIDAvailabilityInputSchema(regex);
60
+ return validateZodAsync(schema)(body);
59
61
  };
60
62
 
61
63
  export { validateBulkActionInput, validateCheckUIDAvailabilityInput, validateGenerateUIDInput, validateKind, validateUIDField };
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../../../../server/src/controllers/validation/index.ts"],"sourcesContent":["import _ from 'lodash';\nimport { Schema, UID } from '@strapi/types';\nimport { yup, validateYupSchema, errors } from '@strapi/utils';\nimport { ValidateOptions } from 'yup/lib/types';\nimport { TestContext } from 'yup';\nimport createModelConfigurationSchema from './model-configuration';\n\nconst { PaginationError, ValidationError } = errors;\nconst TYPES = ['singleType', 'collectionType'];\n\n/**\n * Validates type kind\n */\nconst kindSchema = yup.string().oneOf(TYPES).nullable();\n\nconst bulkActionInputSchema = yup\n .object({\n documentIds: yup.array().of(yup.strapiID()).min(1).required(),\n })\n .required();\n\nconst generateUIDInputSchema = yup.object({\n contentTypeUID: yup.string().required(),\n field: yup.string().required(),\n data: yup.object().required(),\n});\n\nconst checkUIDAvailabilityInputSchema = yup.object({\n contentTypeUID: yup.string().required(),\n field: yup.string().required(),\n value: yup\n .string()\n .required()\n .test(\n 'isValueMatchingRegex',\n `\\${path} must match the custom regex or the default one \"/^[A-Za-z0-9-_.~]*$/\"`,\n function (value, context: TestContext<{ regex?: string }>) {\n return (\n value === '' ||\n (context.options.context?.regex\n ? new RegExp(context.options?.context.regex).test(value as string)\n : /^[A-Za-z0-9-_.~]*$/.test(value as string))\n );\n }\n ),\n});\n\nconst validateUIDField = (contentTypeUID: any, field: any) => {\n const model = strapi.contentTypes[contentTypeUID];\n\n if (!model) {\n throw new ValidationError('ContentType not found');\n }\n\n if (\n !_.has(model, ['attributes', field]) ||\n _.get(model, ['attributes', field, 'type']) !== 'uid'\n ) {\n throw new ValidationError(`${field} must be a valid \\`uid\\` attribute`);\n }\n};\n\nconst validatePagination = ({ page, pageSize }: any) => {\n const pageNumber = parseInt(page, 10);\n const pageSizeNumber = parseInt(pageSize, 10);\n\n if (Number.isNaN(pageNumber) || pageNumber < 1) {\n throw new PaginationError('invalid pageNumber param');\n }\n if (Number.isNaN(pageSizeNumber) || pageSizeNumber < 1) {\n throw new PaginationError('invalid pageSize param');\n }\n};\n\nconst validateKind = validateYupSchema(kindSchema);\nconst validateBulkActionInput = validateYupSchema(bulkActionInputSchema);\nconst validateGenerateUIDInput = validateYupSchema(generateUIDInputSchema);\nconst validateCheckUIDAvailabilityInput = (body: {\n contentTypeUID: UID.ContentType;\n field: string;\n value: string;\n}) => {\n const options: ValidateOptions<{ regex?: string }> = {};\n\n const contentType =\n body.contentTypeUID in strapi.contentTypes ? strapi.contentTypes[body.contentTypeUID] : null;\n\n if (\n contentType?.attributes[body.field] &&\n `regex` in contentType.attributes[body.field] &&\n (contentType.attributes[body.field] as Schema.Attribute.UID).regex\n ) {\n options.context = {\n regex: (contentType?.attributes[body.field] as Schema.Attribute.UID).regex,\n };\n }\n\n const validator = validateYupSchema(checkUIDAvailabilityInputSchema, options);\n\n return validator(body);\n};\n\nexport {\n createModelConfigurationSchema,\n validateUIDField,\n validatePagination,\n validateKind,\n validateBulkActionInput,\n validateGenerateUIDInput,\n validateCheckUIDAvailabilityInput,\n};\n"],"names":["PaginationError","ValidationError","errors","TYPES","kindSchema","yup","string","oneOf","nullable","bulkActionInputSchema","object","documentIds","array","of","strapiID","min","required","generateUIDInputSchema","contentTypeUID","field","data","checkUIDAvailabilityInputSchema","value","test","context","options","regex","RegExp","validateUIDField","model","strapi","contentTypes","_","has","get","validateKind","validateYupSchema","validateBulkActionInput","validateGenerateUIDInput","validateCheckUIDAvailabilityInput","body","contentType","attributes","validator"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../../../../server/src/controllers/validation/index.ts"],"sourcesContent":["import _ from 'lodash';\nimport { Schema, UID } from '@strapi/types';\nimport { z, errors } from '@strapi/utils';\nimport { validateZodAsync, strapiID } from '../../validation/zod';\nimport createModelConfigurationSchema from './model-configuration';\n\nconst { PaginationError, ValidationError } = errors;\nconst TYPES = ['singleType', 'collectionType'] as const;\n\n/**\n * Validates type kind\n */\nconst kindSchema = z.enum(TYPES).nullable().optional();\n\nconst bulkActionInputSchema = z.object({\n documentIds: z.array(strapiID).min(1),\n});\n\nconst generateUIDInputSchema = z.object({\n contentTypeUID: z.string(),\n field: z.string(),\n data: z.looseObject({}),\n});\n\nconst createCheckUIDAvailabilityInputSchema = (regex?: string) => {\n const pattern = regex ? new RegExp(regex) : /^[A-Za-z0-9-_.~]*$/;\n return z.object({\n contentTypeUID: z.string(),\n field: z.string(),\n value: z.string().refine((value) => value === '' || pattern.test(value), {\n error: `Must match the custom regex or the default one \"/^[A-Za-z0-9-_.~]*$/\"`,\n }),\n });\n};\n\nconst validateUIDField = (contentTypeUID: any, field: any) => {\n const model = strapi.contentTypes[contentTypeUID];\n\n if (!model) {\n throw new ValidationError('ContentType not found');\n }\n\n if (\n !_.has(model, ['attributes', field]) ||\n _.get(model, ['attributes', field, 'type']) !== 'uid'\n ) {\n throw new ValidationError(`${field} must be a valid \\`uid\\` attribute`);\n }\n};\n\nconst validatePagination = ({ page, pageSize }: any) => {\n const pageNumber = parseInt(page, 10);\n const pageSizeNumber = parseInt(pageSize, 10);\n\n if (Number.isNaN(pageNumber) || pageNumber < 1) {\n throw new PaginationError('invalid pageNumber param');\n }\n if (Number.isNaN(pageSizeNumber) || pageSizeNumber < 1) {\n throw new PaginationError('invalid pageSize param');\n }\n};\n\nconst validateKind = validateZodAsync(kindSchema);\nconst validateBulkActionInput = validateZodAsync(bulkActionInputSchema);\nconst validateGenerateUIDInput = validateZodAsync(generateUIDInputSchema);\nconst validateCheckUIDAvailabilityInput = (body: {\n contentTypeUID: UID.ContentType;\n field: string;\n value: string;\n}) => {\n let regex: string | undefined;\n\n const contentType =\n body.contentTypeUID in strapi.contentTypes ? strapi.contentTypes[body.contentTypeUID] : null;\n\n if (\n contentType?.attributes[body.field] &&\n `regex` in contentType.attributes[body.field] &&\n (contentType.attributes[body.field] as Schema.Attribute.UID).regex\n ) {\n regex = (contentType?.attributes[body.field] as Schema.Attribute.UID).regex;\n }\n\n const schema = createCheckUIDAvailabilityInputSchema(regex);\n return validateZodAsync(schema)(body);\n};\n\nexport {\n createModelConfigurationSchema,\n validateUIDField,\n validatePagination,\n validateKind,\n validateBulkActionInput,\n validateGenerateUIDInput,\n validateCheckUIDAvailabilityInput,\n};\n"],"names":["PaginationError","ValidationError","errors","TYPES","kindSchema","z","enum","nullable","optional","bulkActionInputSchema","object","documentIds","array","strapiID","min","generateUIDInputSchema","contentTypeUID","string","field","data","looseObject","createCheckUIDAvailabilityInputSchema","regex","pattern","RegExp","value","refine","test","error","validateUIDField","model","strapi","contentTypes","_","has","get","validateKind","validateZodAsync","validateBulkActionInput","validateGenerateUIDInput","validateCheckUIDAvailabilityInput","body","contentType","attributes","schema"],"mappings":";;;;;;;AAMA,MAAM,EAAEA,eAAe,EAAEC,eAAe,EAAE,GAAGC,MAAAA;AAC7C,MAAMC,KAAAA,GAAQ;AAAC,IAAA,YAAA;AAAc,IAAA;AAAiB,CAAA;AAE9C;;IAGA,MAAMC,aAAaC,CAAAA,CAAEC,IAAI,CAACH,KAAAA,CAAAA,CAAOI,QAAQ,GAAGC,QAAQ,EAAA;AAEpD,MAAMC,qBAAAA,GAAwBJ,CAAAA,CAAEK,MAAM,CAAC;AACrCC,IAAAA,WAAAA,EAAaN,CAAAA,CAAEO,KAAK,CAACC,QAAAA,CAAAA,CAAUC,GAAG,CAAC,CAAA;AACrC,CAAA,CAAA;AAEA,MAAMC,sBAAAA,GAAyBV,CAAAA,CAAEK,MAAM,CAAC;AACtCM,IAAAA,cAAAA,EAAgBX,EAAEY,MAAM,EAAA;AACxBC,IAAAA,KAAAA,EAAOb,EAAEY,MAAM,EAAA;IACfE,IAAAA,EAAMd,CAAAA,CAAEe,WAAW,CAAC,EAAC;AACvB,CAAA,CAAA;AAEA,MAAMC,wCAAwC,CAACC,KAAAA,GAAAA;AAC7C,IAAA,MAAMC,OAAAA,GAAUD,KAAAA,GAAQ,IAAIE,MAAAA,CAAOF,KAAAA,CAAAA,GAAS,oBAAA;IAC5C,OAAOjB,CAAAA,CAAEK,MAAM,CAAC;AACdM,QAAAA,cAAAA,EAAgBX,EAAEY,MAAM,EAAA;AACxBC,QAAAA,KAAAA,EAAOb,EAAEY,MAAM,EAAA;AACfQ,QAAAA,KAAAA,EAAOpB,CAAAA,CAAEY,MAAM,EAAA,CAAGS,MAAM,CAAC,CAACD,KAAAA,GAAUA,KAAAA,KAAU,EAAA,IAAMF,OAAAA,CAAQI,IAAI,CAACF,KAAAA,CAAAA,EAAQ;YACvEG,KAAAA,EAAO,CAAC,qEAAqE;AAC/E,SAAA;AACF,KAAA,CAAA;AACF,CAAA;AAEA,MAAMC,gBAAAA,GAAmB,CAACb,cAAAA,EAAqBE,KAAAA,GAAAA;AAC7C,IAAA,MAAMY,KAAAA,GAAQC,MAAAA,CAAOC,YAAY,CAAChB,cAAAA,CAAe;AAEjD,IAAA,IAAI,CAACc,KAAAA,EAAO;AACV,QAAA,MAAM,IAAI7B,eAAAA,CAAgB,uBAAA,CAAA;AAC5B,IAAA;AAEA,IAAA,IACE,CAACgC,CAAAA,CAAEC,GAAG,CAACJ,KAAAA,EAAO;AAAC,QAAA,YAAA;AAAcZ,QAAAA;KAAM,CAAA,IACnCe,CAAAA,CAAEE,GAAG,CAACL,KAAAA,EAAO;AAAC,QAAA,YAAA;AAAcZ,QAAAA,KAAAA;AAAO,QAAA;AAAO,KAAA,CAAA,KAAM,KAAA,EAChD;AACA,QAAA,MAAM,IAAIjB,eAAAA,CAAgB,CAAA,EAAGiB,KAAAA,CAAM,kCAAkC,CAAC,CAAA;AACxE,IAAA;AACF;AAcA,MAAMkB,eAAeC,gBAAAA,CAAiBjC,UAAAA;AACtC,MAAMkC,0BAA0BD,gBAAAA,CAAiB5B,qBAAAA;AACjD,MAAM8B,2BAA2BF,gBAAAA,CAAiBtB,sBAAAA;AAClD,MAAMyB,oCAAoC,CAACC,IAAAA,GAAAA;IAKzC,IAAInB,KAAAA;AAEJ,IAAA,MAAMoB,WAAAA,GACJD,IAAAA,CAAKzB,cAAc,IAAIe,MAAAA,CAAOC,YAAY,GAAGD,MAAAA,CAAOC,YAAY,CAACS,IAAAA,CAAKzB,cAAc,CAAC,GAAG,IAAA;IAE1F,IACE0B,WAAAA,EAAaC,UAAU,CAACF,IAAAA,CAAKvB,KAAK,CAAC,IACnC,CAAC,KAAK,CAAC,IAAIwB,WAAAA,CAAYC,UAAU,CAACF,IAAAA,CAAKvB,KAAK,CAAC,IAC5CwB,WAAAA,CAAYC,UAAU,CAACF,IAAAA,CAAKvB,KAAK,CAAC,CAA0BI,KAAK,EAClE;QACAA,KAAAA,GAASoB,CAAAA,WAAAA,EAAaC,UAAU,CAACF,KAAKvB,KAAK,CAAC,EAA0BI,KAAK;AAC7E,IAAA;AAEA,IAAA,MAAMsB,SAASvB,qCAAAA,CAAsCC,KAAAA,CAAAA;AACrD,IAAA,OAAOe,iBAAiBO,MAAAA,CAAAA,CAAQH,IAAAA,CAAAA;AAClC;;;;"}
@@ -1,36 +1,33 @@
1
1
  'use strict';
2
2
 
3
3
  var strapiUtils = require('@strapi/utils');
4
+ var zod = require('../../validation/zod.js');
4
5
 
5
- const validateFindAvailableSchema = strapiUtils.yup.object().shape({
6
- component: strapiUtils.yup.string(),
7
- id: strapiUtils.yup.strapiID(),
8
- _q: strapiUtils.yup.string(),
9
- idsToOmit: strapiUtils.yup.array().of(strapiUtils.yup.strapiID()),
10
- idsToInclude: strapiUtils.yup.array().of(strapiUtils.yup.strapiID()),
11
- page: strapiUtils.yup.number().integer().min(1),
12
- pageSize: strapiUtils.yup.number().integer().min(1).max(100),
13
- locale: strapiUtils.yup.string().nullable(),
14
- status: strapiUtils.yup.string().oneOf([
6
+ const validateFindAvailableSchema = strapiUtils.z.object({
7
+ component: strapiUtils.z.string().optional(),
8
+ id: zod.strapiID.optional(),
9
+ _q: strapiUtils.z.string().optional(),
10
+ idsToOmit: strapiUtils.z.array(zod.strapiID).optional(),
11
+ idsToInclude: strapiUtils.z.array(zod.strapiID).optional(),
12
+ page: strapiUtils.z.coerce.number().int().min(1).optional(),
13
+ pageSize: strapiUtils.z.coerce.number().int().min(1).max(100).optional(),
14
+ locale: strapiUtils.z.string().nullable().optional(),
15
+ status: strapiUtils.z.enum([
15
16
  'published',
16
17
  'draft'
17
- ]).nullable()
18
- }).required();
19
- const validateFindExistingSchema = strapiUtils.yup.object().shape({
20
- page: strapiUtils.yup.number().integer().min(1),
21
- pageSize: strapiUtils.yup.number().integer().min(1).max(100),
22
- locale: strapiUtils.yup.string().nullable(),
23
- status: strapiUtils.yup.string().oneOf([
18
+ ]).nullable().optional()
19
+ });
20
+ const validateFindExistingSchema = strapiUtils.z.object({
21
+ page: strapiUtils.z.coerce.number().int().min(1).optional(),
22
+ pageSize: strapiUtils.z.coerce.number().int().min(1).max(100).optional(),
23
+ locale: strapiUtils.z.string().nullable().optional(),
24
+ status: strapiUtils.z.enum([
24
25
  'published',
25
26
  'draft'
26
- ]).nullable()
27
- }).required();
28
- const validateFindAvailable = strapiUtils.validateYupSchema(validateFindAvailableSchema, {
29
- strict: false
30
- });
31
- const validateFindExisting = strapiUtils.validateYupSchema(validateFindExistingSchema, {
32
- strict: false
27
+ ]).nullable().optional()
33
28
  });
29
+ const validateFindAvailable = zod.validateZodAsync(validateFindAvailableSchema);
30
+ const validateFindExisting = zod.validateZodAsync(validateFindExistingSchema);
34
31
 
35
32
  exports.validateFindAvailable = validateFindAvailable;
36
33
  exports.validateFindExisting = validateFindExisting;
@@ -1 +1 @@
1
- {"version":3,"file":"relations.js","sources":["../../../../server/src/controllers/validation/relations.ts"],"sourcesContent":["import { yup, validateYupSchema } from '@strapi/utils';\n\nconst validateFindAvailableSchema = yup\n .object()\n .shape({\n component: yup.string(),\n id: yup.strapiID(),\n _q: yup.string(),\n idsToOmit: yup.array().of(yup.strapiID()),\n idsToInclude: yup.array().of(yup.strapiID()),\n page: yup.number().integer().min(1),\n pageSize: yup.number().integer().min(1).max(100),\n locale: yup.string().nullable(),\n status: yup.string().oneOf(['published', 'draft']).nullable(),\n })\n .required();\n\nconst validateFindExistingSchema = yup\n .object()\n .shape({\n page: yup.number().integer().min(1),\n pageSize: yup.number().integer().min(1).max(100),\n locale: yup.string().nullable(),\n status: yup.string().oneOf(['published', 'draft']).nullable(),\n })\n .required();\n\nconst validateFindAvailable = validateYupSchema(validateFindAvailableSchema, { strict: false });\nconst validateFindExisting = validateYupSchema(validateFindExistingSchema, { strict: false });\n\nexport { validateFindAvailable, validateFindExisting };\n"],"names":["validateFindAvailableSchema","yup","object","shape","component","string","id","strapiID","_q","idsToOmit","array","of","idsToInclude","page","number","integer","min","pageSize","max","locale","nullable","status","oneOf","required","validateFindExistingSchema","validateFindAvailable","validateYupSchema","strict","validateFindExisting"],"mappings":";;;;AAEA,MAAMA,2BAAAA,GAA8BC,eAAAA,CACjCC,MAAM,EAAA,CACNC,KAAK,CAAC;AACLC,IAAAA,SAAAA,EAAWH,gBAAII,MAAM,EAAA;AACrBC,IAAAA,EAAAA,EAAIL,gBAAIM,QAAQ,EAAA;AAChBC,IAAAA,EAAAA,EAAIP,gBAAII,MAAM,EAAA;AACdI,IAAAA,SAAAA,EAAWR,gBAAIS,KAAK,EAAA,CAAGC,EAAE,CAACV,gBAAIM,QAAQ,EAAA,CAAA;AACtCK,IAAAA,YAAAA,EAAcX,gBAAIS,KAAK,EAAA,CAAGC,EAAE,CAACV,gBAAIM,QAAQ,EAAA,CAAA;AACzCM,IAAAA,IAAAA,EAAMZ,gBAAIa,MAAM,EAAA,CAAGC,OAAO,EAAA,CAAGC,GAAG,CAAC,CAAA,CAAA;IACjCC,QAAAA,EAAUhB,eAAAA,CAAIa,MAAM,EAAA,CAAGC,OAAO,GAAGC,GAAG,CAAC,CAAA,CAAA,CAAGE,GAAG,CAAC,GAAA,CAAA;IAC5CC,MAAAA,EAAQlB,eAAAA,CAAII,MAAM,EAAA,CAAGe,QAAQ,EAAA;AAC7BC,IAAAA,MAAAA,EAAQpB,eAAAA,CAAII,MAAM,EAAA,CAAGiB,KAAK,CAAC;AAAC,QAAA,WAAA;AAAa,QAAA;AAAQ,KAAA,CAAA,CAAEF,QAAQ;AAC7D,CAAA,CAAA,CACCG,QAAQ,EAAA;AAEX,MAAMC,0BAAAA,GAA6BvB,eAAAA,CAChCC,MAAM,EAAA,CACNC,KAAK,CAAC;AACLU,IAAAA,IAAAA,EAAMZ,gBAAIa,MAAM,EAAA,CAAGC,OAAO,EAAA,CAAGC,GAAG,CAAC,CAAA,CAAA;IACjCC,QAAAA,EAAUhB,eAAAA,CAAIa,MAAM,EAAA,CAAGC,OAAO,GAAGC,GAAG,CAAC,CAAA,CAAA,CAAGE,GAAG,CAAC,GAAA,CAAA;IAC5CC,MAAAA,EAAQlB,eAAAA,CAAII,MAAM,EAAA,CAAGe,QAAQ,EAAA;AAC7BC,IAAAA,MAAAA,EAAQpB,eAAAA,CAAII,MAAM,EAAA,CAAGiB,KAAK,CAAC;AAAC,QAAA,WAAA;AAAa,QAAA;AAAQ,KAAA,CAAA,CAAEF,QAAQ;AAC7D,CAAA,CAAA,CACCG,QAAQ,EAAA;AAEX,MAAME,qBAAAA,GAAwBC,8BAAkB1B,2BAAAA,EAA6B;IAAE2B,MAAAA,EAAQ;AAAM,CAAA;AAC7F,MAAMC,oBAAAA,GAAuBF,8BAAkBF,0BAAAA,EAA4B;IAAEG,MAAAA,EAAQ;AAAM,CAAA;;;;;"}
1
+ {"version":3,"file":"relations.js","sources":["../../../../server/src/controllers/validation/relations.ts"],"sourcesContent":["import { z } from '@strapi/utils';\nimport { validateZodAsync, strapiID } from '../../validation/zod';\n\nconst validateFindAvailableSchema = z.object({\n component: z.string().optional(),\n id: strapiID.optional(),\n _q: z.string().optional(),\n idsToOmit: z.array(strapiID).optional(),\n idsToInclude: z.array(strapiID).optional(),\n page: z.coerce.number().int().min(1).optional(),\n pageSize: z.coerce.number().int().min(1).max(100).optional(),\n locale: z.string().nullable().optional(),\n status: z.enum(['published', 'draft']).nullable().optional(),\n});\n\nconst validateFindExistingSchema = z.object({\n page: z.coerce.number().int().min(1).optional(),\n pageSize: z.coerce.number().int().min(1).max(100).optional(),\n locale: z.string().nullable().optional(),\n status: z.enum(['published', 'draft']).nullable().optional(),\n});\n\nconst validateFindAvailable = validateZodAsync(validateFindAvailableSchema);\nconst validateFindExisting = validateZodAsync(validateFindExistingSchema);\n\nexport { validateFindAvailable, validateFindExisting };\n"],"names":["validateFindAvailableSchema","z","object","component","string","optional","id","strapiID","_q","idsToOmit","array","idsToInclude","page","coerce","number","int","min","pageSize","max","locale","nullable","status","enum","validateFindExistingSchema","validateFindAvailable","validateZodAsync","validateFindExisting"],"mappings":";;;;;AAGA,MAAMA,2BAAAA,GAA8BC,aAAAA,CAAEC,MAAM,CAAC;IAC3CC,SAAAA,EAAWF,aAAAA,CAAEG,MAAM,EAAA,CAAGC,QAAQ,EAAA;AAC9BC,IAAAA,EAAAA,EAAIC,aAASF,QAAQ,EAAA;IACrBG,EAAAA,EAAIP,aAAAA,CAAEG,MAAM,EAAA,CAAGC,QAAQ,EAAA;AACvBI,IAAAA,SAAAA,EAAWR,aAAAA,CAAES,KAAK,CAACH,YAAAA,CAAAA,CAAUF,QAAQ,EAAA;AACrCM,IAAAA,YAAAA,EAAcV,aAAAA,CAAES,KAAK,CAACH,YAAAA,CAAAA,CAAUF,QAAQ,EAAA;IACxCO,IAAAA,EAAMX,aAAAA,CAAEY,MAAM,CAACC,MAAM,EAAA,CAAGC,GAAG,EAAA,CAAGC,GAAG,CAAC,CAAA,CAAA,CAAGX,QAAQ,EAAA;AAC7CY,IAAAA,QAAAA,EAAUhB,aAAAA,CAAEY,MAAM,CAACC,MAAM,EAAA,CAAGC,GAAG,EAAA,CAAGC,GAAG,CAAC,CAAA,CAAA,CAAGE,GAAG,CAAC,KAAKb,QAAQ,EAAA;AAC1Dc,IAAAA,MAAAA,EAAQlB,aAAAA,CAAEG,MAAM,EAAA,CAAGgB,QAAQ,GAAGf,QAAQ,EAAA;IACtCgB,MAAAA,EAAQpB,aAAAA,CAAEqB,IAAI,CAAC;AAAC,QAAA,WAAA;AAAa,QAAA;KAAQ,CAAA,CAAEF,QAAQ,GAAGf,QAAQ;AAC5D,CAAA,CAAA;AAEA,MAAMkB,0BAAAA,GAA6BtB,aAAAA,CAAEC,MAAM,CAAC;IAC1CU,IAAAA,EAAMX,aAAAA,CAAEY,MAAM,CAACC,MAAM,EAAA,CAAGC,GAAG,EAAA,CAAGC,GAAG,CAAC,CAAA,CAAA,CAAGX,QAAQ,EAAA;AAC7CY,IAAAA,QAAAA,EAAUhB,aAAAA,CAAEY,MAAM,CAACC,MAAM,EAAA,CAAGC,GAAG,EAAA,CAAGC,GAAG,CAAC,CAAA,CAAA,CAAGE,GAAG,CAAC,KAAKb,QAAQ,EAAA;AAC1Dc,IAAAA,MAAAA,EAAQlB,aAAAA,CAAEG,MAAM,EAAA,CAAGgB,QAAQ,GAAGf,QAAQ,EAAA;IACtCgB,MAAAA,EAAQpB,aAAAA,CAAEqB,IAAI,CAAC;AAAC,QAAA,WAAA;AAAa,QAAA;KAAQ,CAAA,CAAEF,QAAQ,GAAGf,QAAQ;AAC5D,CAAA,CAAA;AAEA,MAAMmB,wBAAwBC,oBAAAA,CAAiBzB,2BAAAA;AAC/C,MAAM0B,uBAAuBD,oBAAAA,CAAiBF,0BAAAA;;;;;"}
@@ -1,34 +1,31 @@
1
- import { yup, validateYupSchema } from '@strapi/utils';
1
+ import { z } from '@strapi/utils';
2
+ import { strapiID, validateZodAsync } from '../../validation/zod.mjs';
2
3
 
3
- const validateFindAvailableSchema = yup.object().shape({
4
- component: yup.string(),
5
- id: yup.strapiID(),
6
- _q: yup.string(),
7
- idsToOmit: yup.array().of(yup.strapiID()),
8
- idsToInclude: yup.array().of(yup.strapiID()),
9
- page: yup.number().integer().min(1),
10
- pageSize: yup.number().integer().min(1).max(100),
11
- locale: yup.string().nullable(),
12
- status: yup.string().oneOf([
4
+ const validateFindAvailableSchema = z.object({
5
+ component: z.string().optional(),
6
+ id: strapiID.optional(),
7
+ _q: z.string().optional(),
8
+ idsToOmit: z.array(strapiID).optional(),
9
+ idsToInclude: z.array(strapiID).optional(),
10
+ page: z.coerce.number().int().min(1).optional(),
11
+ pageSize: z.coerce.number().int().min(1).max(100).optional(),
12
+ locale: z.string().nullable().optional(),
13
+ status: z.enum([
13
14
  'published',
14
15
  'draft'
15
- ]).nullable()
16
- }).required();
17
- const validateFindExistingSchema = yup.object().shape({
18
- page: yup.number().integer().min(1),
19
- pageSize: yup.number().integer().min(1).max(100),
20
- locale: yup.string().nullable(),
21
- status: yup.string().oneOf([
16
+ ]).nullable().optional()
17
+ });
18
+ const validateFindExistingSchema = z.object({
19
+ page: z.coerce.number().int().min(1).optional(),
20
+ pageSize: z.coerce.number().int().min(1).max(100).optional(),
21
+ locale: z.string().nullable().optional(),
22
+ status: z.enum([
22
23
  'published',
23
24
  'draft'
24
- ]).nullable()
25
- }).required();
26
- const validateFindAvailable = validateYupSchema(validateFindAvailableSchema, {
27
- strict: false
28
- });
29
- const validateFindExisting = validateYupSchema(validateFindExistingSchema, {
30
- strict: false
25
+ ]).nullable().optional()
31
26
  });
27
+ const validateFindAvailable = validateZodAsync(validateFindAvailableSchema);
28
+ const validateFindExisting = validateZodAsync(validateFindExistingSchema);
32
29
 
33
30
  export { validateFindAvailable, validateFindExisting };
34
31
  //# sourceMappingURL=relations.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"relations.mjs","sources":["../../../../server/src/controllers/validation/relations.ts"],"sourcesContent":["import { yup, validateYupSchema } from '@strapi/utils';\n\nconst validateFindAvailableSchema = yup\n .object()\n .shape({\n component: yup.string(),\n id: yup.strapiID(),\n _q: yup.string(),\n idsToOmit: yup.array().of(yup.strapiID()),\n idsToInclude: yup.array().of(yup.strapiID()),\n page: yup.number().integer().min(1),\n pageSize: yup.number().integer().min(1).max(100),\n locale: yup.string().nullable(),\n status: yup.string().oneOf(['published', 'draft']).nullable(),\n })\n .required();\n\nconst validateFindExistingSchema = yup\n .object()\n .shape({\n page: yup.number().integer().min(1),\n pageSize: yup.number().integer().min(1).max(100),\n locale: yup.string().nullable(),\n status: yup.string().oneOf(['published', 'draft']).nullable(),\n })\n .required();\n\nconst validateFindAvailable = validateYupSchema(validateFindAvailableSchema, { strict: false });\nconst validateFindExisting = validateYupSchema(validateFindExistingSchema, { strict: false });\n\nexport { validateFindAvailable, validateFindExisting };\n"],"names":["validateFindAvailableSchema","yup","object","shape","component","string","id","strapiID","_q","idsToOmit","array","of","idsToInclude","page","number","integer","min","pageSize","max","locale","nullable","status","oneOf","required","validateFindExistingSchema","validateFindAvailable","validateYupSchema","strict","validateFindExisting"],"mappings":";;AAEA,MAAMA,2BAAAA,GAA8BC,GAAAA,CACjCC,MAAM,EAAA,CACNC,KAAK,CAAC;AACLC,IAAAA,SAAAA,EAAWH,IAAII,MAAM,EAAA;AACrBC,IAAAA,EAAAA,EAAIL,IAAIM,QAAQ,EAAA;AAChBC,IAAAA,EAAAA,EAAIP,IAAII,MAAM,EAAA;AACdI,IAAAA,SAAAA,EAAWR,IAAIS,KAAK,EAAA,CAAGC,EAAE,CAACV,IAAIM,QAAQ,EAAA,CAAA;AACtCK,IAAAA,YAAAA,EAAcX,IAAIS,KAAK,EAAA,CAAGC,EAAE,CAACV,IAAIM,QAAQ,EAAA,CAAA;AACzCM,IAAAA,IAAAA,EAAMZ,IAAIa,MAAM,EAAA,CAAGC,OAAO,EAAA,CAAGC,GAAG,CAAC,CAAA,CAAA;IACjCC,QAAAA,EAAUhB,GAAAA,CAAIa,MAAM,EAAA,CAAGC,OAAO,GAAGC,GAAG,CAAC,CAAA,CAAA,CAAGE,GAAG,CAAC,GAAA,CAAA;IAC5CC,MAAAA,EAAQlB,GAAAA,CAAII,MAAM,EAAA,CAAGe,QAAQ,EAAA;AAC7BC,IAAAA,MAAAA,EAAQpB,GAAAA,CAAII,MAAM,EAAA,CAAGiB,KAAK,CAAC;AAAC,QAAA,WAAA;AAAa,QAAA;AAAQ,KAAA,CAAA,CAAEF,QAAQ;AAC7D,CAAA,CAAA,CACCG,QAAQ,EAAA;AAEX,MAAMC,0BAAAA,GAA6BvB,GAAAA,CAChCC,MAAM,EAAA,CACNC,KAAK,CAAC;AACLU,IAAAA,IAAAA,EAAMZ,IAAIa,MAAM,EAAA,CAAGC,OAAO,EAAA,CAAGC,GAAG,CAAC,CAAA,CAAA;IACjCC,QAAAA,EAAUhB,GAAAA,CAAIa,MAAM,EAAA,CAAGC,OAAO,GAAGC,GAAG,CAAC,CAAA,CAAA,CAAGE,GAAG,CAAC,GAAA,CAAA;IAC5CC,MAAAA,EAAQlB,GAAAA,CAAII,MAAM,EAAA,CAAGe,QAAQ,EAAA;AAC7BC,IAAAA,MAAAA,EAAQpB,GAAAA,CAAII,MAAM,EAAA,CAAGiB,KAAK,CAAC;AAAC,QAAA,WAAA;AAAa,QAAA;AAAQ,KAAA,CAAA,CAAEF,QAAQ;AAC7D,CAAA,CAAA,CACCG,QAAQ,EAAA;AAEX,MAAME,qBAAAA,GAAwBC,kBAAkB1B,2BAAAA,EAA6B;IAAE2B,MAAAA,EAAQ;AAAM,CAAA;AAC7F,MAAMC,oBAAAA,GAAuBF,kBAAkBF,0BAAAA,EAA4B;IAAEG,MAAAA,EAAQ;AAAM,CAAA;;;;"}
1
+ {"version":3,"file":"relations.mjs","sources":["../../../../server/src/controllers/validation/relations.ts"],"sourcesContent":["import { z } from '@strapi/utils';\nimport { validateZodAsync, strapiID } from '../../validation/zod';\n\nconst validateFindAvailableSchema = z.object({\n component: z.string().optional(),\n id: strapiID.optional(),\n _q: z.string().optional(),\n idsToOmit: z.array(strapiID).optional(),\n idsToInclude: z.array(strapiID).optional(),\n page: z.coerce.number().int().min(1).optional(),\n pageSize: z.coerce.number().int().min(1).max(100).optional(),\n locale: z.string().nullable().optional(),\n status: z.enum(['published', 'draft']).nullable().optional(),\n});\n\nconst validateFindExistingSchema = z.object({\n page: z.coerce.number().int().min(1).optional(),\n pageSize: z.coerce.number().int().min(1).max(100).optional(),\n locale: z.string().nullable().optional(),\n status: z.enum(['published', 'draft']).nullable().optional(),\n});\n\nconst validateFindAvailable = validateZodAsync(validateFindAvailableSchema);\nconst validateFindExisting = validateZodAsync(validateFindExistingSchema);\n\nexport { validateFindAvailable, validateFindExisting };\n"],"names":["validateFindAvailableSchema","z","object","component","string","optional","id","strapiID","_q","idsToOmit","array","idsToInclude","page","coerce","number","int","min","pageSize","max","locale","nullable","status","enum","validateFindExistingSchema","validateFindAvailable","validateZodAsync","validateFindExisting"],"mappings":";;;AAGA,MAAMA,2BAAAA,GAA8BC,CAAAA,CAAEC,MAAM,CAAC;IAC3CC,SAAAA,EAAWF,CAAAA,CAAEG,MAAM,EAAA,CAAGC,QAAQ,EAAA;AAC9BC,IAAAA,EAAAA,EAAIC,SAASF,QAAQ,EAAA;IACrBG,EAAAA,EAAIP,CAAAA,CAAEG,MAAM,EAAA,CAAGC,QAAQ,EAAA;AACvBI,IAAAA,SAAAA,EAAWR,CAAAA,CAAES,KAAK,CAACH,QAAAA,CAAAA,CAAUF,QAAQ,EAAA;AACrCM,IAAAA,YAAAA,EAAcV,CAAAA,CAAES,KAAK,CAACH,QAAAA,CAAAA,CAAUF,QAAQ,EAAA;IACxCO,IAAAA,EAAMX,CAAAA,CAAEY,MAAM,CAACC,MAAM,EAAA,CAAGC,GAAG,EAAA,CAAGC,GAAG,CAAC,CAAA,CAAA,CAAGX,QAAQ,EAAA;AAC7CY,IAAAA,QAAAA,EAAUhB,CAAAA,CAAEY,MAAM,CAACC,MAAM,EAAA,CAAGC,GAAG,EAAA,CAAGC,GAAG,CAAC,CAAA,CAAA,CAAGE,GAAG,CAAC,KAAKb,QAAQ,EAAA;AAC1Dc,IAAAA,MAAAA,EAAQlB,CAAAA,CAAEG,MAAM,EAAA,CAAGgB,QAAQ,GAAGf,QAAQ,EAAA;IACtCgB,MAAAA,EAAQpB,CAAAA,CAAEqB,IAAI,CAAC;AAAC,QAAA,WAAA;AAAa,QAAA;KAAQ,CAAA,CAAEF,QAAQ,GAAGf,QAAQ;AAC5D,CAAA,CAAA;AAEA,MAAMkB,0BAAAA,GAA6BtB,CAAAA,CAAEC,MAAM,CAAC;IAC1CU,IAAAA,EAAMX,CAAAA,CAAEY,MAAM,CAACC,MAAM,EAAA,CAAGC,GAAG,EAAA,CAAGC,GAAG,CAAC,CAAA,CAAA,CAAGX,QAAQ,EAAA;AAC7CY,IAAAA,QAAAA,EAAUhB,CAAAA,CAAEY,MAAM,CAACC,MAAM,EAAA,CAAGC,GAAG,EAAA,CAAGC,GAAG,CAAC,CAAA,CAAA,CAAGE,GAAG,CAAC,KAAKb,QAAQ,EAAA;AAC1Dc,IAAAA,MAAAA,EAAQlB,CAAAA,CAAEG,MAAM,EAAA,CAAGgB,QAAQ,GAAGf,QAAQ,EAAA;IACtCgB,MAAAA,EAAQpB,CAAAA,CAAEqB,IAAI,CAAC;AAAC,QAAA,WAAA;AAAa,QAAA;KAAQ,CAAA,CAAEF,QAAQ,GAAGf,QAAQ;AAC5D,CAAA,CAAA;AAEA,MAAMmB,wBAAwBC,gBAAAA,CAAiBzB,2BAAAA;AAC/C,MAAM0B,uBAAuBD,gBAAAA,CAAiBF,0BAAAA;;;;"}
@@ -1,31 +1,11 @@
1
1
  'use strict';
2
2
 
3
- var yup = require('yup');
4
3
  var strapiUtils = require('@strapi/utils');
5
4
 
6
- function _interopNamespaceDefault(e) {
7
- var n = Object.create(null);
8
- if (e) {
9
- Object.keys(e).forEach(function (k) {
10
- if (k !== 'default') {
11
- var d = Object.getOwnPropertyDescriptor(e, k);
12
- Object.defineProperty(n, k, d.get ? d : {
13
- enumerable: true,
14
- get: function () { return e[k]; }
15
- });
16
- }
17
- });
18
- }
19
- n.default = e;
20
- return Object.freeze(n);
21
- }
22
-
23
- var yup__namespace = /*#__PURE__*/_interopNamespaceDefault(yup);
24
-
25
- const historyRestoreVersionSchema = yup__namespace.object().shape({
26
- contentType: yup__namespace.string().trim().required()
27
- }).required();
28
- const validateRestoreVersion = strapiUtils.validateYupSchema(historyRestoreVersionSchema);
5
+ const historyRestoreVersionSchema = strapiUtils.z.object({
6
+ contentType: strapiUtils.z.string().trim()
7
+ });
8
+ const validateRestoreVersion = strapiUtils.validateZodSchema(historyRestoreVersionSchema);
29
9
 
30
10
  exports.validateRestoreVersion = validateRestoreVersion;
31
11
  //# sourceMappingURL=history-version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"history-version.js","sources":["../../../../../server/src/history/controllers/validation/history-version.ts"],"sourcesContent":["import * as yup from 'yup';\nimport { validateYupSchema } from '@strapi/utils';\n\nconst historyRestoreVersionSchema = yup\n .object()\n .shape({\n contentType: yup.string().trim().required(),\n })\n .required();\n\nexport const validateRestoreVersion = validateYupSchema(historyRestoreVersionSchema);\n"],"names":["historyRestoreVersionSchema","yup","object","shape","contentType","string","trim","required","validateRestoreVersion","validateYupSchema"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAGA,MAAMA,2BAAAA,GAA8BC,cAAAA,CACjCC,MAAM,EAAA,CACNC,KAAK,CAAC;AACLC,IAAAA,WAAAA,EAAaH,cAAAA,CAAII,MAAM,EAAA,CAAGC,IAAI,GAAGC,QAAQ;AAC3C,CAAA,CAAA,CACCA,QAAQ,EAAA;AAEJ,MAAMC,sBAAAA,GAAyBC,6BAAAA,CAAkBT,2BAAAA;;;;"}
1
+ {"version":3,"file":"history-version.js","sources":["../../../../../server/src/history/controllers/validation/history-version.ts"],"sourcesContent":["import { z, validateZodSchema } from '@strapi/utils';\n\nconst historyRestoreVersionSchema = z.object({\n contentType: z.string().trim(),\n});\n\nexport const validateRestoreVersion = validateZodSchema(historyRestoreVersionSchema);\n"],"names":["historyRestoreVersionSchema","z","object","contentType","string","trim","validateRestoreVersion","validateZodSchema"],"mappings":";;;;AAEA,MAAMA,2BAAAA,GAA8BC,aAAAA,CAAEC,MAAM,CAAC;IAC3CC,WAAAA,EAAaF,aAAAA,CAAEG,MAAM,EAAA,CAAGC,IAAI;AAC9B,CAAA,CAAA;AAEO,MAAMC,sBAAAA,GAAyBC,6BAAAA,CAAkBP,2BAAAA;;;;"}
@@ -1,10 +1,9 @@
1
- import * as yup from 'yup';
2
- import { validateYupSchema } from '@strapi/utils';
1
+ import { z, validateZodSchema } from '@strapi/utils';
3
2
 
4
- const historyRestoreVersionSchema = yup.object().shape({
5
- contentType: yup.string().trim().required()
6
- }).required();
7
- const validateRestoreVersion = validateYupSchema(historyRestoreVersionSchema);
3
+ const historyRestoreVersionSchema = z.object({
4
+ contentType: z.string().trim()
5
+ });
6
+ const validateRestoreVersion = validateZodSchema(historyRestoreVersionSchema);
8
7
 
9
8
  export { validateRestoreVersion };
10
9
  //# sourceMappingURL=history-version.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"history-version.mjs","sources":["../../../../../server/src/history/controllers/validation/history-version.ts"],"sourcesContent":["import * as yup from 'yup';\nimport { validateYupSchema } from '@strapi/utils';\n\nconst historyRestoreVersionSchema = yup\n .object()\n .shape({\n contentType: yup.string().trim().required(),\n })\n .required();\n\nexport const validateRestoreVersion = validateYupSchema(historyRestoreVersionSchema);\n"],"names":["historyRestoreVersionSchema","yup","object","shape","contentType","string","trim","required","validateRestoreVersion","validateYupSchema"],"mappings":";;;AAGA,MAAMA,2BAAAA,GAA8BC,GAAAA,CACjCC,MAAM,EAAA,CACNC,KAAK,CAAC;AACLC,IAAAA,WAAAA,EAAaH,GAAAA,CAAII,MAAM,EAAA,CAAGC,IAAI,GAAGC,QAAQ;AAC3C,CAAA,CAAA,CACCA,QAAQ,EAAA;AAEJ,MAAMC,sBAAAA,GAAyBC,iBAAAA,CAAkBT,2BAAAA;;;;"}
1
+ {"version":3,"file":"history-version.mjs","sources":["../../../../../server/src/history/controllers/validation/history-version.ts"],"sourcesContent":["import { z, validateZodSchema } from '@strapi/utils';\n\nconst historyRestoreVersionSchema = z.object({\n contentType: z.string().trim(),\n});\n\nexport const validateRestoreVersion = validateZodSchema(historyRestoreVersionSchema);\n"],"names":["historyRestoreVersionSchema","z","object","contentType","string","trim","validateRestoreVersion","validateZodSchema"],"mappings":";;AAEA,MAAMA,2BAAAA,GAA8BC,CAAAA,CAAEC,MAAM,CAAC;IAC3CC,WAAAA,EAAaF,CAAAA,CAAEG,MAAM,EAAA,CAAGC,IAAI;AAC9B,CAAA,CAAA;AAEO,MAAMC,sBAAAA,GAAyBC,iBAAAA,CAAkBP,2BAAAA;;;;"}
@@ -22,7 +22,7 @@ var utils = require('./utils.js');
22
22
  * It creates confusion for users because they see two history versions each publish action.
23
23
  * To avoid this, we silence the update action during a publish request,
24
24
  * so that they only see the published version of the document in the history.
25
- */ if (context.action === 'update' && strapi.requestContext.get()?.request.url.endsWith('/actions/publish')) {
25
+ */ if (context.action === 'update' && strapi.requestContext.get()?.request.url.split('?')[0].endsWith('/actions/publish')) {
26
26
  return false;
27
27
  }
28
28
  // Ignore content types not created by the user
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycles.js","sources":["../../../../server/src/history/services/lifecycles.ts"],"sourcesContent":["import type { Core, Modules, UID } from '@strapi/types';\nimport { contentTypes } from '@strapi/utils';\n\nimport { omit, castArray } from 'lodash/fp';\n\nimport { getService } from '../utils';\nimport { FIELDS_TO_IGNORE, HISTORY_VERSION_UID } from '../constants';\n\nimport type { CreateHistoryVersion } from '../../../../shared/contracts/history-versions';\nimport { createServiceUtils } from './utils';\n\n/**\n * Filters out actions that should not create a history version.\n */\nconst shouldCreateHistoryVersion = (\n context: Modules.Documents.Middleware.Context\n): context is Modules.Documents.Middleware.Context & {\n action: 'create' | 'update' | 'clone' | 'publish' | 'unpublish' | 'discardDraft';\n contentType: UID.CollectionType;\n} => {\n // Ignore requests that are not related to the content manager\n if (!strapi.requestContext.get()?.request.url.startsWith('/content-manager')) {\n return false;\n }\n\n // NOTE: cannot do type narrowing with array includes\n if (\n context.action !== 'create' &&\n context.action !== 'update' &&\n context.action !== 'clone' &&\n context.action !== 'publish' &&\n context.action !== 'unpublish' &&\n context.action !== 'discardDraft'\n ) {\n return false;\n }\n\n /**\n * When a document is published, the draft version of the document is also updated.\n * It creates confusion for users because they see two history versions each publish action.\n * To avoid this, we silence the update action during a publish request,\n * so that they only see the published version of the document in the history.\n */\n if (\n context.action === 'update' &&\n strapi.requestContext.get()?.request.url.endsWith('/actions/publish')\n ) {\n return false;\n }\n\n // Ignore content types not created by the user\n if (!context.contentType.uid.startsWith('api::')) {\n return false;\n }\n\n return true;\n};\n\n/**\n * Returns the content type schema (and its components schemas).\n * Used to determine if changes were made in the content type builder since a history version was created.\n * And therefore which fields can be restored and which cannot.\n */\nconst getSchemas = (uid: UID.CollectionType) => {\n const attributesSchema = strapi.getModel(uid).attributes;\n\n // TODO: Handle nested components\n const componentsSchemas = Object.keys(attributesSchema).reduce(\n (currentComponentSchemas, key) => {\n const fieldSchema = attributesSchema[key];\n\n if (fieldSchema.type === 'component') {\n const componentSchema = strapi.getModel(fieldSchema.component).attributes;\n return {\n ...currentComponentSchemas,\n [fieldSchema.component]: componentSchema,\n };\n }\n\n // Ignore anything that's not a component\n return currentComponentSchemas;\n },\n {} as CreateHistoryVersion['componentsSchemas']\n );\n\n return {\n schema: omit(FIELDS_TO_IGNORE, attributesSchema) as CreateHistoryVersion['schema'],\n componentsSchemas,\n };\n};\n\nconst createLifecyclesService = ({ strapi }: { strapi: Core.Strapi }) => {\n const state: {\n isInitialized: boolean;\n } = {\n isInitialized: false,\n };\n\n const serviceUtils = createServiceUtils({ strapi });\n const { persistTablesWithPrefix } = strapi.service('admin::persist-tables');\n\n return {\n async bootstrap() {\n // Prevent initializing the service twice\n if (state.isInitialized) {\n return;\n }\n\n // Avoid data loss in case users temporarily don't have a license\n await persistTablesWithPrefix('strapi_history_versions');\n\n strapi.documents.use(async (context, next) => {\n const result = (await next()) as any;\n\n if (!shouldCreateHistoryVersion(context)) {\n return result;\n }\n\n // On create/clone actions, the documentId is not available before creating the action is executed\n const documentId =\n context.action === 'create' || context.action === 'clone'\n ? result.documentId\n : context.params.documentId;\n\n // Apply default locale if not available in the request\n const defaultLocale = await serviceUtils.getDefaultLocale();\n const locales = castArray(context.params?.locale || defaultLocale);\n if (!locales.length) {\n return result;\n }\n\n // All schemas related to the content type\n const uid = context.contentType.uid;\n const schemas = getSchemas(uid);\n const model = strapi.getModel(uid);\n\n const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);\n\n // Find all affected entries\n const localeEntries = await strapi.db.query(uid).findMany({\n where: {\n documentId,\n ...(isLocalizedContentType ? { locale: { $in: locales } } : {}),\n ...(contentTypes.hasDraftAndPublish(strapi.contentTypes[uid])\n ? { publishedAt: null }\n : {}),\n },\n populate: serviceUtils.getDeepPopulate(uid, true /* use database syntax */),\n });\n\n await strapi.db.transaction(async ({ onCommit }) => {\n // .createVersion() is executed asynchronously,\n // onCommit prevents creating a history version\n // when the transaction has already been committed\n onCommit(async () => {\n for (const entry of localeEntries) {\n const status = await serviceUtils.getVersionStatus(uid, entry);\n\n await getService(strapi, 'history').createVersion({\n contentType: uid,\n data: omit(FIELDS_TO_IGNORE, entry) as Modules.Documents.AnyDocument,\n relatedDocumentId: documentId,\n locale: entry.locale,\n status,\n ...schemas,\n });\n }\n });\n });\n\n return result;\n });\n\n // Schedule a job to delete expired history versions every day at midnight\n strapi.cron.add({\n deleteHistoryDaily: {\n async task() {\n const BATCH_SIZE = 1000;\n\n const retentionDaysInMilliseconds =\n serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1000;\n const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);\n\n // Delete in batches of 1000 to avoid a single query that\n // exhausts the DB connection pool and blocks other operations.\n let deleted: number;\n do {\n // Fetch up to BATCH_SIZE expired IDs\n const expiredVersions = await strapi.db.query(HISTORY_VERSION_UID).findMany({\n select: ['id'],\n where: {\n created_at: {\n $lt: expirationDate,\n },\n },\n limit: BATCH_SIZE,\n });\n\n const ids = expiredVersions.map((v: { id: number | string }) => v.id);\n deleted = ids.length;\n\n // Delete this batch by ID\n if (deleted > 0) {\n await strapi.db.query(HISTORY_VERSION_UID).deleteMany({\n where: {\n id: { $in: ids },\n },\n });\n }\n\n // If we got a full batch, there are likely more rows to delete — loop again.\n // If we got fewer, we've handled everything and can stop.\n } while (deleted >= BATCH_SIZE);\n },\n options: '0 0 * * *',\n },\n });\n\n state.isInitialized = true;\n },\n\n async destroy() {\n strapi.cron.remove('deleteHistoryDaily');\n },\n };\n};\n\nexport { createLifecyclesService };\n"],"names":["shouldCreateHistoryVersion","context","strapi","requestContext","get","request","url","startsWith","action","endsWith","contentType","uid","getSchemas","attributesSchema","getModel","attributes","componentsSchemas","Object","keys","reduce","currentComponentSchemas","key","fieldSchema","type","componentSchema","component","schema","omit","FIELDS_TO_IGNORE","createLifecyclesService","state","isInitialized","serviceUtils","createServiceUtils","persistTablesWithPrefix","service","bootstrap","documents","use","next","result","documentId","params","defaultLocale","getDefaultLocale","locales","castArray","locale","length","schemas","model","isLocalizedContentType","localeEntries","db","query","findMany","where","$in","contentTypes","hasDraftAndPublish","publishedAt","populate","getDeepPopulate","transaction","onCommit","entry","status","getVersionStatus","getService","createVersion","data","relatedDocumentId","cron","add","deleteHistoryDaily","task","BATCH_SIZE","retentionDaysInMilliseconds","getRetentionDays","expirationDate","Date","now","deleted","expiredVersions","HISTORY_VERSION_UID","select","created_at","$lt","limit","ids","map","v","id","deleteMany","options","destroy","remove"],"mappings":";;;;;;;;AAWA;;IAGA,MAAMA,6BAA6B,CACjCC,OAAAA,GAAAA;;IAMA,IAAI,CAACC,OAAOC,cAAc,CAACC,GAAG,EAAA,EAAIC,OAAAA,CAAQC,GAAAA,CAAIC,UAAAA,CAAW,kBAAA,CAAA,EAAqB;QAC5E,OAAO,KAAA;AACT,IAAA;;IAGA,IACEN,OAAAA,CAAQO,MAAM,KAAK,QAAA,IACnBP,QAAQO,MAAM,KAAK,QAAA,IACnBP,OAAAA,CAAQO,MAAM,KAAK,WACnBP,OAAAA,CAAQO,MAAM,KAAK,SAAA,IACnBP,OAAAA,CAAQO,MAAM,KAAK,WAAA,IACnBP,OAAAA,CAAQO,MAAM,KAAK,cAAA,EACnB;QACA,OAAO,KAAA;AACT,IAAA;AAEA;;;;;AAKC,MACD,IACEP,OAAAA,CAAQO,MAAM,KAAK,QAAA,IACnBN,MAAAA,CAAOC,cAAc,CAACC,GAAG,EAAA,EAAIC,OAAAA,CAAQC,GAAAA,CAAIG,SAAS,kBAAA,CAAA,EAClD;QACA,OAAO,KAAA;AACT,IAAA;;IAGA,IAAI,CAACR,QAAQS,WAAW,CAACC,GAAG,CAACJ,UAAU,CAAC,OAAA,CAAA,EAAU;QAChD,OAAO,KAAA;AACT,IAAA;IAEA,OAAO,IAAA;AACT,CAAA;AAEA;;;;IAKA,MAAMK,aAAa,CAACD,GAAAA,GAAAA;AAClB,IAAA,MAAME,gBAAAA,GAAmBX,MAAAA,CAAOY,QAAQ,CAACH,KAAKI,UAAU;;IAGxD,MAAMC,iBAAAA,GAAoBC,OAAOC,IAAI,CAACL,kBAAkBM,MAAM,CAC5D,CAACC,uBAAAA,EAAyBC,GAAAA,GAAAA;QACxB,MAAMC,WAAAA,GAAcT,gBAAgB,CAACQ,GAAAA,CAAI;QAEzC,IAAIC,WAAAA,CAAYC,IAAI,KAAK,WAAA,EAAa;AACpC,YAAA,MAAMC,kBAAkBtB,MAAAA,CAAOY,QAAQ,CAACQ,WAAAA,CAAYG,SAAS,EAAEV,UAAU;YACzE,OAAO;AACL,gBAAA,GAAGK,uBAAuB;gBAC1B,CAACE,WAAAA,CAAYG,SAAS,GAAGD;AAC3B,aAAA;AACF,QAAA;;QAGA,OAAOJ,uBAAAA;AACT,IAAA,CAAA,EACA,EAAC,CAAA;IAGH,OAAO;AACLM,QAAAA,MAAAA,EAAQC,QAAKC,0BAAAA,EAAkBf,gBAAAA,CAAAA;AAC/BG,QAAAA;AACF,KAAA;AACF,CAAA;AAEA,MAAMa,uBAAAA,GAA0B,CAAC,EAAE3B,MAAAA,EAAAA,OAAM,EAA2B,GAAA;AAClE,IAAA,MAAM4B,KAAAA,GAEF;QACFC,aAAAA,EAAe;AACjB,KAAA;AAEA,IAAA,MAAMC,eAAeC,wBAAAA,CAAmB;QAAE/B,MAAAA,EAAAA;AAAO,KAAA,CAAA;AACjD,IAAA,MAAM,EAAEgC,uBAAuB,EAAE,GAAGhC,OAAAA,CAAOiC,OAAO,CAAC,uBAAA,CAAA;IAEnD,OAAO;QACL,MAAMC,SAAAA,CAAAA,GAAAA;;YAEJ,IAAIN,KAAAA,CAAMC,aAAa,EAAE;AACvB,gBAAA;AACF,YAAA;;AAGA,YAAA,MAAMG,uBAAAA,CAAwB,yBAAA,CAAA;AAE9BhC,YAAAA,OAAAA,CAAOmC,SAAS,CAACC,GAAG,CAAC,OAAOrC,OAAAA,EAASsC,IAAAA,GAAAA;AACnC,gBAAA,MAAMC,SAAU,MAAMD,IAAAA,EAAAA;gBAEtB,IAAI,CAACvC,2BAA2BC,OAAAA,CAAAA,EAAU;oBACxC,OAAOuC,MAAAA;AACT,gBAAA;;AAGA,gBAAA,MAAMC,UAAAA,GACJxC,OAAAA,CAAQO,MAAM,KAAK,YAAYP,OAAAA,CAAQO,MAAM,KAAK,OAAA,GAC9CgC,OAAOC,UAAU,GACjBxC,OAAAA,CAAQyC,MAAM,CAACD,UAAU;;gBAG/B,MAAME,aAAAA,GAAgB,MAAMX,YAAAA,CAAaY,gBAAgB,EAAA;AACzD,gBAAA,MAAMC,OAAAA,GAAUC,YAAAA,CAAU7C,OAAAA,CAAQyC,MAAM,EAAEK,MAAAA,IAAUJ,aAAAA,CAAAA;gBACpD,IAAI,CAACE,OAAAA,CAAQG,MAAM,EAAE;oBACnB,OAAOR,MAAAA;AACT,gBAAA;;AAGA,gBAAA,MAAM7B,GAAAA,GAAMV,OAAAA,CAAQS,WAAW,CAACC,GAAG;AACnC,gBAAA,MAAMsC,UAAUrC,UAAAA,CAAWD,GAAAA,CAAAA;gBAC3B,MAAMuC,KAAAA,GAAQhD,OAAAA,CAAOY,QAAQ,CAACH,GAAAA,CAAAA;gBAE9B,MAAMwC,sBAAAA,GAAyBnB,YAAAA,CAAamB,sBAAsB,CAACD,KAAAA,CAAAA;;gBAGnE,MAAME,aAAAA,GAAgB,MAAMlD,OAAAA,CAAOmD,EAAE,CAACC,KAAK,CAAC3C,GAAAA,CAAAA,CAAK4C,QAAQ,CAAC;oBACxDC,KAAAA,EAAO;AACLf,wBAAAA,UAAAA;AACA,wBAAA,GAAIU,sBAAAA,GAAyB;4BAAEJ,MAAAA,EAAQ;gCAAEU,GAAAA,EAAKZ;AAAQ;AAAE,yBAAA,GAAI,EAAE;AAC9D,wBAAA,GAAIa,yBAAaC,kBAAkB,CAACzD,QAAOwD,YAAY,CAAC/C,IAAI,CAAA,GACxD;4BAAEiD,WAAAA,EAAa;AAAK,yBAAA,GACpB;AACN,qBAAA;oBACAC,QAAAA,EAAU7B,YAAAA,CAAa8B,eAAe,CAACnD,GAAAA,EAAK,IAAA;AAC9C,iBAAA,CAAA;gBAEA,MAAMT,OAAAA,CAAOmD,EAAE,CAACU,WAAW,CAAC,OAAO,EAAEC,QAAQ,EAAE,GAAA;;;;oBAI7CA,QAAAA,CAAS,UAAA;wBACP,KAAK,MAAMC,SAASb,aAAAA,CAAe;AACjC,4BAAA,MAAMc,MAAAA,GAAS,MAAMlC,YAAAA,CAAamC,gBAAgB,CAACxD,GAAAA,EAAKsD,KAAAA,CAAAA;AAExD,4BAAA,MAAMG,kBAAAA,CAAWlE,OAAAA,EAAQ,SAAA,CAAA,CAAWmE,aAAa,CAAC;gCAChD3D,WAAAA,EAAaC,GAAAA;AACb2D,gCAAAA,IAAAA,EAAM3C,QAAKC,0BAAAA,EAAkBqC,KAAAA,CAAAA;gCAC7BM,iBAAAA,EAAmB9B,UAAAA;AACnBM,gCAAAA,MAAAA,EAAQkB,MAAMlB,MAAM;AACpBmB,gCAAAA,MAAAA;AACA,gCAAA,GAAGjB;AACL,6BAAA,CAAA;AACF,wBAAA;AACF,oBAAA,CAAA,CAAA;AACF,gBAAA,CAAA,CAAA;gBAEA,OAAOT,MAAAA;AACT,YAAA,CAAA,CAAA;;YAGAtC,OAAAA,CAAOsE,IAAI,CAACC,GAAG,CAAC;gBACdC,kBAAAA,EAAoB;oBAClB,MAAMC,IAAAA,CAAAA,GAAAA;AACJ,wBAAA,MAAMC,UAAAA,GAAa,IAAA;AAEnB,wBAAA,MAAMC,8BACJ7C,YAAAA,CAAa8C,gBAAgB,EAAA,GAAK,EAAA,GAAK,KAAK,EAAA,GAAK,IAAA;AACnD,wBAAA,MAAMC,cAAAA,GAAiB,IAAIC,IAAAA,CAAKA,IAAAA,CAAKC,GAAG,EAAA,GAAKJ,2BAAAA,CAAAA;;;wBAI7C,IAAIK,OAAAA;wBACJ,GAAG;;4BAED,MAAMC,eAAAA,GAAkB,MAAMjF,OAAAA,CAAOmD,EAAE,CAACC,KAAK,CAAC8B,6BAAAA,CAAAA,CAAqB7B,QAAQ,CAAC;gCAC1E8B,MAAAA,EAAQ;AAAC,oCAAA;AAAK,iCAAA;gCACd7B,KAAAA,EAAO;oCACL8B,UAAAA,EAAY;wCACVC,GAAAA,EAAKR;AACP;AACF,iCAAA;gCACAS,KAAAA,EAAOZ;AACT,6BAAA,CAAA;AAEA,4BAAA,MAAMa,MAAMN,eAAAA,CAAgBO,GAAG,CAAC,CAACC,CAAAA,GAA+BA,EAAEC,EAAE,CAAA;AACpEV,4BAAAA,OAAAA,GAAUO,IAAIzC,MAAM;;AAGpB,4BAAA,IAAIkC,UAAU,CAAA,EAAG;AACf,gCAAA,MAAMhF,QAAOmD,EAAE,CAACC,KAAK,CAAC8B,6BAAAA,CAAAA,CAAqBS,UAAU,CAAC;oCACpDrC,KAAAA,EAAO;wCACLoC,EAAAA,EAAI;4CAAEnC,GAAAA,EAAKgC;AAAI;AACjB;AACF,iCAAA,CAAA;AACF,4BAAA;;;AAIF,wBAAA,CAAA,OAASP,WAAWN,UAAAA;AACtB,oBAAA,CAAA;oBACAkB,OAAAA,EAAS;AACX;AACF,aAAA,CAAA;AAEAhE,YAAAA,KAAAA,CAAMC,aAAa,GAAG,IAAA;AACxB,QAAA,CAAA;QAEA,MAAMgE,OAAAA,CAAAA,GAAAA;YACJ7F,OAAAA,CAAOsE,IAAI,CAACwB,MAAM,CAAC,oBAAA,CAAA;AACrB,QAAA;AACF,KAAA;AACF;;;;"}
1
+ {"version":3,"file":"lifecycles.js","sources":["../../../../server/src/history/services/lifecycles.ts"],"sourcesContent":["import type { Core, Modules, UID } from '@strapi/types';\nimport { contentTypes } from '@strapi/utils';\n\nimport { omit, castArray } from 'lodash/fp';\n\nimport { getService } from '../utils';\nimport { FIELDS_TO_IGNORE, HISTORY_VERSION_UID } from '../constants';\n\nimport type { CreateHistoryVersion } from '../../../../shared/contracts/history-versions';\nimport { createServiceUtils } from './utils';\n\n/**\n * Filters out actions that should not create a history version.\n */\nconst shouldCreateHistoryVersion = (\n context: Modules.Documents.Middleware.Context\n): context is Modules.Documents.Middleware.Context & {\n action: 'create' | 'update' | 'clone' | 'publish' | 'unpublish' | 'discardDraft';\n contentType: UID.CollectionType;\n} => {\n // Ignore requests that are not related to the content manager\n if (!strapi.requestContext.get()?.request.url.startsWith('/content-manager')) {\n return false;\n }\n\n // NOTE: cannot do type narrowing with array includes\n if (\n context.action !== 'create' &&\n context.action !== 'update' &&\n context.action !== 'clone' &&\n context.action !== 'publish' &&\n context.action !== 'unpublish' &&\n context.action !== 'discardDraft'\n ) {\n return false;\n }\n\n /**\n * When a document is published, the draft version of the document is also updated.\n * It creates confusion for users because they see two history versions each publish action.\n * To avoid this, we silence the update action during a publish request,\n * so that they only see the published version of the document in the history.\n */\n if (\n context.action === 'update' &&\n strapi.requestContext.get()?.request.url.split('?')[0].endsWith('/actions/publish')\n ) {\n return false;\n }\n\n // Ignore content types not created by the user\n if (!context.contentType.uid.startsWith('api::')) {\n return false;\n }\n\n return true;\n};\n\n/**\n * Returns the content type schema (and its components schemas).\n * Used to determine if changes were made in the content type builder since a history version was created.\n * And therefore which fields can be restored and which cannot.\n */\nconst getSchemas = (uid: UID.CollectionType) => {\n const attributesSchema = strapi.getModel(uid).attributes;\n\n // TODO: Handle nested components\n const componentsSchemas = Object.keys(attributesSchema).reduce(\n (currentComponentSchemas, key) => {\n const fieldSchema = attributesSchema[key];\n\n if (fieldSchema.type === 'component') {\n const componentSchema = strapi.getModel(fieldSchema.component).attributes;\n return {\n ...currentComponentSchemas,\n [fieldSchema.component]: componentSchema,\n };\n }\n\n // Ignore anything that's not a component\n return currentComponentSchemas;\n },\n {} as CreateHistoryVersion['componentsSchemas']\n );\n\n return {\n schema: omit(FIELDS_TO_IGNORE, attributesSchema) as CreateHistoryVersion['schema'],\n componentsSchemas,\n };\n};\n\nconst createLifecyclesService = ({ strapi }: { strapi: Core.Strapi }) => {\n const state: {\n isInitialized: boolean;\n } = {\n isInitialized: false,\n };\n\n const serviceUtils = createServiceUtils({ strapi });\n const { persistTablesWithPrefix } = strapi.service('admin::persist-tables');\n\n return {\n async bootstrap() {\n // Prevent initializing the service twice\n if (state.isInitialized) {\n return;\n }\n\n // Avoid data loss in case users temporarily don't have a license\n await persistTablesWithPrefix('strapi_history_versions');\n\n strapi.documents.use(async (context, next) => {\n const result = (await next()) as any;\n\n if (!shouldCreateHistoryVersion(context)) {\n return result;\n }\n\n // On create/clone actions, the documentId is not available before creating the action is executed\n const documentId =\n context.action === 'create' || context.action === 'clone'\n ? result.documentId\n : context.params.documentId;\n\n // Apply default locale if not available in the request\n const defaultLocale = await serviceUtils.getDefaultLocale();\n const locales = castArray(context.params?.locale || defaultLocale);\n if (!locales.length) {\n return result;\n }\n\n // All schemas related to the content type\n const uid = context.contentType.uid;\n const schemas = getSchemas(uid);\n const model = strapi.getModel(uid);\n\n const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);\n\n // Find all affected entries\n const localeEntries = await strapi.db.query(uid).findMany({\n where: {\n documentId,\n ...(isLocalizedContentType ? { locale: { $in: locales } } : {}),\n ...(contentTypes.hasDraftAndPublish(strapi.contentTypes[uid])\n ? { publishedAt: null }\n : {}),\n },\n populate: serviceUtils.getDeepPopulate(uid, true /* use database syntax */),\n });\n\n await strapi.db.transaction(async ({ onCommit }) => {\n // .createVersion() is executed asynchronously,\n // onCommit prevents creating a history version\n // when the transaction has already been committed\n onCommit(async () => {\n for (const entry of localeEntries) {\n const status = await serviceUtils.getVersionStatus(uid, entry);\n\n await getService(strapi, 'history').createVersion({\n contentType: uid,\n data: omit(FIELDS_TO_IGNORE, entry) as Modules.Documents.AnyDocument,\n relatedDocumentId: documentId,\n locale: entry.locale,\n status,\n ...schemas,\n });\n }\n });\n });\n\n return result;\n });\n\n // Schedule a job to delete expired history versions every day at midnight\n strapi.cron.add({\n deleteHistoryDaily: {\n async task() {\n const BATCH_SIZE = 1000;\n\n const retentionDaysInMilliseconds =\n serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1000;\n const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);\n\n // Delete in batches of 1000 to avoid a single query that\n // exhausts the DB connection pool and blocks other operations.\n let deleted: number;\n do {\n // Fetch up to BATCH_SIZE expired IDs\n const expiredVersions = await strapi.db.query(HISTORY_VERSION_UID).findMany({\n select: ['id'],\n where: {\n created_at: {\n $lt: expirationDate,\n },\n },\n limit: BATCH_SIZE,\n });\n\n const ids = expiredVersions.map((v: { id: number | string }) => v.id);\n deleted = ids.length;\n\n // Delete this batch by ID\n if (deleted > 0) {\n await strapi.db.query(HISTORY_VERSION_UID).deleteMany({\n where: {\n id: { $in: ids },\n },\n });\n }\n\n // If we got a full batch, there are likely more rows to delete — loop again.\n // If we got fewer, we've handled everything and can stop.\n } while (deleted >= BATCH_SIZE);\n },\n options: '0 0 * * *',\n },\n });\n\n state.isInitialized = true;\n },\n\n async destroy() {\n strapi.cron.remove('deleteHistoryDaily');\n },\n };\n};\n\nexport { createLifecyclesService };\n"],"names":["shouldCreateHistoryVersion","context","strapi","requestContext","get","request","url","startsWith","action","split","endsWith","contentType","uid","getSchemas","attributesSchema","getModel","attributes","componentsSchemas","Object","keys","reduce","currentComponentSchemas","key","fieldSchema","type","componentSchema","component","schema","omit","FIELDS_TO_IGNORE","createLifecyclesService","state","isInitialized","serviceUtils","createServiceUtils","persistTablesWithPrefix","service","bootstrap","documents","use","next","result","documentId","params","defaultLocale","getDefaultLocale","locales","castArray","locale","length","schemas","model","isLocalizedContentType","localeEntries","db","query","findMany","where","$in","contentTypes","hasDraftAndPublish","publishedAt","populate","getDeepPopulate","transaction","onCommit","entry","status","getVersionStatus","getService","createVersion","data","relatedDocumentId","cron","add","deleteHistoryDaily","task","BATCH_SIZE","retentionDaysInMilliseconds","getRetentionDays","expirationDate","Date","now","deleted","expiredVersions","HISTORY_VERSION_UID","select","created_at","$lt","limit","ids","map","v","id","deleteMany","options","destroy","remove"],"mappings":"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"}
@@ -20,7 +20,7 @@ import { createServiceUtils } from './utils.mjs';
20
20
  * It creates confusion for users because they see two history versions each publish action.
21
21
  * To avoid this, we silence the update action during a publish request,
22
22
  * so that they only see the published version of the document in the history.
23
- */ if (context.action === 'update' && strapi.requestContext.get()?.request.url.endsWith('/actions/publish')) {
23
+ */ if (context.action === 'update' && strapi.requestContext.get()?.request.url.split('?')[0].endsWith('/actions/publish')) {
24
24
  return false;
25
25
  }
26
26
  // Ignore content types not created by the user
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycles.mjs","sources":["../../../../server/src/history/services/lifecycles.ts"],"sourcesContent":["import type { Core, Modules, UID } from '@strapi/types';\nimport { contentTypes } from '@strapi/utils';\n\nimport { omit, castArray } from 'lodash/fp';\n\nimport { getService } from '../utils';\nimport { FIELDS_TO_IGNORE, HISTORY_VERSION_UID } from '../constants';\n\nimport type { CreateHistoryVersion } from '../../../../shared/contracts/history-versions';\nimport { createServiceUtils } from './utils';\n\n/**\n * Filters out actions that should not create a history version.\n */\nconst shouldCreateHistoryVersion = (\n context: Modules.Documents.Middleware.Context\n): context is Modules.Documents.Middleware.Context & {\n action: 'create' | 'update' | 'clone' | 'publish' | 'unpublish' | 'discardDraft';\n contentType: UID.CollectionType;\n} => {\n // Ignore requests that are not related to the content manager\n if (!strapi.requestContext.get()?.request.url.startsWith('/content-manager')) {\n return false;\n }\n\n // NOTE: cannot do type narrowing with array includes\n if (\n context.action !== 'create' &&\n context.action !== 'update' &&\n context.action !== 'clone' &&\n context.action !== 'publish' &&\n context.action !== 'unpublish' &&\n context.action !== 'discardDraft'\n ) {\n return false;\n }\n\n /**\n * When a document is published, the draft version of the document is also updated.\n * It creates confusion for users because they see two history versions each publish action.\n * To avoid this, we silence the update action during a publish request,\n * so that they only see the published version of the document in the history.\n */\n if (\n context.action === 'update' &&\n strapi.requestContext.get()?.request.url.endsWith('/actions/publish')\n ) {\n return false;\n }\n\n // Ignore content types not created by the user\n if (!context.contentType.uid.startsWith('api::')) {\n return false;\n }\n\n return true;\n};\n\n/**\n * Returns the content type schema (and its components schemas).\n * Used to determine if changes were made in the content type builder since a history version was created.\n * And therefore which fields can be restored and which cannot.\n */\nconst getSchemas = (uid: UID.CollectionType) => {\n const attributesSchema = strapi.getModel(uid).attributes;\n\n // TODO: Handle nested components\n const componentsSchemas = Object.keys(attributesSchema).reduce(\n (currentComponentSchemas, key) => {\n const fieldSchema = attributesSchema[key];\n\n if (fieldSchema.type === 'component') {\n const componentSchema = strapi.getModel(fieldSchema.component).attributes;\n return {\n ...currentComponentSchemas,\n [fieldSchema.component]: componentSchema,\n };\n }\n\n // Ignore anything that's not a component\n return currentComponentSchemas;\n },\n {} as CreateHistoryVersion['componentsSchemas']\n );\n\n return {\n schema: omit(FIELDS_TO_IGNORE, attributesSchema) as CreateHistoryVersion['schema'],\n componentsSchemas,\n };\n};\n\nconst createLifecyclesService = ({ strapi }: { strapi: Core.Strapi }) => {\n const state: {\n isInitialized: boolean;\n } = {\n isInitialized: false,\n };\n\n const serviceUtils = createServiceUtils({ strapi });\n const { persistTablesWithPrefix } = strapi.service('admin::persist-tables');\n\n return {\n async bootstrap() {\n // Prevent initializing the service twice\n if (state.isInitialized) {\n return;\n }\n\n // Avoid data loss in case users temporarily don't have a license\n await persistTablesWithPrefix('strapi_history_versions');\n\n strapi.documents.use(async (context, next) => {\n const result = (await next()) as any;\n\n if (!shouldCreateHistoryVersion(context)) {\n return result;\n }\n\n // On create/clone actions, the documentId is not available before creating the action is executed\n const documentId =\n context.action === 'create' || context.action === 'clone'\n ? result.documentId\n : context.params.documentId;\n\n // Apply default locale if not available in the request\n const defaultLocale = await serviceUtils.getDefaultLocale();\n const locales = castArray(context.params?.locale || defaultLocale);\n if (!locales.length) {\n return result;\n }\n\n // All schemas related to the content type\n const uid = context.contentType.uid;\n const schemas = getSchemas(uid);\n const model = strapi.getModel(uid);\n\n const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);\n\n // Find all affected entries\n const localeEntries = await strapi.db.query(uid).findMany({\n where: {\n documentId,\n ...(isLocalizedContentType ? { locale: { $in: locales } } : {}),\n ...(contentTypes.hasDraftAndPublish(strapi.contentTypes[uid])\n ? { publishedAt: null }\n : {}),\n },\n populate: serviceUtils.getDeepPopulate(uid, true /* use database syntax */),\n });\n\n await strapi.db.transaction(async ({ onCommit }) => {\n // .createVersion() is executed asynchronously,\n // onCommit prevents creating a history version\n // when the transaction has already been committed\n onCommit(async () => {\n for (const entry of localeEntries) {\n const status = await serviceUtils.getVersionStatus(uid, entry);\n\n await getService(strapi, 'history').createVersion({\n contentType: uid,\n data: omit(FIELDS_TO_IGNORE, entry) as Modules.Documents.AnyDocument,\n relatedDocumentId: documentId,\n locale: entry.locale,\n status,\n ...schemas,\n });\n }\n });\n });\n\n return result;\n });\n\n // Schedule a job to delete expired history versions every day at midnight\n strapi.cron.add({\n deleteHistoryDaily: {\n async task() {\n const BATCH_SIZE = 1000;\n\n const retentionDaysInMilliseconds =\n serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1000;\n const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);\n\n // Delete in batches of 1000 to avoid a single query that\n // exhausts the DB connection pool and blocks other operations.\n let deleted: number;\n do {\n // Fetch up to BATCH_SIZE expired IDs\n const expiredVersions = await strapi.db.query(HISTORY_VERSION_UID).findMany({\n select: ['id'],\n where: {\n created_at: {\n $lt: expirationDate,\n },\n },\n limit: BATCH_SIZE,\n });\n\n const ids = expiredVersions.map((v: { id: number | string }) => v.id);\n deleted = ids.length;\n\n // Delete this batch by ID\n if (deleted > 0) {\n await strapi.db.query(HISTORY_VERSION_UID).deleteMany({\n where: {\n id: { $in: ids },\n },\n });\n }\n\n // If we got a full batch, there are likely more rows to delete — loop again.\n // If we got fewer, we've handled everything and can stop.\n } while (deleted >= BATCH_SIZE);\n },\n options: '0 0 * * *',\n },\n });\n\n state.isInitialized = true;\n },\n\n async destroy() {\n strapi.cron.remove('deleteHistoryDaily');\n },\n };\n};\n\nexport { createLifecyclesService };\n"],"names":["shouldCreateHistoryVersion","context","strapi","requestContext","get","request","url","startsWith","action","endsWith","contentType","uid","getSchemas","attributesSchema","getModel","attributes","componentsSchemas","Object","keys","reduce","currentComponentSchemas","key","fieldSchema","type","componentSchema","component","schema","omit","FIELDS_TO_IGNORE","createLifecyclesService","state","isInitialized","serviceUtils","createServiceUtils","persistTablesWithPrefix","service","bootstrap","documents","use","next","result","documentId","params","defaultLocale","getDefaultLocale","locales","castArray","locale","length","schemas","model","isLocalizedContentType","localeEntries","db","query","findMany","where","$in","contentTypes","hasDraftAndPublish","publishedAt","populate","getDeepPopulate","transaction","onCommit","entry","status","getVersionStatus","getService","createVersion","data","relatedDocumentId","cron","add","deleteHistoryDaily","task","BATCH_SIZE","retentionDaysInMilliseconds","getRetentionDays","expirationDate","Date","now","deleted","expiredVersions","HISTORY_VERSION_UID","select","created_at","$lt","limit","ids","map","v","id","deleteMany","options","destroy","remove"],"mappings":"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"}
1
+ {"version":3,"file":"lifecycles.mjs","sources":["../../../../server/src/history/services/lifecycles.ts"],"sourcesContent":["import type { Core, Modules, UID } from '@strapi/types';\nimport { contentTypes } from '@strapi/utils';\n\nimport { omit, castArray } from 'lodash/fp';\n\nimport { getService } from '../utils';\nimport { FIELDS_TO_IGNORE, HISTORY_VERSION_UID } from '../constants';\n\nimport type { CreateHistoryVersion } from '../../../../shared/contracts/history-versions';\nimport { createServiceUtils } from './utils';\n\n/**\n * Filters out actions that should not create a history version.\n */\nconst shouldCreateHistoryVersion = (\n context: Modules.Documents.Middleware.Context\n): context is Modules.Documents.Middleware.Context & {\n action: 'create' | 'update' | 'clone' | 'publish' | 'unpublish' | 'discardDraft';\n contentType: UID.CollectionType;\n} => {\n // Ignore requests that are not related to the content manager\n if (!strapi.requestContext.get()?.request.url.startsWith('/content-manager')) {\n return false;\n }\n\n // NOTE: cannot do type narrowing with array includes\n if (\n context.action !== 'create' &&\n context.action !== 'update' &&\n context.action !== 'clone' &&\n context.action !== 'publish' &&\n context.action !== 'unpublish' &&\n context.action !== 'discardDraft'\n ) {\n return false;\n }\n\n /**\n * When a document is published, the draft version of the document is also updated.\n * It creates confusion for users because they see two history versions each publish action.\n * To avoid this, we silence the update action during a publish request,\n * so that they only see the published version of the document in the history.\n */\n if (\n context.action === 'update' &&\n strapi.requestContext.get()?.request.url.split('?')[0].endsWith('/actions/publish')\n ) {\n return false;\n }\n\n // Ignore content types not created by the user\n if (!context.contentType.uid.startsWith('api::')) {\n return false;\n }\n\n return true;\n};\n\n/**\n * Returns the content type schema (and its components schemas).\n * Used to determine if changes were made in the content type builder since a history version was created.\n * And therefore which fields can be restored and which cannot.\n */\nconst getSchemas = (uid: UID.CollectionType) => {\n const attributesSchema = strapi.getModel(uid).attributes;\n\n // TODO: Handle nested components\n const componentsSchemas = Object.keys(attributesSchema).reduce(\n (currentComponentSchemas, key) => {\n const fieldSchema = attributesSchema[key];\n\n if (fieldSchema.type === 'component') {\n const componentSchema = strapi.getModel(fieldSchema.component).attributes;\n return {\n ...currentComponentSchemas,\n [fieldSchema.component]: componentSchema,\n };\n }\n\n // Ignore anything that's not a component\n return currentComponentSchemas;\n },\n {} as CreateHistoryVersion['componentsSchemas']\n );\n\n return {\n schema: omit(FIELDS_TO_IGNORE, attributesSchema) as CreateHistoryVersion['schema'],\n componentsSchemas,\n };\n};\n\nconst createLifecyclesService = ({ strapi }: { strapi: Core.Strapi }) => {\n const state: {\n isInitialized: boolean;\n } = {\n isInitialized: false,\n };\n\n const serviceUtils = createServiceUtils({ strapi });\n const { persistTablesWithPrefix } = strapi.service('admin::persist-tables');\n\n return {\n async bootstrap() {\n // Prevent initializing the service twice\n if (state.isInitialized) {\n return;\n }\n\n // Avoid data loss in case users temporarily don't have a license\n await persistTablesWithPrefix('strapi_history_versions');\n\n strapi.documents.use(async (context, next) => {\n const result = (await next()) as any;\n\n if (!shouldCreateHistoryVersion(context)) {\n return result;\n }\n\n // On create/clone actions, the documentId is not available before creating the action is executed\n const documentId =\n context.action === 'create' || context.action === 'clone'\n ? result.documentId\n : context.params.documentId;\n\n // Apply default locale if not available in the request\n const defaultLocale = await serviceUtils.getDefaultLocale();\n const locales = castArray(context.params?.locale || defaultLocale);\n if (!locales.length) {\n return result;\n }\n\n // All schemas related to the content type\n const uid = context.contentType.uid;\n const schemas = getSchemas(uid);\n const model = strapi.getModel(uid);\n\n const isLocalizedContentType = serviceUtils.isLocalizedContentType(model);\n\n // Find all affected entries\n const localeEntries = await strapi.db.query(uid).findMany({\n where: {\n documentId,\n ...(isLocalizedContentType ? { locale: { $in: locales } } : {}),\n ...(contentTypes.hasDraftAndPublish(strapi.contentTypes[uid])\n ? { publishedAt: null }\n : {}),\n },\n populate: serviceUtils.getDeepPopulate(uid, true /* use database syntax */),\n });\n\n await strapi.db.transaction(async ({ onCommit }) => {\n // .createVersion() is executed asynchronously,\n // onCommit prevents creating a history version\n // when the transaction has already been committed\n onCommit(async () => {\n for (const entry of localeEntries) {\n const status = await serviceUtils.getVersionStatus(uid, entry);\n\n await getService(strapi, 'history').createVersion({\n contentType: uid,\n data: omit(FIELDS_TO_IGNORE, entry) as Modules.Documents.AnyDocument,\n relatedDocumentId: documentId,\n locale: entry.locale,\n status,\n ...schemas,\n });\n }\n });\n });\n\n return result;\n });\n\n // Schedule a job to delete expired history versions every day at midnight\n strapi.cron.add({\n deleteHistoryDaily: {\n async task() {\n const BATCH_SIZE = 1000;\n\n const retentionDaysInMilliseconds =\n serviceUtils.getRetentionDays() * 24 * 60 * 60 * 1000;\n const expirationDate = new Date(Date.now() - retentionDaysInMilliseconds);\n\n // Delete in batches of 1000 to avoid a single query that\n // exhausts the DB connection pool and blocks other operations.\n let deleted: number;\n do {\n // Fetch up to BATCH_SIZE expired IDs\n const expiredVersions = await strapi.db.query(HISTORY_VERSION_UID).findMany({\n select: ['id'],\n where: {\n created_at: {\n $lt: expirationDate,\n },\n },\n limit: BATCH_SIZE,\n });\n\n const ids = expiredVersions.map((v: { id: number | string }) => v.id);\n deleted = ids.length;\n\n // Delete this batch by ID\n if (deleted > 0) {\n await strapi.db.query(HISTORY_VERSION_UID).deleteMany({\n where: {\n id: { $in: ids },\n },\n });\n }\n\n // If we got a full batch, there are likely more rows to delete — loop again.\n // If we got fewer, we've handled everything and can stop.\n } while (deleted >= BATCH_SIZE);\n },\n options: '0 0 * * *',\n },\n });\n\n state.isInitialized = true;\n },\n\n async destroy() {\n strapi.cron.remove('deleteHistoryDaily');\n },\n };\n};\n\nexport { createLifecyclesService };\n"],"names":["shouldCreateHistoryVersion","context","strapi","requestContext","get","request","url","startsWith","action","split","endsWith","contentType","uid","getSchemas","attributesSchema","getModel","attributes","componentsSchemas","Object","keys","reduce","currentComponentSchemas","key","fieldSchema","type","componentSchema","component","schema","omit","FIELDS_TO_IGNORE","createLifecyclesService","state","isInitialized","serviceUtils","createServiceUtils","persistTablesWithPrefix","service","bootstrap","documents","use","next","result","documentId","params","defaultLocale","getDefaultLocale","locales","castArray","locale","length","schemas","model","isLocalizedContentType","localeEntries","db","query","findMany","where","$in","contentTypes","hasDraftAndPublish","publishedAt","populate","getDeepPopulate","transaction","onCommit","entry","status","getVersionStatus","getService","createVersion","data","relatedDocumentId","cron","add","deleteHistoryDaily","task","BATCH_SIZE","retentionDaysInMilliseconds","getRetentionDays","expirationDate","Date","now","deleted","expiredVersions","HISTORY_VERSION_UID","select","created_at","$lt","limit","ids","map","v","id","deleteMany","options","destroy","remove"],"mappings":"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"}
@@ -1,43 +1,23 @@
1
1
  'use strict';
2
2
 
3
- var yup = require('yup');
4
3
  var strapiUtils = require('@strapi/utils');
5
4
 
6
- function _interopNamespaceDefault(e) {
7
- var n = Object.create(null);
8
- if (e) {
9
- Object.keys(e).forEach(function (k) {
10
- if (k !== 'default') {
11
- var d = Object.getOwnPropertyDescriptor(e, k);
12
- Object.defineProperty(n, k, d.get ? d : {
13
- enumerable: true,
14
- get: function () { return e[k]; }
15
- });
16
- }
17
- });
18
- }
19
- n.default = e;
20
- return Object.freeze(n);
21
- }
22
-
23
- var yup__namespace = /*#__PURE__*/_interopNamespaceDefault(yup);
24
-
25
5
  const createHomepageController = ()=>{
26
6
  const homepageService = strapi.plugin('content-manager').service('homepage');
27
- const recentDocumentParamsSchema = yup__namespace.object().shape({
28
- action: yup__namespace.mixed().oneOf([
7
+ const recentDocumentParamsSchema = strapiUtils.z.object({
8
+ action: strapiUtils.z.enum([
29
9
  'update',
30
10
  'publish'
31
- ]).required()
11
+ ])
32
12
  });
33
13
  return {
34
14
  async getRecentDocuments (ctx) {
35
15
  let action;
36
16
  try {
37
- action = (await recentDocumentParamsSchema.validate(ctx.query)).action;
17
+ action = recentDocumentParamsSchema.parse(ctx.query).action;
38
18
  } catch (error) {
39
- if (error instanceof yup__namespace.ValidationError) {
40
- throw new strapiUtils.errors.ValidationError(error.message);
19
+ if (error instanceof strapiUtils.z.ZodError) {
20
+ throw new strapiUtils.errors.ValidationError(error.issues[0]?.message ?? 'Validation error');
41
21
  }
42
22
  throw error;
43
23
  }
@@ -1 +1 @@
1
- {"version":3,"file":"homepage.js","sources":["../../../../server/src/homepage/controllers/homepage.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\nimport * as yup from 'yup';\nimport { errors } from '@strapi/utils';\nimport type { GetRecentDocuments, GetCountDocuments } from '../../../../shared/contracts/homepage';\n\nconst createHomepageController = () => {\n const homepageService = strapi.plugin('content-manager').service('homepage');\n\n const recentDocumentParamsSchema = yup.object().shape({\n action: yup\n .mixed<GetRecentDocuments.Request['query']['action']>()\n .oneOf(['update', 'publish'])\n .required(),\n });\n\n return {\n async getRecentDocuments(ctx): Promise<GetRecentDocuments.Response> {\n let action;\n\n try {\n action = (await recentDocumentParamsSchema.validate(ctx.query)).action;\n } catch (error) {\n if (error instanceof yup.ValidationError) {\n throw new errors.ValidationError(error.message);\n }\n throw error;\n }\n\n if (action === 'publish') {\n return { data: await homepageService.getRecentlyPublishedDocuments() };\n }\n\n return { data: await homepageService.getRecentlyUpdatedDocuments() };\n },\n async getCountDocuments(): Promise<GetCountDocuments.Response> {\n return { data: await homepageService.getCountDocuments() };\n },\n } satisfies Core.Controller;\n};\n\nexport { createHomepageController };\n"],"names":["createHomepageController","homepageService","strapi","plugin","service","recentDocumentParamsSchema","yup","object","shape","action","mixed","oneOf","required","getRecentDocuments","ctx","validate","query","error","ValidationError","errors","message","data","getRecentlyPublishedDocuments","getRecentlyUpdatedDocuments","getCountDocuments"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAKA,MAAMA,wBAAAA,GAA2B,IAAA;AAC/B,IAAA,MAAMC,kBAAkBC,MAAAA,CAAOC,MAAM,CAAC,iBAAA,CAAA,CAAmBC,OAAO,CAAC,UAAA,CAAA;AAEjE,IAAA,MAAMC,0BAAAA,GAA6BC,cAAAA,CAAIC,MAAM,EAAA,CAAGC,KAAK,CAAC;AACpDC,QAAAA,MAAAA,EAAQH,cAAAA,CACLI,KAAK,EAAA,CACLC,KAAK,CAAC;AAAC,YAAA,QAAA;AAAU,YAAA;AAAU,SAAA,CAAA,CAC3BC,QAAQ;AACb,KAAA,CAAA;IAEA,OAAO;AACL,QAAA,MAAMC,oBAAmBC,GAAG,EAAA;YAC1B,IAAIL,MAAAA;YAEJ,IAAI;gBACFA,MAAAA,GAAU,CAAA,MAAMJ,0BAAAA,CAA2BU,QAAQ,CAACD,GAAAA,CAAIE,KAAK,CAAA,EAAGP,MAAM;AACxE,YAAA,CAAA,CAAE,OAAOQ,KAAAA,EAAO;gBACd,IAAIA,KAAAA,YAAiBX,cAAAA,CAAIY,eAAe,EAAE;AACxC,oBAAA,MAAM,IAAIC,kBAAAA,CAAOD,eAAe,CAACD,MAAMG,OAAO,CAAA;AAChD,gBAAA;gBACA,MAAMH,KAAAA;AACR,YAAA;AAEA,YAAA,IAAIR,WAAW,SAAA,EAAW;gBACxB,OAAO;oBAAEY,IAAAA,EAAM,MAAMpB,gBAAgBqB,6BAA6B;AAAG,iBAAA;AACvE,YAAA;YAEA,OAAO;gBAAED,IAAAA,EAAM,MAAMpB,gBAAgBsB,2BAA2B;AAAG,aAAA;AACrE,QAAA,CAAA;QACA,MAAMC,iBAAAA,CAAAA,GAAAA;YACJ,OAAO;gBAAEH,IAAAA,EAAM,MAAMpB,gBAAgBuB,iBAAiB;AAAG,aAAA;AAC3D,QAAA;AACF,KAAA;AACF;;;;"}
1
+ {"version":3,"file":"homepage.js","sources":["../../../../server/src/homepage/controllers/homepage.ts"],"sourcesContent":["import type { Core } from '@strapi/types';\nimport { z, errors } from '@strapi/utils';\nimport type { GetRecentDocuments, GetCountDocuments } from '../../../../shared/contracts/homepage';\n\nconst createHomepageController = () => {\n const homepageService = strapi.plugin('content-manager').service('homepage');\n\n const recentDocumentParamsSchema = z.object({\n action: z.enum(['update', 'publish']),\n });\n\n return {\n async getRecentDocuments(ctx): Promise<GetRecentDocuments.Response> {\n let action;\n\n try {\n action = recentDocumentParamsSchema.parse(ctx.query).action;\n } catch (error) {\n if (error instanceof z.ZodError) {\n throw new errors.ValidationError(error.issues[0]?.message ?? 'Validation error');\n }\n throw error;\n }\n\n if (action === 'publish') {\n return { data: await homepageService.getRecentlyPublishedDocuments() };\n }\n\n return { data: await homepageService.getRecentlyUpdatedDocuments() };\n },\n async getCountDocuments(): Promise<GetCountDocuments.Response> {\n return { data: await homepageService.getCountDocuments() };\n },\n } satisfies Core.Controller;\n};\n\nexport { createHomepageController };\n"],"names":["createHomepageController","homepageService","strapi","plugin","service","recentDocumentParamsSchema","z","object","action","enum","getRecentDocuments","ctx","parse","query","error","ZodError","errors","ValidationError","issues","message","data","getRecentlyPublishedDocuments","getRecentlyUpdatedDocuments","getCountDocuments"],"mappings":";;;;AAIA,MAAMA,wBAAAA,GAA2B,IAAA;AAC/B,IAAA,MAAMC,kBAAkBC,MAAAA,CAAOC,MAAM,CAAC,iBAAA,CAAA,CAAmBC,OAAO,CAAC,UAAA,CAAA;IAEjE,MAAMC,0BAAAA,GAA6BC,aAAAA,CAAEC,MAAM,CAAC;QAC1CC,MAAAA,EAAQF,aAAAA,CAAEG,IAAI,CAAC;AAAC,YAAA,QAAA;AAAU,YAAA;AAAU,SAAA;AACtC,KAAA,CAAA;IAEA,OAAO;AACL,QAAA,MAAMC,oBAAmBC,GAAG,EAAA;YAC1B,IAAIH,MAAAA;YAEJ,IAAI;AACFA,gBAAAA,MAAAA,GAASH,2BAA2BO,KAAK,CAACD,GAAAA,CAAIE,KAAK,EAAEL,MAAM;AAC7D,YAAA,CAAA,CAAE,OAAOM,KAAAA,EAAO;gBACd,IAAIA,KAAAA,YAAiBR,aAAAA,CAAES,QAAQ,EAAE;oBAC/B,MAAM,IAAIC,mBAAOC,eAAe,CAACH,MAAMI,MAAM,CAAC,CAAA,CAAE,EAAEC,OAAAA,IAAW,kBAAA,CAAA;AAC/D,gBAAA;gBACA,MAAML,KAAAA;AACR,YAAA;AAEA,YAAA,IAAIN,WAAW,SAAA,EAAW;gBACxB,OAAO;oBAAEY,IAAAA,EAAM,MAAMnB,gBAAgBoB,6BAA6B;AAAG,iBAAA;AACvE,YAAA;YAEA,OAAO;gBAAED,IAAAA,EAAM,MAAMnB,gBAAgBqB,2BAA2B;AAAG,aAAA;AACrE,QAAA,CAAA;QACA,MAAMC,iBAAAA,CAAAA,GAAAA;YACJ,OAAO;gBAAEH,IAAAA,EAAM,MAAMnB,gBAAgBsB,iBAAiB;AAAG,aAAA;AAC3D,QAAA;AACF,KAAA;AACF;;;;"}