@abinnovision/payloadcms-mcpx 1.0.0-beta.3
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/LICENSE +201 -0
- package/README.md +258 -0
- package/dist/api-keys/collection.mjs +58 -0
- package/dist/api-keys/fields.mjs +88 -0
- package/dist/api-keys/key.mjs +10 -0
- package/dist/auth/resolve.mjs +62 -0
- package/dist/capabilities.mjs +30 -0
- package/dist/endpoint/handler.mjs +84 -0
- package/dist/endpoint/result.mjs +59 -0
- package/dist/endpoint/server.mjs +52 -0
- package/dist/index.d.mts +5 -0
- package/dist/index.mjs +4 -0
- package/dist/options.mjs +107 -0
- package/dist/plugin.d.mts +9 -0
- package/dist/plugin.mjs +42 -0
- package/dist/schema/describe.mjs +82 -0
- package/dist/schema/lexical.mjs +25 -0
- package/dist/schema/pointer.mjs +83 -0
- package/dist/schema/shape.mjs +147 -0
- package/dist/schema/walk.mjs +109 -0
- package/dist/tools/create-document.mjs +67 -0
- package/dist/tools/describe-schema.mjs +44 -0
- package/dist/tools/find-documents.mjs +54 -0
- package/dist/tools/get-document.mjs +54 -0
- package/dist/tools/index.mjs +23 -0
- package/dist/tools/list-capabilities.mjs +49 -0
- package/dist/tools/names.mjs +14 -0
- package/dist/tools/patch-document.mjs +113 -0
- package/dist/tools/shared.mjs +65 -0
- package/dist/tools/validate-document.mjs +48 -0
- package/dist/types.d.mts +113 -0
- package/dist/types.mjs +7 -0
- package/dist/version.mjs +6 -0
- package/dist/write/draft-guard.d.mts +10 -0
- package/dist/write/draft-guard.mjs +70 -0
- package/dist/write/patch.mjs +220 -0
- package/dist/write/publish-blockers.d.mts +13 -0
- package/dist/write/publish-blockers.mjs +72 -0
- package/dist/write/transaction.mjs +19 -0
- package/package.json +89 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { beforeChangeTraverseFields, beforeValidateTraverseFields } from "payload";
|
|
2
|
+
//#region src/write/publish-blockers.ts
|
|
3
|
+
/**
|
|
4
|
+
* Runs Payload's own field validation over a draft without saving anything.
|
|
5
|
+
*
|
|
6
|
+
* Draft saves skip validation unless `versions.drafts.validate` is set, so an
|
|
7
|
+
* agent building a document incrementally gets no signal until a human presses
|
|
8
|
+
* Publish. This is the same traversal a real save runs, exported from
|
|
9
|
+
* `payload`, called with `skipValidation: false` so it collects into `errors`
|
|
10
|
+
* instead of throwing. The `beforeValidate` pass runs first because some field
|
|
11
|
+
* hooks (Lexical's) prepare state in `context` that their `beforeChange`
|
|
12
|
+
* counterpart depends on.
|
|
13
|
+
*
|
|
14
|
+
* Nothing is written: `data` is a copy, the context is a scratch copy and the
|
|
15
|
+
* locale merge actions are discarded. `overrideAccess` is true because the
|
|
16
|
+
* question is "could this be published", not "may this client write it".
|
|
17
|
+
*
|
|
18
|
+
* Limits: only the locale the doc was read in is checked, and field-level
|
|
19
|
+
* `beforeChange` hooks run again, which is safe only for pure ones.
|
|
20
|
+
*/ const collectPublishBlockers = async (req, target) => {
|
|
21
|
+
const { collection, doc } = target;
|
|
22
|
+
const id = doc["id"];
|
|
23
|
+
const errors = [];
|
|
24
|
+
const data = {
|
|
25
|
+
...structuredClone(doc),
|
|
26
|
+
_status: "published"
|
|
27
|
+
};
|
|
28
|
+
const shared = {
|
|
29
|
+
collection,
|
|
30
|
+
context: { ...req.context },
|
|
31
|
+
data,
|
|
32
|
+
doc,
|
|
33
|
+
global: null,
|
|
34
|
+
operation: "update",
|
|
35
|
+
overrideAccess: true,
|
|
36
|
+
parentIndexPath: "",
|
|
37
|
+
parentIsLocalized: false,
|
|
38
|
+
parentPath: "",
|
|
39
|
+
parentSchemaPath: "",
|
|
40
|
+
req,
|
|
41
|
+
siblingDoc: doc,
|
|
42
|
+
...id === void 0 ? {} : { id }
|
|
43
|
+
};
|
|
44
|
+
try {
|
|
45
|
+
await beforeValidateTraverseFields({
|
|
46
|
+
...shared,
|
|
47
|
+
fields: collection.fields,
|
|
48
|
+
siblingData: data
|
|
49
|
+
});
|
|
50
|
+
await beforeChangeTraverseFields({
|
|
51
|
+
...shared,
|
|
52
|
+
docWithLocales: doc,
|
|
53
|
+
errors,
|
|
54
|
+
fieldLabelPath: "",
|
|
55
|
+
fields: collection.fields,
|
|
56
|
+
mergeLocaleActions: [],
|
|
57
|
+
siblingData: data,
|
|
58
|
+
siblingDocWithLocales: doc,
|
|
59
|
+
skipValidation: false
|
|
60
|
+
});
|
|
61
|
+
} catch (error) {
|
|
62
|
+
req.payload.logger.warn(`[payloadcms-mcpx] Could not validate the ${collection.slug} draft: ${error instanceof Error ? error.message : "unknown error"}`);
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
return errors.map((error) => ({
|
|
66
|
+
message: error.message,
|
|
67
|
+
path: error.path,
|
|
68
|
+
...typeof error.label === "string" ? { field: error.label } : {}
|
|
69
|
+
}));
|
|
70
|
+
};
|
|
71
|
+
//#endregion
|
|
72
|
+
export { collectPublishBlockers };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { commitTransaction, initTransaction, killTransaction } from "payload";
|
|
2
|
+
//#region src/write/transaction.ts
|
|
3
|
+
/**
|
|
4
|
+
* Runs `fn` inside one database transaction on `req`, so a read followed by a
|
|
5
|
+
* write cannot interleave with another writer. Adapters without transaction
|
|
6
|
+
* support, or a request that already owns one, run `fn` as is.
|
|
7
|
+
*/ const withTransaction = async (req, fn) => {
|
|
8
|
+
if (!await initTransaction(req)) return await fn();
|
|
9
|
+
try {
|
|
10
|
+
const result = await fn();
|
|
11
|
+
await commitTransaction(req);
|
|
12
|
+
return result;
|
|
13
|
+
} catch (error) {
|
|
14
|
+
await killTransaction(req);
|
|
15
|
+
throw error;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
//#endregion
|
|
19
|
+
export { withTransaction };
|
package/package.json
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/package.json",
|
|
3
|
+
"name": "@abinnovision/payloadcms-mcpx",
|
|
4
|
+
"version": "1.0.0-beta.3",
|
|
5
|
+
"description": "Payload CMS plugin exposing a fixed, schema-aware MCP tool surface with draft-only writes and per-API-key capabilities.",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"payload",
|
|
8
|
+
"payloadcms",
|
|
9
|
+
"plugin",
|
|
10
|
+
"mcp",
|
|
11
|
+
"model-context-protocol"
|
|
12
|
+
],
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/abinnovision/payloadcms-commons.git",
|
|
16
|
+
"directory": "packages/mcpx"
|
|
17
|
+
},
|
|
18
|
+
"license": "Apache-2.0",
|
|
19
|
+
"author": {
|
|
20
|
+
"name": "abi group GmbH",
|
|
21
|
+
"email": "info@abigroup.io",
|
|
22
|
+
"url": "https://abigroup.io"
|
|
23
|
+
},
|
|
24
|
+
"type": "module",
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"types": "./dist/index.d.mts",
|
|
28
|
+
"default": "./dist/index.mjs"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist",
|
|
33
|
+
"LICENSE",
|
|
34
|
+
"README.md"
|
|
35
|
+
],
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsdown",
|
|
38
|
+
"format:check": "prettier --check 'src/**/*.ts' 'test/**/*.ts' '*.{json{,5},md,y{,a}ml}'",
|
|
39
|
+
"format:fix": "prettier --write 'src/**/*.ts' 'test/**/*.ts' '*.{json{,5},md,y{,a}ml}'",
|
|
40
|
+
"lint:check": "eslint 'src/**/*.ts' 'test/**/*.ts'",
|
|
41
|
+
"lint:fix": "eslint 'src/**/*.ts' 'test/**/*.ts' --fix",
|
|
42
|
+
"test-integration": "vitest --run --config test/integration/vitest.config.mts",
|
|
43
|
+
"test-unit": "vitest --run --coverage --config vitest.config.mts",
|
|
44
|
+
"test-unit:watch": "vitest --config vitest.config.mts",
|
|
45
|
+
"typecheck": "tsc --noEmit"
|
|
46
|
+
},
|
|
47
|
+
"lint-staged": {
|
|
48
|
+
"{src,test}/**/*.ts": [
|
|
49
|
+
"eslint --fix",
|
|
50
|
+
"prettier --write"
|
|
51
|
+
],
|
|
52
|
+
"*.{json{,5},md,y{,a}ml}": "prettier --write"
|
|
53
|
+
},
|
|
54
|
+
"prettier": "@abinnovision/prettier-config",
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
57
|
+
"rfc6902": "^5.3.0",
|
|
58
|
+
"zod": "^4.4.3"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@abinnovision/eslint-config-base": "^3.4.2",
|
|
62
|
+
"@abinnovision/prettier-config": "^2.2.0",
|
|
63
|
+
"@arethetypeswrong/core": "^0.18.5",
|
|
64
|
+
"@payloadcms/db-sqlite": "3.88.0",
|
|
65
|
+
"@payloadcms/richtext-lexical": "3.88.0",
|
|
66
|
+
"@swc/core": "^1.16.1",
|
|
67
|
+
"@types/node": "^26.2.0",
|
|
68
|
+
"@types/react": "^19.2.18",
|
|
69
|
+
"@vitest/coverage-v8": "^4.1.10",
|
|
70
|
+
"eslint": "^10.7.0",
|
|
71
|
+
"payload": "3.88.0",
|
|
72
|
+
"prettier": "^3.9.5",
|
|
73
|
+
"publint": "^0.3.24",
|
|
74
|
+
"react": "^19.2.8",
|
|
75
|
+
"react-dom": "^19.2.8",
|
|
76
|
+
"tsdown": "^0.22.14",
|
|
77
|
+
"typescript": "^6.0.3",
|
|
78
|
+
"unplugin-swc": "^1.5.11",
|
|
79
|
+
"vitest": "^4.1.10"
|
|
80
|
+
},
|
|
81
|
+
"peerDependencies": {
|
|
82
|
+
"payload": ">=3.88.0 <4"
|
|
83
|
+
},
|
|
84
|
+
"publishConfig": {
|
|
85
|
+
"ghpr": true,
|
|
86
|
+
"npm": true,
|
|
87
|
+
"npmAccess": "public"
|
|
88
|
+
}
|
|
89
|
+
}
|