@abinnovision/payloadcms-mcpx 2.0.0-beta.12 → 2.0.0-beta.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/upload/file.mjs +22 -3
- package/package.json +1 -1
package/dist/upload/file.mjs
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { errorResult, jsonResult } from "../result.mjs";
|
|
2
|
+
import { SchemaError } from "../schema/errors.mjs";
|
|
3
|
+
import { resolveDataPointer } from "../schema/pointer.mjs";
|
|
4
|
+
import "../schema/index.mjs";
|
|
2
5
|
import { issueGrant, uploadKvSlug } from "./grant.mjs";
|
|
3
6
|
import { collectPublishBlockers } from "../write/publish-blockers.mjs";
|
|
4
7
|
import { APIError } from "payload";
|
|
@@ -77,22 +80,38 @@ const sharesPublishedFile = async (req, entity, id) => {
|
|
|
77
80
|
})]);
|
|
78
81
|
return latest?.["_status"] === "draft" && published?.["_status"] === "published" && latest["filename"] === published["filename"];
|
|
79
82
|
};
|
|
83
|
+
const isClientWritable = (scope, target, path) => {
|
|
84
|
+
try {
|
|
85
|
+
const resolution = resolveDataPointer(scope.req.payload.config, {
|
|
86
|
+
ref: target.entity,
|
|
87
|
+
doc: target.data,
|
|
88
|
+
pointer: path
|
|
89
|
+
});
|
|
90
|
+
return resolution.readOnly !== true && resolution.descriptor?.readOnly !== true;
|
|
91
|
+
} catch (error) {
|
|
92
|
+
if (error instanceof SchemaError) return false;
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
80
96
|
/**
|
|
81
97
|
* Refuses a file write Payload would turn into data loss: a replace that
|
|
82
98
|
* deletes the published file, or a write that fails validation after the old
|
|
83
99
|
* file is gone. Payload validates only after it moves files, so the merged
|
|
84
|
-
* data is validated here first wherever Payload will validate it
|
|
100
|
+
* data is validated here first wherever Payload will validate it, keeping only
|
|
101
|
+
* failures the client can fix. Once the bytes are attached, Payload validates
|
|
102
|
+
* with every hook and the file.
|
|
85
103
|
*/ const fileWriteRefusal = async (scope, target) => {
|
|
86
104
|
const { entity, id } = target;
|
|
87
105
|
if (id !== void 0 && await sharesPublishedFile(scope.req, entity, id)) return errorResult("The file was not replaced: the latest draft still uses the published file, which the replace would delete. Publish or discard the draft first.");
|
|
88
|
-
if (hasDraftsEnabled(entity.config) && !hasDraftValidationEnabled(entity.config)) return;
|
|
89
|
-
const { blockers } = await collectPublishBlockers(scope.req, {
|
|
106
|
+
if (uploadedFile(scope.req) !== void 0 || hasDraftsEnabled(entity.config) && !hasDraftValidationEnabled(entity.config)) return;
|
|
107
|
+
const { blockers: found } = await collectPublishBlockers(scope.req, {
|
|
90
108
|
doc: {
|
|
91
109
|
...target.data,
|
|
92
110
|
...id === void 0 ? {} : { id }
|
|
93
111
|
},
|
|
94
112
|
entity
|
|
95
113
|
});
|
|
114
|
+
const blockers = found.filter((blocker) => isClientWritable(scope, target, blocker.path));
|
|
96
115
|
return blockers.length === 0 ? void 0 : errorResult("Nothing was written: the document fails validation.", { validationErrors: blockers });
|
|
97
116
|
};
|
|
98
117
|
const handoffUrl = (req, path) => {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "@abinnovision/payloadcms-mcpx",
|
|
4
|
-
"version": "2.0.0-beta.
|
|
4
|
+
"version": "2.0.0-beta.13",
|
|
5
5
|
"description": "Payload CMS plugin exposing a fixed, schema-aware MCP tool surface with draft-only writes and per-API-key capabilities.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"payload",
|