strapi-plugin-publish-media-validation 1.1.0 → 1.1.2
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAO,MAAM,gBAAgB,CAAC;;2BAiHlB;QAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;KAAE;uBAoD3B;QAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;KAAE;qBACzB;QAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAA;KAAE;;AAE/C,wBAAgD"}
|
package/dist/server/index.js
CHANGED
|
@@ -1,26 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const path_1 = __importDefault(require("path"));
|
|
7
3
|
function resolveValidationError() {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
4
|
+
try {
|
|
5
|
+
// @strapi/utils is always present in the host Strapi project; require()
|
|
6
|
+
// loads the CJS build, which is the same instance Strapi's error
|
|
7
|
+
// middleware uses for instanceof checks → errors become 400, not 500.
|
|
8
|
+
return require('@strapi/utils').errors.ValidationError;
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return class extends Error {
|
|
12
|
+
constructor(message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = 'ValidationError';
|
|
15
|
+
this.status = 400;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
16
18
|
}
|
|
17
|
-
return class extends Error {
|
|
18
|
-
constructor(message) {
|
|
19
|
-
super(message);
|
|
20
|
-
this.name = 'ValidationError';
|
|
21
|
-
this.status = 400;
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
19
|
}
|
|
25
20
|
/**
|
|
26
21
|
* Recursively build a Strapi populate object that covers every media field
|
|
@@ -121,9 +116,23 @@ const register = ({ strapi }) => {
|
|
|
121
116
|
const missing = collectMissingMedia(doc, ctx.uid, strapi);
|
|
122
117
|
if (missing.length > 0) {
|
|
123
118
|
const labels = missing
|
|
124
|
-
.map((
|
|
119
|
+
.map((rawPath) => rawPath
|
|
120
|
+
.split(' > ')
|
|
121
|
+
.map((seg) => {
|
|
122
|
+
// "blocks[2]" → "Blocks (item 2)"
|
|
123
|
+
const indexed = seg.match(/^(.+?)\[(\d+)\]$/);
|
|
124
|
+
if (indexed) {
|
|
125
|
+
const name = indexed[1].charAt(0).toUpperCase() +
|
|
126
|
+
indexed[1].slice(1).replace(/([A-Z])/g, ' $1').replace(/_/g, ' ');
|
|
127
|
+
return `${name} (item ${indexed[2]})`;
|
|
128
|
+
}
|
|
129
|
+
return seg.charAt(0).toUpperCase() +
|
|
130
|
+
seg.slice(1).replace(/([A-Z])/g, ' $1').replace(/_/g, ' ');
|
|
131
|
+
})
|
|
132
|
+
.join(' › '))
|
|
125
133
|
.join(', ');
|
|
126
|
-
|
|
134
|
+
const verb = missing.length === 1 ? 'field is' : 'fields are';
|
|
135
|
+
throw new ValidationError(`Cannot publish: required media ${verb} missing — ${labels}`);
|
|
127
136
|
}
|
|
128
137
|
return next();
|
|
129
138
|
});
|
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "strapi-plugin-publish-media-validation",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "Strapi v5 plugin that enforces required media fields at publish time — works around the known limitation where required: true on media fields is not validated on publish.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -165,7 +165,7 @@ describe('middleware — flat media fields', () => {
|
|
|
165
165
|
);
|
|
166
166
|
const { result } = runMiddleware(baseCtx);
|
|
167
167
|
await expect(result).rejects.toThrow(errors.ValidationError);
|
|
168
|
-
await expect(result).rejects.toThrow('Cover');
|
|
168
|
+
await expect(result).rejects.toThrow('Cannot publish: required media field is missing — Cover');
|
|
169
169
|
});
|
|
170
170
|
|
|
171
171
|
it('lists all missing fields in the error message', async () => {
|
|
@@ -177,6 +177,7 @@ describe('middleware — flat media fields', () => {
|
|
|
177
177
|
{ cover: null, heroImage: null }
|
|
178
178
|
);
|
|
179
179
|
const { result } = runMiddleware(baseCtx);
|
|
180
|
+
await expect(result).rejects.toThrow('Cannot publish: required media fields are missing');
|
|
180
181
|
await expect(result).rejects.toThrow('Cover');
|
|
181
182
|
await expect(result).rejects.toThrow('Hero Image');
|
|
182
183
|
});
|
|
@@ -247,7 +248,7 @@ describe('middleware — component fields', () => {
|
|
|
247
248
|
);
|
|
248
249
|
const { result } = runMiddleware();
|
|
249
250
|
await expect(result).rejects.toThrow(errors.ValidationError);
|
|
250
|
-
await expect(result).rejects.toThrow('Hero
|
|
251
|
+
await expect(result).rejects.toThrow('Hero › Photo');
|
|
251
252
|
});
|
|
252
253
|
|
|
253
254
|
it('passes through when all repeatable component items have required media', async () => {
|
|
@@ -272,7 +273,7 @@ describe('middleware — component fields', () => {
|
|
|
272
273
|
{ cards: [{ photo: { id: 1 } }, { photo: null }] }
|
|
273
274
|
);
|
|
274
275
|
const { result } = runMiddleware();
|
|
275
|
-
await expect(result).rejects.toThrow('Cards
|
|
276
|
+
await expect(result).rejects.toThrow('Cards (item 2) › Photo');
|
|
276
277
|
});
|
|
277
278
|
|
|
278
279
|
it('builds populate that includes the component media field', async () => {
|
|
@@ -332,7 +333,7 @@ describe('middleware — dynamiczone fields', () => {
|
|
|
332
333
|
);
|
|
333
334
|
const { result } = runMiddleware();
|
|
334
335
|
await expect(result).rejects.toThrow(errors.ValidationError);
|
|
335
|
-
await expect(result).rejects.toThrow('Blocks
|
|
336
|
+
await expect(result).rejects.toThrow('Blocks (item 1) › Photo');
|
|
336
337
|
});
|
|
337
338
|
|
|
338
339
|
it('reports the correct block index in a multi-block dynamic zone', async () => {
|
|
@@ -349,7 +350,7 @@ describe('middleware — dynamiczone fields', () => {
|
|
|
349
350
|
}
|
|
350
351
|
);
|
|
351
352
|
const { result } = runMiddleware();
|
|
352
|
-
await expect(result).rejects.toThrow('Blocks
|
|
353
|
+
await expect(result).rejects.toThrow('Blocks (item 2) › Photo');
|
|
353
354
|
});
|
|
354
355
|
|
|
355
356
|
it('skips blocks whose component type has no required media', async () => {
|
|
@@ -386,7 +387,7 @@ describe('middleware — dynamiczone fields', () => {
|
|
|
386
387
|
}
|
|
387
388
|
);
|
|
388
389
|
const { result } = runMiddleware();
|
|
389
|
-
await expect(result).rejects.toThrow('Blocks
|
|
390
|
+
await expect(result).rejects.toThrow('Blocks (item 2) › Photo');
|
|
390
391
|
});
|
|
391
392
|
|
|
392
393
|
it('builds populate that merges media fields from all component types', async () => {
|
package/src/server/index.ts
CHANGED
|
@@ -1,26 +1,22 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
1
|
import type { Core, UID } from '@strapi/strapi';
|
|
3
2
|
|
|
4
3
|
type ValidationErrorCtor = new (message: string) => Error;
|
|
5
4
|
|
|
6
5
|
function resolveValidationError(): ValidationErrorCtor {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
6
|
+
try {
|
|
7
|
+
// @strapi/utils is always present in the host Strapi project; require()
|
|
8
|
+
// loads the CJS build, which is the same instance Strapi's error
|
|
9
|
+
// middleware uses for instanceof checks → errors become 400, not 500.
|
|
10
|
+
return (require('@strapi/utils') as any).errors.ValidationError;
|
|
11
|
+
} catch {
|
|
12
|
+
return class extends Error {
|
|
13
|
+
constructor(message: string) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.name = 'ValidationError';
|
|
16
|
+
(this as any).status = 400;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
16
19
|
}
|
|
17
|
-
return class extends Error {
|
|
18
|
-
constructor(message: string) {
|
|
19
|
-
super(message);
|
|
20
|
-
this.name = 'ValidationError';
|
|
21
|
-
(this as any).status = 400;
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
20
|
}
|
|
25
21
|
|
|
26
22
|
/**
|
|
@@ -139,9 +135,28 @@ const register = ({ strapi }: { strapi: Core.Strapi }) => {
|
|
|
139
135
|
|
|
140
136
|
if (missing.length > 0) {
|
|
141
137
|
const labels = missing
|
|
142
|
-
.map((
|
|
138
|
+
.map((rawPath) =>
|
|
139
|
+
rawPath
|
|
140
|
+
.split(' > ')
|
|
141
|
+
.map((seg) => {
|
|
142
|
+
// "blocks[2]" → "Blocks (item 2)"
|
|
143
|
+
const indexed = seg.match(/^(.+?)\[(\d+)\]$/);
|
|
144
|
+
if (indexed) {
|
|
145
|
+
const name = indexed[1].charAt(0).toUpperCase() +
|
|
146
|
+
indexed[1].slice(1).replace(/([A-Z])/g, ' $1').replace(/_/g, ' ');
|
|
147
|
+
return `${name} (item ${indexed[2]})`;
|
|
148
|
+
}
|
|
149
|
+
return seg.charAt(0).toUpperCase() +
|
|
150
|
+
seg.slice(1).replace(/([A-Z])/g, ' $1').replace(/_/g, ' ');
|
|
151
|
+
})
|
|
152
|
+
.join(' › ')
|
|
153
|
+
)
|
|
143
154
|
.join(', ');
|
|
144
|
-
|
|
155
|
+
|
|
156
|
+
const verb = missing.length === 1 ? 'field is' : 'fields are';
|
|
157
|
+
throw new ValidationError(
|
|
158
|
+
`Cannot publish: required media ${verb} missing — ${labels}`
|
|
159
|
+
);
|
|
145
160
|
}
|
|
146
161
|
|
|
147
162
|
return next();
|