payload-mcp-toolkit 0.8.0 → 0.9.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.
- package/README.md +100 -237
- package/dist/api-keys.js +16 -0
- package/dist/api-keys.js.map +1 -1
- package/dist/auth-strategy.js +49 -49
- package/dist/auth-strategy.js.map +1 -1
- package/dist/components/AgentConnectPill.d.ts +3 -0
- package/dist/components/AgentConnectPill.js +121 -0
- package/dist/components/AgentConnectPill.js.map +1 -0
- package/dist/components/CollectionScopesMatrix.js.map +1 -1
- package/dist/components/ConsentPermissions.d.ts +10 -0
- package/dist/components/ConsentPermissions.js +165 -0
- package/dist/components/ConsentPermissions.js.map +1 -0
- package/dist/components/GlobalScopesMatrix.js.map +1 -1
- package/dist/components/OAuthView.d.ts +4 -0
- package/dist/components/OAuthView.js +269 -0
- package/dist/components/OAuthView.js.map +1 -0
- package/dist/components/ScopesTable.d.ts +28 -0
- package/dist/components/ScopesTable.js +165 -130
- package/dist/components/ScopesTable.js.map +1 -1
- package/dist/components/agentInstructions.d.ts +2 -0
- package/dist/components/agentInstructions.js +34 -0
- package/dist/components/agentInstructions.js.map +1 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.js +2 -0
- package/dist/components/index.js.map +1 -1
- package/dist/components/oauth.css +111 -0
- package/dist/conflict-detection.js +13 -13
- package/dist/conflict-detection.js.map +1 -1
- package/dist/draft-workflow.js +26 -26
- package/dist/draft-workflow.js.map +1 -1
- package/dist/endpoint.d.ts +5 -0
- package/dist/endpoint.js +21 -13
- package/dist/endpoint.js.map +1 -1
- package/dist/hash.js +15 -15
- package/dist/hash.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +67 -3
- package/dist/index.js.map +1 -1
- package/dist/introspection.js +47 -47
- package/dist/introspection.js.map +1 -1
- package/dist/oauth-permissions.d.ts +52 -0
- package/dist/oauth-permissions.js +100 -0
- package/dist/oauth-permissions.js.map +1 -0
- package/dist/oauth-store.d.ts +19 -0
- package/dist/oauth-store.js +122 -0
- package/dist/oauth-store.js.map +1 -0
- package/dist/oauth.d.ts +19 -0
- package/dist/oauth.js +523 -0
- package/dist/oauth.js.map +1 -0
- package/dist/prompts.js +5 -5
- package/dist/prompts.js.map +1 -1
- package/dist/registry.js +7 -1
- package/dist/registry.js.map +1 -1
- package/dist/resources.js +10 -10
- package/dist/resources.js.map +1 -1
- package/dist/scope/audit-log.js +9 -9
- package/dist/scope/audit-log.js.map +1 -1
- package/dist/scope/policy.js +7 -7
- package/dist/scope/policy.js.map +1 -1
- package/dist/tools/_helpers.d.ts +10 -0
- package/dist/tools/_helpers.js +53 -41
- package/dist/tools/_helpers.js.map +1 -1
- package/dist/tools/_layout-helpers.js +33 -33
- package/dist/tools/_layout-helpers.js.map +1 -1
- package/dist/tools/create-document.js +20 -19
- package/dist/tools/create-document.js.map +1 -1
- package/dist/tools/delete-document.js +10 -9
- package/dist/tools/delete-document.js.map +1 -1
- package/dist/tools/find-document.js +18 -15
- package/dist/tools/find-document.js.map +1 -1
- package/dist/tools/find-global.js +13 -13
- package/dist/tools/find-global.js.map +1 -1
- package/dist/tools/global-versions.js +8 -7
- package/dist/tools/global-versions.js.map +1 -1
- package/dist/tools/patch-global-layout.js +9 -9
- package/dist/tools/patch-global-layout.js.map +1 -1
- package/dist/tools/patch-layout.js +15 -14
- package/dist/tools/patch-layout.js.map +1 -1
- package/dist/tools/publish-draft.js +2 -1
- package/dist/tools/publish-draft.js.map +1 -1
- package/dist/tools/publish-global-draft.js +4 -4
- package/dist/tools/publish-global-draft.js.map +1 -1
- package/dist/tools/resolve-reference.js.map +1 -1
- package/dist/tools/safe-delete.js +14 -14
- package/dist/tools/safe-delete.js.map +1 -1
- package/dist/tools/schedule-publish.js +21 -20
- package/dist/tools/schedule-publish.js.map +1 -1
- package/dist/tools/search-content.js +12 -12
- package/dist/tools/search-content.js.map +1 -1
- package/dist/tools/update-document.js +6 -5
- package/dist/tools/update-document.js.map +1 -1
- package/dist/tools/update-global.js +9 -9
- package/dist/tools/update-global.js.map +1 -1
- package/dist/tools/upload-media.js +2 -1
- package/dist/tools/upload-media.js.map +1 -1
- package/dist/tools/versions.js +10 -8
- package/dist/tools/versions.js.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.js.map +1 -1
- package/docs/oauth.md +96 -0
- package/package.json +7 -2
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import React, { useEffect, useState } from 'react';
|
|
4
|
+
import { Banner, Button, Gutter } from '@payloadcms/ui';
|
|
5
|
+
import { agentInstructions } from './agentInstructions';
|
|
6
|
+
import { ConsentPermissions } from './ConsentPermissions';
|
|
7
|
+
import './oauth.css';
|
|
8
|
+
function CopyButton({ text, label }) {
|
|
9
|
+
const [status, setStatus] = useState('');
|
|
10
|
+
async function copy() {
|
|
11
|
+
setStatus('');
|
|
12
|
+
try {
|
|
13
|
+
await navigator.clipboard.writeText(text);
|
|
14
|
+
setStatus('Copied.');
|
|
15
|
+
} catch {
|
|
16
|
+
setStatus('Copy failed. Select the text and copy it.');
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
20
|
+
className: "mcp-oauth__copy",
|
|
21
|
+
children: [
|
|
22
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
23
|
+
type: "button",
|
|
24
|
+
buttonStyle: "secondary",
|
|
25
|
+
size: "small",
|
|
26
|
+
margin: false,
|
|
27
|
+
onClick: copy,
|
|
28
|
+
children: label
|
|
29
|
+
}),
|
|
30
|
+
/*#__PURE__*/ _jsx("span", {
|
|
31
|
+
role: "status",
|
|
32
|
+
children: status
|
|
33
|
+
})
|
|
34
|
+
]
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
export function OAuthView({ mode }) {
|
|
38
|
+
const [data, setData] = useState(null);
|
|
39
|
+
const [error, setError] = useState('');
|
|
40
|
+
const [nothingPicked, setNothingPicked] = useState(false);
|
|
41
|
+
const endpoint = `/api/mcp/oauth/${mode}`;
|
|
42
|
+
useEffect(()=>{
|
|
43
|
+
const controller = new AbortController();
|
|
44
|
+
async function load() {
|
|
45
|
+
try {
|
|
46
|
+
const response = await fetch(`${endpoint}${window.location.search}`, {
|
|
47
|
+
headers: {
|
|
48
|
+
Accept: 'application/json'
|
|
49
|
+
},
|
|
50
|
+
credentials: 'same-origin',
|
|
51
|
+
cache: 'no-store',
|
|
52
|
+
signal: controller.signal
|
|
53
|
+
});
|
|
54
|
+
if (response.redirected) {
|
|
55
|
+
const destination = new URL(response.url);
|
|
56
|
+
if (destination.origin === window.location.origin) window.location.assign(destination.href);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (!response.ok) {
|
|
60
|
+
setError(response.status === 403 ? 'Your account cannot authorize this connection.' : 'This request could not be loaded. Start the connection again from your AI app.');
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
setData(await response.json());
|
|
64
|
+
} catch {
|
|
65
|
+
if (!controller.signal.aborted) setError('The connection could not be loaded. Check your connection and reload this page.');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
void load();
|
|
69
|
+
return ()=>controller.abort();
|
|
70
|
+
}, [
|
|
71
|
+
endpoint
|
|
72
|
+
]);
|
|
73
|
+
const approval = data && 'account' in data ? data : null;
|
|
74
|
+
const connections = data && 'grants' in data ? data : null;
|
|
75
|
+
const instructions = connections ? agentInstructions(connections.resource, connections.access) : '';
|
|
76
|
+
return /*#__PURE__*/ _jsx(Gutter, {
|
|
77
|
+
children: /*#__PURE__*/ _jsxs("main", {
|
|
78
|
+
className: "mcp-oauth",
|
|
79
|
+
children: [
|
|
80
|
+
/*#__PURE__*/ _jsx("h1", {
|
|
81
|
+
children: mode === 'authorize' ? 'Connect your account' : 'AI connections'
|
|
82
|
+
}),
|
|
83
|
+
error ? /*#__PURE__*/ _jsx(Banner, {
|
|
84
|
+
type: "error",
|
|
85
|
+
children: /*#__PURE__*/ _jsx("span", {
|
|
86
|
+
role: "alert",
|
|
87
|
+
children: error
|
|
88
|
+
})
|
|
89
|
+
}) : !data ? /*#__PURE__*/ _jsx("p", {
|
|
90
|
+
role: "status",
|
|
91
|
+
children: "Loading connection…"
|
|
92
|
+
}) : null,
|
|
93
|
+
approval && /*#__PURE__*/ _jsxs(_Fragment, {
|
|
94
|
+
children: [
|
|
95
|
+
/*#__PURE__*/ _jsxs("p", {
|
|
96
|
+
children: [
|
|
97
|
+
/*#__PURE__*/ _jsx("strong", {
|
|
98
|
+
children: approval.clientName
|
|
99
|
+
}),
|
|
100
|
+
" is requesting access to your website account."
|
|
101
|
+
]
|
|
102
|
+
}),
|
|
103
|
+
/*#__PURE__*/ _jsxs("dl", {
|
|
104
|
+
className: "mcp-oauth__details",
|
|
105
|
+
children: [
|
|
106
|
+
/*#__PURE__*/ _jsx("dt", {
|
|
107
|
+
children: "Signed in as"
|
|
108
|
+
}),
|
|
109
|
+
/*#__PURE__*/ _jsx("dd", {
|
|
110
|
+
children: approval.account
|
|
111
|
+
}),
|
|
112
|
+
/*#__PURE__*/ _jsx("dt", {
|
|
113
|
+
children: "Permissions"
|
|
114
|
+
}),
|
|
115
|
+
/*#__PURE__*/ _jsx("dd", {
|
|
116
|
+
children: "What you choose below. Your website permissions still apply. Deleting content and changing global settings are not allowed."
|
|
117
|
+
}),
|
|
118
|
+
/*#__PURE__*/ _jsx("dt", {
|
|
119
|
+
children: "Duration"
|
|
120
|
+
}),
|
|
121
|
+
/*#__PURE__*/ _jsx("dd", {
|
|
122
|
+
children: "Up to 30 days. You can disconnect at any time."
|
|
123
|
+
})
|
|
124
|
+
]
|
|
125
|
+
}),
|
|
126
|
+
/*#__PURE__*/ _jsxs("form", {
|
|
127
|
+
action: endpoint,
|
|
128
|
+
method: "post",
|
|
129
|
+
onKeyDown: (e)=>{
|
|
130
|
+
if (e.key === 'Enter' && e.target.matches('input[type=checkbox]')) e.preventDefault();
|
|
131
|
+
},
|
|
132
|
+
children: [
|
|
133
|
+
/*#__PURE__*/ _jsx("input", {
|
|
134
|
+
type: "hidden",
|
|
135
|
+
name: "consent",
|
|
136
|
+
value: approval.consent
|
|
137
|
+
}),
|
|
138
|
+
/*#__PURE__*/ _jsx(ConsentPermissions, {
|
|
139
|
+
catalog: approval.catalog,
|
|
140
|
+
max: approval.scope.split(' ').includes('mcp:write') ? 'editor' : 'read-only',
|
|
141
|
+
onEmptyChange: setNothingPicked
|
|
142
|
+
}),
|
|
143
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
144
|
+
className: "mcp-oauth__actions",
|
|
145
|
+
children: [
|
|
146
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
147
|
+
type: "submit",
|
|
148
|
+
margin: false,
|
|
149
|
+
disabled: nothingPicked,
|
|
150
|
+
extraButtonProps: {
|
|
151
|
+
name: 'decision',
|
|
152
|
+
value: 'allow'
|
|
153
|
+
},
|
|
154
|
+
children: "Allow access"
|
|
155
|
+
}),
|
|
156
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
157
|
+
type: "submit",
|
|
158
|
+
buttonStyle: "secondary",
|
|
159
|
+
margin: false,
|
|
160
|
+
extraButtonProps: {
|
|
161
|
+
name: 'decision',
|
|
162
|
+
value: 'deny'
|
|
163
|
+
},
|
|
164
|
+
children: "Cancel"
|
|
165
|
+
})
|
|
166
|
+
]
|
|
167
|
+
})
|
|
168
|
+
]
|
|
169
|
+
})
|
|
170
|
+
]
|
|
171
|
+
}),
|
|
172
|
+
connections && /*#__PURE__*/ _jsxs(_Fragment, {
|
|
173
|
+
children: [
|
|
174
|
+
connections.eligible ? /*#__PURE__*/ _jsxs(_Fragment, {
|
|
175
|
+
children: [
|
|
176
|
+
/*#__PURE__*/ _jsx("p", {
|
|
177
|
+
children: "Add this URL as a custom connector in your AI app. Then sign in and approve access."
|
|
178
|
+
}),
|
|
179
|
+
/*#__PURE__*/ _jsxs("ul", {
|
|
180
|
+
children: [
|
|
181
|
+
/*#__PURE__*/ _jsxs("li", {
|
|
182
|
+
children: [
|
|
183
|
+
/*#__PURE__*/ _jsx("strong", {
|
|
184
|
+
children: "Claude:"
|
|
185
|
+
}),
|
|
186
|
+
" Settings → Connectors → Add custom connector."
|
|
187
|
+
]
|
|
188
|
+
}),
|
|
189
|
+
/*#__PURE__*/ _jsxs("li", {
|
|
190
|
+
children: [
|
|
191
|
+
/*#__PURE__*/ _jsx("strong", {
|
|
192
|
+
children: "ChatGPT (web):"
|
|
193
|
+
}),
|
|
194
|
+
" turn on Developer mode in Settings, then create an app with this URL and OAuth sign-in."
|
|
195
|
+
]
|
|
196
|
+
})
|
|
197
|
+
]
|
|
198
|
+
}),
|
|
199
|
+
/*#__PURE__*/ _jsx("code", {
|
|
200
|
+
className: "mcp-oauth__url",
|
|
201
|
+
children: connections.resource
|
|
202
|
+
}),
|
|
203
|
+
/*#__PURE__*/ _jsx(CopyButton, {
|
|
204
|
+
text: connections.resource,
|
|
205
|
+
label: "Copy URL"
|
|
206
|
+
}),
|
|
207
|
+
/*#__PURE__*/ _jsx("h2", {
|
|
208
|
+
children: "Agent instructions"
|
|
209
|
+
}),
|
|
210
|
+
/*#__PURE__*/ _jsx("p", {
|
|
211
|
+
children: "Paste these into your AI app, for example as project instructions. They tell the assistant how to connect and how to work with your content."
|
|
212
|
+
}),
|
|
213
|
+
/*#__PURE__*/ _jsx("pre", {
|
|
214
|
+
className: "mcp-oauth__instructions",
|
|
215
|
+
children: instructions
|
|
216
|
+
}),
|
|
217
|
+
/*#__PURE__*/ _jsx(CopyButton, {
|
|
218
|
+
text: instructions,
|
|
219
|
+
label: "Copy instructions"
|
|
220
|
+
})
|
|
221
|
+
]
|
|
222
|
+
}) : /*#__PURE__*/ _jsx("p", {
|
|
223
|
+
children: "Your account cannot connect AI apps. Ask a site administrator for access."
|
|
224
|
+
}),
|
|
225
|
+
/*#__PURE__*/ _jsx("h2", {
|
|
226
|
+
children: "Connected apps"
|
|
227
|
+
}),
|
|
228
|
+
connections.grants.length ? connections.grants.map((grant)=>/*#__PURE__*/ _jsxs("div", {
|
|
229
|
+
className: "mcp-oauth__connection",
|
|
230
|
+
children: [
|
|
231
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
232
|
+
children: [
|
|
233
|
+
/*#__PURE__*/ _jsx("strong", {
|
|
234
|
+
children: grant.clientName
|
|
235
|
+
}),
|
|
236
|
+
/*#__PURE__*/ _jsx("p", {
|
|
237
|
+
children: grant.summary
|
|
238
|
+
})
|
|
239
|
+
]
|
|
240
|
+
}),
|
|
241
|
+
/*#__PURE__*/ _jsxs("form", {
|
|
242
|
+
action: endpoint,
|
|
243
|
+
method: "post",
|
|
244
|
+
children: [
|
|
245
|
+
/*#__PURE__*/ _jsx("input", {
|
|
246
|
+
type: "hidden",
|
|
247
|
+
name: "consent",
|
|
248
|
+
value: grant.consent
|
|
249
|
+
}),
|
|
250
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
251
|
+
type: "submit",
|
|
252
|
+
buttonStyle: "secondary",
|
|
253
|
+
margin: false,
|
|
254
|
+
children: "Disconnect"
|
|
255
|
+
})
|
|
256
|
+
]
|
|
257
|
+
})
|
|
258
|
+
]
|
|
259
|
+
}, grant.consent)) : /*#__PURE__*/ _jsx("p", {
|
|
260
|
+
children: "No active connections."
|
|
261
|
+
})
|
|
262
|
+
]
|
|
263
|
+
})
|
|
264
|
+
]
|
|
265
|
+
})
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
//# sourceMappingURL=OAuthView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/OAuthView.tsx"],"sourcesContent":["'use client'\n\nimport React, { useEffect, useState } from 'react'\nimport { Banner, Button, Gutter } from '@payloadcms/ui'\nimport type { Catalog } from '../oauth-permissions'\nimport { agentInstructions } from './agentInstructions'\nimport { ConsentPermissions } from './ConsentPermissions'\nimport './oauth.css'\n\ntype Consent = { consent: string; clientName: string; account: string; scope: string; catalog: Catalog }\ntype Grant = { consent: string; clientName: string; scope: string; summary: string }\ntype Connections = { resource: string; access: 'read-only' | 'editor'; eligible: boolean; grants: Grant[] }\n\nfunction CopyButton({ text, label }: { text: string; label: string }) {\n const [status, setStatus] = useState('')\n async function copy() {\n setStatus('')\n try {\n await navigator.clipboard.writeText(text)\n setStatus('Copied.')\n } catch {\n setStatus('Copy failed. Select the text and copy it.')\n }\n }\n return (\n <div className=\"mcp-oauth__copy\">\n <Button type=\"button\" buttonStyle=\"secondary\" size=\"small\" margin={false} onClick={copy}>{label}</Button>\n <span role=\"status\">{status}</span>\n </div>\n )\n}\n\nexport function OAuthView({ mode }: { mode: 'authorize' | 'connections' }) {\n const [data, setData] = useState<Consent | Connections | null>(null)\n const [error, setError] = useState('')\n const [nothingPicked, setNothingPicked] = useState(false)\n const endpoint = `/api/mcp/oauth/${mode}`\n\n useEffect(() => {\n const controller = new AbortController()\n async function load() {\n try {\n const response = await fetch(`${endpoint}${window.location.search}`, {\n headers: { Accept: 'application/json' }, credentials: 'same-origin', cache: 'no-store', signal: controller.signal,\n })\n if (response.redirected) {\n const destination = new URL(response.url)\n if (destination.origin === window.location.origin) window.location.assign(destination.href)\n return\n }\n if (!response.ok) {\n setError(response.status === 403 ? 'Your account cannot authorize this connection.' : 'This request could not be loaded. Start the connection again from your AI app.')\n return\n }\n setData(await response.json())\n } catch {\n if (!controller.signal.aborted) setError('The connection could not be loaded. Check your connection and reload this page.')\n }\n }\n void load()\n return () => controller.abort()\n }, [endpoint])\n\n const approval = data && 'account' in data ? data : null\n const connections = data && 'grants' in data ? data : null\n const instructions = connections ? agentInstructions(connections.resource, connections.access) : ''\n\n return (\n <Gutter>\n <main className=\"mcp-oauth\">\n <h1>{mode === 'authorize' ? 'Connect your account' : 'AI connections'}</h1>\n {error ? <Banner type=\"error\"><span role=\"alert\">{error}</span></Banner> : !data ? <p role=\"status\">Loading connection…</p> : null}\n {approval && (\n <>\n <p><strong>{approval.clientName}</strong> is requesting access to your website account.</p>\n <dl className=\"mcp-oauth__details\">\n <dt>Signed in as</dt><dd>{approval.account}</dd>\n <dt>Permissions</dt><dd>What you choose below. Your website permissions still apply. Deleting content and changing global settings are not allowed.</dd>\n <dt>Duration</dt><dd>Up to 30 days. You can disconnect at any time.</dd>\n </dl>\n {/* Enter on a checkbox would submit the form through its first button, Allow access. */}\n <form action={endpoint} method=\"post\" onKeyDown={e => {\n if (e.key === 'Enter' && (e.target as HTMLElement).matches('input[type=checkbox]')) e.preventDefault()\n }}>\n <input type=\"hidden\" name=\"consent\" value={approval.consent} />\n <ConsentPermissions\n catalog={approval.catalog}\n max={approval.scope.split(' ').includes('mcp:write') ? 'editor' : 'read-only'}\n onEmptyChange={setNothingPicked}\n />\n <div className=\"mcp-oauth__actions\">\n <Button type=\"submit\" margin={false} disabled={nothingPicked} extraButtonProps={{ name: 'decision', value: 'allow' }}>Allow access</Button>\n <Button type=\"submit\" buttonStyle=\"secondary\" margin={false} extraButtonProps={{ name: 'decision', value: 'deny' }}>Cancel</Button>\n </div>\n </form>\n </>\n )}\n {connections && (\n <>\n {connections.eligible ? (\n <>\n <p>Add this URL as a custom connector in your AI app. Then sign in and approve access.</p>\n <ul>\n <li><strong>Claude:</strong> Settings → Connectors → Add custom connector.</li>\n <li><strong>ChatGPT (web):</strong> turn on Developer mode in Settings, then create an app with this URL and OAuth sign-in.</li>\n </ul>\n <code className=\"mcp-oauth__url\">{connections.resource}</code>\n <CopyButton text={connections.resource} label=\"Copy URL\" />\n <h2>Agent instructions</h2>\n <p>Paste these into your AI app, for example as project instructions. They tell the assistant how to connect and how to work with your content.</p>\n <pre className=\"mcp-oauth__instructions\">{instructions}</pre>\n <CopyButton text={instructions} label=\"Copy instructions\" />\n </>\n ) : <p>Your account cannot connect AI apps. Ask a site administrator for access.</p>}\n <h2>Connected apps</h2>\n {connections.grants.length ? connections.grants.map(grant => (\n <div className=\"mcp-oauth__connection\" key={grant.consent}>\n <div><strong>{grant.clientName}</strong><p>{grant.summary}</p></div>\n <form action={endpoint} method=\"post\">\n <input type=\"hidden\" name=\"consent\" value={grant.consent} />\n <Button type=\"submit\" buttonStyle=\"secondary\" margin={false}>Disconnect</Button>\n </form>\n </div>\n )) : <p>No active connections.</p>}\n </>\n )}\n </main>\n </Gutter>\n )\n}\n"],"names":["React","useEffect","useState","Banner","Button","Gutter","agentInstructions","ConsentPermissions","CopyButton","text","label","status","setStatus","copy","navigator","clipboard","writeText","div","className","type","buttonStyle","size","margin","onClick","span","role","OAuthView","mode","data","setData","error","setError","nothingPicked","setNothingPicked","endpoint","controller","AbortController","load","response","fetch","window","location","search","headers","Accept","credentials","cache","signal","redirected","destination","URL","url","origin","assign","href","ok","json","aborted","abort","approval","connections","instructions","resource","access","main","h1","p","strong","clientName","dl","dt","dd","account","form","action","method","onKeyDown","e","key","target","matches","preventDefault","input","name","value","consent","catalog","max","scope","split","includes","onEmptyChange","disabled","extraButtonProps","eligible","ul","li","code","h2","pre","grants","length","map","grant","summary"],"mappings":"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"}
|
|
@@ -1,4 +1,29 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Reusable matrix renderer for "items × actions" scope tables.
|
|
4
|
+
*
|
|
5
|
+
* Used by both CollectionScopesMatrix (collections × 4 actions) and
|
|
6
|
+
* GlobalScopesMatrix (globals × 2 actions). The stored shape is
|
|
7
|
+
* `Array<{ slug: string; actions: string[] }>` — the parent field name
|
|
8
|
+
* (`collectionScopes` vs `globalScopes`) already encodes which axis the
|
|
9
|
+
* slugs belong to, so the row payload no longer mirrors that distinction.
|
|
10
|
+
*/
|
|
11
|
+
interface RowValue {
|
|
12
|
+
slug?: unknown;
|
|
13
|
+
actions?: unknown;
|
|
14
|
+
}
|
|
15
|
+
type MatrixValue = RowValue[];
|
|
16
|
+
export interface ScopesMatrixProps {
|
|
17
|
+
/** Rows in the stored `{ slug, actions }[]` shape. */
|
|
18
|
+
value: MatrixValue | null | undefined;
|
|
19
|
+
onChange: (rows: MatrixValue) => void;
|
|
20
|
+
/** Table id; unique on the page. */
|
|
21
|
+
id: string;
|
|
22
|
+
items: string[];
|
|
23
|
+
actions: string[];
|
|
24
|
+
actionLabels: Record<string, string>;
|
|
25
|
+
itemHeader: string;
|
|
26
|
+
}
|
|
2
27
|
export interface ScopesTableProps {
|
|
3
28
|
path: string;
|
|
4
29
|
/** Slugs to render as rows. */
|
|
@@ -16,4 +41,7 @@ export interface ScopesTableProps {
|
|
|
16
41
|
/** Copy shown when `items` is empty. */
|
|
17
42
|
emptyMessage: string;
|
|
18
43
|
}
|
|
44
|
+
/** The items × actions checkbox table without form binding. The OAuth consent screen uses it too. */
|
|
45
|
+
export declare function ScopesMatrix(props: ScopesMatrixProps): React.ReactElement;
|
|
19
46
|
export declare function ScopesTable(props: ScopesTableProps): React.ReactElement;
|
|
47
|
+
export {};
|
|
@@ -43,16 +43,30 @@ const headerCellStyle = {
|
|
|
43
43
|
borderBottom: '1px solid var(--theme-elevation-150)',
|
|
44
44
|
fontWeight: 600
|
|
45
45
|
};
|
|
46
|
+
// The matrix shows row names and column headers visually; this gives each checkbox a spoken name too.
|
|
47
|
+
const hiddenStyle = {
|
|
48
|
+
position: 'absolute',
|
|
49
|
+
width: 1,
|
|
50
|
+
height: 1,
|
|
51
|
+
margin: -1,
|
|
52
|
+
padding: 0,
|
|
53
|
+
overflow: 'hidden',
|
|
54
|
+
clip: 'rect(0 0 0 0)',
|
|
55
|
+
whiteSpace: 'nowrap',
|
|
56
|
+
border: 0
|
|
57
|
+
};
|
|
58
|
+
const hiddenLabel = (htmlFor, text)=>/*#__PURE__*/ _jsx("label", {
|
|
59
|
+
htmlFor: htmlFor,
|
|
60
|
+
style: hiddenStyle,
|
|
61
|
+
children: text
|
|
62
|
+
});
|
|
46
63
|
const labelCellStyle = {
|
|
47
64
|
textAlign: 'left',
|
|
48
65
|
padding: '0.5rem 0.75rem',
|
|
49
66
|
verticalAlign: 'middle'
|
|
50
67
|
};
|
|
51
|
-
export function
|
|
52
|
-
const { value, setValue } =
|
|
53
|
-
path: props.path,
|
|
54
|
-
hasRows: false
|
|
55
|
-
});
|
|
68
|
+
/** The items × actions checkbox table without form binding. The OAuth consent screen uses it too. */ export function ScopesMatrix(props) {
|
|
69
|
+
const { value, onChange: setValue } = props;
|
|
56
70
|
const allowedActionsSet = React.useMemo(()=>new Set(props.actions), [
|
|
57
71
|
props.actions
|
|
58
72
|
]);
|
|
@@ -110,6 +124,145 @@ export function ScopesTable(props) {
|
|
|
110
124
|
const toggleAll = (checked)=>update((m)=>{
|
|
111
125
|
for (const slug of props.items)m.set(slug, checked ? new Set(props.actions) : new Set());
|
|
112
126
|
});
|
|
127
|
+
return /*#__PURE__*/ _jsxs("table", {
|
|
128
|
+
id: props.id,
|
|
129
|
+
style: {
|
|
130
|
+
width: '100%',
|
|
131
|
+
borderCollapse: 'collapse',
|
|
132
|
+
fontSize: '0.9rem',
|
|
133
|
+
background: 'var(--theme-input-bg)',
|
|
134
|
+
border: '1px solid var(--theme-elevation-150)',
|
|
135
|
+
borderRadius: '4px',
|
|
136
|
+
overflow: 'hidden'
|
|
137
|
+
},
|
|
138
|
+
children: [
|
|
139
|
+
/*#__PURE__*/ _jsx("thead", {
|
|
140
|
+
children: /*#__PURE__*/ _jsxs("tr", {
|
|
141
|
+
children: [
|
|
142
|
+
/*#__PURE__*/ _jsx("th", {
|
|
143
|
+
style: {
|
|
144
|
+
...headerCellStyle,
|
|
145
|
+
textAlign: 'left'
|
|
146
|
+
},
|
|
147
|
+
children: /*#__PURE__*/ _jsxs("div", {
|
|
148
|
+
style: {
|
|
149
|
+
display: 'flex',
|
|
150
|
+
flexDirection: 'column',
|
|
151
|
+
gap: '0.35rem'
|
|
152
|
+
},
|
|
153
|
+
children: [
|
|
154
|
+
/*#__PURE__*/ _jsx("span", {
|
|
155
|
+
children: props.itemHeader
|
|
156
|
+
}),
|
|
157
|
+
/*#__PURE__*/ _jsx(CheckboxInput, {
|
|
158
|
+
checked: isAllFull,
|
|
159
|
+
partialChecked: isAllPartial && !isAllFull,
|
|
160
|
+
onToggle: (e)=>toggleAll(e.currentTarget.checked),
|
|
161
|
+
label: "All"
|
|
162
|
+
})
|
|
163
|
+
]
|
|
164
|
+
})
|
|
165
|
+
}),
|
|
166
|
+
props.actions.map((action)=>/*#__PURE__*/ _jsx("th", {
|
|
167
|
+
style: headerCellStyle,
|
|
168
|
+
children: /*#__PURE__*/ _jsxs("div", {
|
|
169
|
+
style: {
|
|
170
|
+
display: 'flex',
|
|
171
|
+
flexDirection: 'column',
|
|
172
|
+
alignItems: 'center',
|
|
173
|
+
gap: '0.35rem'
|
|
174
|
+
},
|
|
175
|
+
children: [
|
|
176
|
+
/*#__PURE__*/ _jsx("span", {
|
|
177
|
+
children: props.actionLabels[action] ?? action
|
|
178
|
+
}),
|
|
179
|
+
/*#__PURE__*/ _jsx(CheckboxInput, {
|
|
180
|
+
checked: isColumnFull(action),
|
|
181
|
+
id: `${props.id}-col-${action}`,
|
|
182
|
+
Label: hiddenLabel(`${props.id}-col-${action}`, `${props.actionLabels[action] ?? action}: all`),
|
|
183
|
+
partialChecked: isColumnPartial(action) && !isColumnFull(action),
|
|
184
|
+
onToggle: (e)=>toggleColumn(action, e.currentTarget.checked)
|
|
185
|
+
})
|
|
186
|
+
]
|
|
187
|
+
})
|
|
188
|
+
}, action))
|
|
189
|
+
]
|
|
190
|
+
})
|
|
191
|
+
}),
|
|
192
|
+
/*#__PURE__*/ _jsx("tbody", {
|
|
193
|
+
children: props.items.map((slug, idx)=>{
|
|
194
|
+
const niceName = toWords(slug);
|
|
195
|
+
return /*#__PURE__*/ _jsxs("tr", {
|
|
196
|
+
style: {
|
|
197
|
+
background: idx % 2 === 0 ? 'var(--theme-input-bg)' : 'var(--theme-elevation-25)'
|
|
198
|
+
},
|
|
199
|
+
children: [
|
|
200
|
+
/*#__PURE__*/ _jsx("td", {
|
|
201
|
+
style: {
|
|
202
|
+
...labelCellStyle,
|
|
203
|
+
borderTop: idx === 0 ? 'none' : '1px solid var(--theme-elevation-100)'
|
|
204
|
+
},
|
|
205
|
+
children: /*#__PURE__*/ _jsxs("div", {
|
|
206
|
+
style: {
|
|
207
|
+
display: 'flex',
|
|
208
|
+
alignItems: 'center',
|
|
209
|
+
gap: '0.6rem'
|
|
210
|
+
},
|
|
211
|
+
children: [
|
|
212
|
+
/*#__PURE__*/ _jsx(CheckboxInput, {
|
|
213
|
+
checked: isRowFull(slug),
|
|
214
|
+
id: `${props.id}-row-${idx}`,
|
|
215
|
+
Label: hiddenLabel(`${props.id}-row-${idx}`, `${niceName}: all actions`),
|
|
216
|
+
partialChecked: isRowPartial(slug) && !isRowFull(slug),
|
|
217
|
+
onToggle: (e)=>toggleRow(slug, e.currentTarget.checked)
|
|
218
|
+
}),
|
|
219
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
220
|
+
style: {
|
|
221
|
+
display: 'flex',
|
|
222
|
+
flexDirection: 'column'
|
|
223
|
+
},
|
|
224
|
+
children: [
|
|
225
|
+
/*#__PURE__*/ _jsx("span", {
|
|
226
|
+
children: niceName
|
|
227
|
+
}),
|
|
228
|
+
/*#__PURE__*/ _jsx("code", {
|
|
229
|
+
style: {
|
|
230
|
+
fontSize: '0.75rem',
|
|
231
|
+
color: 'var(--theme-elevation-500)',
|
|
232
|
+
background: 'transparent',
|
|
233
|
+
padding: 0
|
|
234
|
+
},
|
|
235
|
+
children: slug
|
|
236
|
+
})
|
|
237
|
+
]
|
|
238
|
+
})
|
|
239
|
+
]
|
|
240
|
+
})
|
|
241
|
+
}),
|
|
242
|
+
props.actions.map((action)=>/*#__PURE__*/ _jsx("td", {
|
|
243
|
+
style: {
|
|
244
|
+
...cellStyle,
|
|
245
|
+
borderTop: idx === 0 ? 'none' : '1px solid var(--theme-elevation-100)'
|
|
246
|
+
},
|
|
247
|
+
children: /*#__PURE__*/ _jsx(CheckboxInput, {
|
|
248
|
+
checked: isCellChecked(slug, action),
|
|
249
|
+
id: `${props.id}-row-${idx}-${action}`,
|
|
250
|
+
Label: hiddenLabel(`${props.id}-row-${idx}-${action}`, `${niceName}: ${props.actionLabels[action] ?? action}`),
|
|
251
|
+
onToggle: (e)=>toggleCell(slug, action, e.currentTarget.checked)
|
|
252
|
+
})
|
|
253
|
+
}, action))
|
|
254
|
+
]
|
|
255
|
+
}, slug);
|
|
256
|
+
})
|
|
257
|
+
})
|
|
258
|
+
]
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
export function ScopesTable(props) {
|
|
262
|
+
const { value, setValue } = useField({
|
|
263
|
+
path: props.path,
|
|
264
|
+
hasRows: false
|
|
265
|
+
});
|
|
113
266
|
if (props.items.length === 0) {
|
|
114
267
|
return /*#__PURE__*/ _jsxs("div", {
|
|
115
268
|
className: "field-type",
|
|
@@ -151,132 +304,14 @@ export function ScopesTable(props) {
|
|
|
151
304
|
},
|
|
152
305
|
children: props.description
|
|
153
306
|
}),
|
|
154
|
-
/*#__PURE__*/
|
|
307
|
+
/*#__PURE__*/ _jsx(ScopesMatrix, {
|
|
155
308
|
id: `${props.path}-matrix`,
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
borderRadius: '4px',
|
|
163
|
-
overflow: 'hidden'
|
|
164
|
-
},
|
|
165
|
-
children: [
|
|
166
|
-
/*#__PURE__*/ _jsx("thead", {
|
|
167
|
-
children: /*#__PURE__*/ _jsxs("tr", {
|
|
168
|
-
children: [
|
|
169
|
-
/*#__PURE__*/ _jsx("th", {
|
|
170
|
-
style: {
|
|
171
|
-
...headerCellStyle,
|
|
172
|
-
textAlign: 'left'
|
|
173
|
-
},
|
|
174
|
-
children: /*#__PURE__*/ _jsxs("div", {
|
|
175
|
-
style: {
|
|
176
|
-
display: 'flex',
|
|
177
|
-
flexDirection: 'column',
|
|
178
|
-
gap: '0.35rem'
|
|
179
|
-
},
|
|
180
|
-
children: [
|
|
181
|
-
/*#__PURE__*/ _jsx("span", {
|
|
182
|
-
children: props.itemHeader
|
|
183
|
-
}),
|
|
184
|
-
/*#__PURE__*/ _jsx(CheckboxInput, {
|
|
185
|
-
checked: isAllFull,
|
|
186
|
-
partialChecked: isAllPartial && !isAllFull,
|
|
187
|
-
onToggle: (e)=>toggleAll(e.currentTarget.checked),
|
|
188
|
-
label: "All"
|
|
189
|
-
})
|
|
190
|
-
]
|
|
191
|
-
})
|
|
192
|
-
}),
|
|
193
|
-
props.actions.map((action)=>/*#__PURE__*/ _jsx("th", {
|
|
194
|
-
style: headerCellStyle,
|
|
195
|
-
children: /*#__PURE__*/ _jsxs("div", {
|
|
196
|
-
style: {
|
|
197
|
-
display: 'flex',
|
|
198
|
-
flexDirection: 'column',
|
|
199
|
-
alignItems: 'center',
|
|
200
|
-
gap: '0.35rem'
|
|
201
|
-
},
|
|
202
|
-
children: [
|
|
203
|
-
/*#__PURE__*/ _jsx("span", {
|
|
204
|
-
children: props.actionLabels[action] ?? action
|
|
205
|
-
}),
|
|
206
|
-
/*#__PURE__*/ _jsx(CheckboxInput, {
|
|
207
|
-
checked: isColumnFull(action),
|
|
208
|
-
partialChecked: isColumnPartial(action) && !isColumnFull(action),
|
|
209
|
-
onToggle: (e)=>toggleColumn(action, e.currentTarget.checked)
|
|
210
|
-
})
|
|
211
|
-
]
|
|
212
|
-
})
|
|
213
|
-
}, action))
|
|
214
|
-
]
|
|
215
|
-
})
|
|
216
|
-
}),
|
|
217
|
-
/*#__PURE__*/ _jsx("tbody", {
|
|
218
|
-
children: props.items.map((slug, idx)=>{
|
|
219
|
-
const niceName = toWords(slug);
|
|
220
|
-
return /*#__PURE__*/ _jsxs("tr", {
|
|
221
|
-
style: {
|
|
222
|
-
background: idx % 2 === 0 ? 'var(--theme-input-bg)' : 'var(--theme-elevation-25)'
|
|
223
|
-
},
|
|
224
|
-
children: [
|
|
225
|
-
/*#__PURE__*/ _jsx("td", {
|
|
226
|
-
style: {
|
|
227
|
-
...labelCellStyle,
|
|
228
|
-
borderTop: idx === 0 ? 'none' : '1px solid var(--theme-elevation-100)'
|
|
229
|
-
},
|
|
230
|
-
children: /*#__PURE__*/ _jsxs("div", {
|
|
231
|
-
style: {
|
|
232
|
-
display: 'flex',
|
|
233
|
-
alignItems: 'center',
|
|
234
|
-
gap: '0.6rem'
|
|
235
|
-
},
|
|
236
|
-
children: [
|
|
237
|
-
/*#__PURE__*/ _jsx(CheckboxInput, {
|
|
238
|
-
checked: isRowFull(slug),
|
|
239
|
-
partialChecked: isRowPartial(slug) && !isRowFull(slug),
|
|
240
|
-
onToggle: (e)=>toggleRow(slug, e.currentTarget.checked)
|
|
241
|
-
}),
|
|
242
|
-
/*#__PURE__*/ _jsxs("div", {
|
|
243
|
-
style: {
|
|
244
|
-
display: 'flex',
|
|
245
|
-
flexDirection: 'column'
|
|
246
|
-
},
|
|
247
|
-
children: [
|
|
248
|
-
/*#__PURE__*/ _jsx("span", {
|
|
249
|
-
children: niceName
|
|
250
|
-
}),
|
|
251
|
-
/*#__PURE__*/ _jsx("code", {
|
|
252
|
-
style: {
|
|
253
|
-
fontSize: '0.75rem',
|
|
254
|
-
color: 'var(--theme-elevation-500)',
|
|
255
|
-
background: 'transparent',
|
|
256
|
-
padding: 0
|
|
257
|
-
},
|
|
258
|
-
children: slug
|
|
259
|
-
})
|
|
260
|
-
]
|
|
261
|
-
})
|
|
262
|
-
]
|
|
263
|
-
})
|
|
264
|
-
}),
|
|
265
|
-
props.actions.map((action)=>/*#__PURE__*/ _jsx("td", {
|
|
266
|
-
style: {
|
|
267
|
-
...cellStyle,
|
|
268
|
-
borderTop: idx === 0 ? 'none' : '1px solid var(--theme-elevation-100)'
|
|
269
|
-
},
|
|
270
|
-
children: /*#__PURE__*/ _jsx(CheckboxInput, {
|
|
271
|
-
checked: isCellChecked(slug, action),
|
|
272
|
-
onToggle: (e)=>toggleCell(slug, action, e.currentTarget.checked)
|
|
273
|
-
})
|
|
274
|
-
}, action))
|
|
275
|
-
]
|
|
276
|
-
}, slug);
|
|
277
|
-
})
|
|
278
|
-
})
|
|
279
|
-
]
|
|
309
|
+
value: value,
|
|
310
|
+
onChange: setValue,
|
|
311
|
+
items: props.items,
|
|
312
|
+
actions: props.actions,
|
|
313
|
+
actionLabels: props.actionLabels,
|
|
314
|
+
itemHeader: props.itemHeader
|
|
280
315
|
})
|
|
281
316
|
]
|
|
282
317
|
});
|