@mvriu5/payload-ai 1.6.3 → 1.6.4
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/components/action-toast/ActionToast.d.ts +1 -14
- package/dist/components/action-toast/ActionToast.js +1 -1
- package/dist/components/ai-input/AIInput.js +1 -1
- package/dist/components/audit-log-list/AuditLogList.d.ts +2 -3
- package/dist/components/diff-dialog/DiffDialog.d.ts +2 -6
- package/dist/components/diff-dialog/DiffDialog.js +1 -1
- package/dist/components/hooks/useAIChatStream.d.ts +1 -1
- package/dist/components/hooks/useAISettings.d.ts +1 -1
- package/dist/components/hooks/useAISettings.js +1 -1
- package/dist/components/hooks/useDocumentMentionSuggestions.js +1 -1
- package/dist/components/hooks/useMentions.js +1 -1
- package/dist/components/hooks/usePluginConfig.d.ts +6 -6
- package/dist/components/hooks/usePluginConfig.js +1 -1
- package/dist/{payload → features}/collectionPermissions.js +1 -1
- package/dist/{ai → features}/promptCaching.d.ts +2 -2
- package/dist/features/proposals/containerNormalization.d.ts +8 -0
- package/dist/features/proposals/containerNormalization.js +112 -0
- package/dist/{payload/proposalData.d.ts → features/proposals/data.d.ts} +5 -10
- package/dist/features/proposals/data.js +113 -0
- package/dist/features/proposals/fieldNormalization.d.ts +2 -0
- package/dist/features/proposals/fieldNormalization.js +69 -0
- package/dist/features/proposals/normalizationTypes.d.ts +31 -0
- package/dist/features/proposals/normalizationTypes.js +1 -0
- package/dist/features/proposals/optionInference.d.ts +13 -0
- package/dist/features/proposals/optionInference.js +46 -0
- package/dist/features/proposals/recordNormalization.d.ts +6 -0
- package/dist/features/proposals/recordNormalization.js +78 -0
- package/dist/features/proposals/relationshipNormalization.d.ts +8 -0
- package/dist/features/proposals/relationshipNormalization.js +71 -0
- package/dist/{ai/proposalRepair.d.ts → features/proposals/repair.d.ts} +1 -1
- package/dist/{ai/proposalSigning.d.ts → features/proposals/signing.d.ts} +2 -5
- package/dist/{ai/proposalSigning.js → features/proposals/signing.js} +1 -1
- package/dist/features/proposals/target.d.ts +52 -0
- package/dist/features/proposals/target.js +125 -0
- package/dist/features/proposals/types.d.ts +49 -0
- package/dist/features/proposals/types.js +1 -0
- package/dist/features/proposals/validation.d.ts +12 -0
- package/dist/features/proposals/validation.js +26 -0
- package/dist/features/providers/requestContext.d.ts +53 -0
- package/dist/features/providers/requestContext.js +90 -0
- package/dist/{ai/providerRuntime.d.ts → features/providers/runtime.d.ts} +1 -1
- package/dist/{ai/providerRuntime.js → features/providers/runtime.js} +1 -1
- package/dist/features/schema/context.d.ts +7 -0
- package/dist/features/schema/context.js +11 -0
- package/dist/{payload/schemaContext.d.ts → features/schema/description.d.ts} +6 -33
- package/dist/{payload/schemaContext.js → features/schema/description.js} +3 -207
- package/dist/{payload/toolFieldSelection.d.ts → features/schema/fieldSelection.d.ts} +1 -1
- package/dist/{payload/toolFieldSelection.js → features/schema/fieldSelection.js} +2 -2
- package/dist/features/schema/mentionDocuments.d.ts +15 -0
- package/dist/features/schema/mentionDocuments.js +50 -0
- package/dist/features/schema/mentions.d.ts +18 -0
- package/dist/features/schema/mentions.js +100 -0
- package/dist/{payload/normalizeData.js → features/schema/normalize.js} +1 -1
- package/dist/features/schema/registry.d.ts +30 -0
- package/dist/features/schema/registry.js +73 -0
- package/dist/{payload → features/schema}/toolSchemas.d.ts +1 -1
- package/dist/{payload → features/schema}/toolSchemas.js +1 -1
- package/dist/{ai → features}/sensitiveData.js +1 -1
- package/dist/{ai → features}/tokenUsage.d.ts +1 -2
- package/dist/handlers/apply/audit.d.ts +42 -0
- package/dist/handlers/apply/audit.js +150 -0
- package/dist/handlers/apply/operations.d.ts +18 -0
- package/dist/handlers/apply/operations.js +377 -0
- package/dist/handlers/apply/types.d.ts +33 -0
- package/dist/handlers/apply/types.js +1 -0
- package/dist/handlers/apply/validation.d.ts +45 -0
- package/dist/handlers/apply/validation.js +125 -0
- package/dist/handlers/applyActionHandler.d.ts +1 -6
- package/dist/handlers/applyActionHandler.js +13 -757
- package/dist/handlers/auditLogHandler.js +4 -8
- package/dist/handlers/chat/intent.d.ts +32 -0
- package/dist/handlers/chat/intent.js +155 -0
- package/dist/handlers/chat/prompt.d.ts +20 -0
- package/dist/handlers/chat/prompt.js +55 -0
- package/dist/handlers/chat/proposalTools.d.ts +96 -0
- package/dist/handlers/chat/proposalTools.js +451 -0
- package/dist/handlers/chat/streaming.d.ts +38 -0
- package/dist/handlers/chat/streaming.js +136 -0
- package/dist/handlers/chat/toolFactory.d.ts +79 -0
- package/dist/handlers/chat/toolFactory.js +156 -0
- package/dist/handlers/chat/types.d.ts +57 -0
- package/dist/handlers/chat/types.js +1 -0
- package/dist/handlers/chatHandler.d.ts +1 -44
- package/dist/handlers/chatHandler.js +186 -1162
- package/dist/handlers/generateFieldHandler.d.ts +3 -8
- package/dist/handlers/generateFieldHandler.js +26 -97
- package/dist/handlers/http.d.ts +17 -0
- package/dist/handlers/http.js +21 -0
- package/dist/handlers/mediaUploadHandler.js +12 -34
- package/dist/handlers/mentionSuggestionHandler.d.ts +1 -1
- package/dist/handlers/mentionSuggestionHandler.js +6 -10
- package/dist/handlers/proposalDiffHandler.d.ts +1 -1
- package/dist/handlers/proposalDiffHandler.js +72 -195
- package/dist/handlers/translateDocumentHandler.d.ts +3 -8
- package/dist/handlers/translateDocumentHandler.js +26 -82
- package/dist/index.d.ts +4 -30
- package/dist/index.js +31 -421
- package/dist/plugin/admin.d.ts +30 -0
- package/dist/plugin/admin.js +155 -0
- package/dist/plugin/collections.d.ts +3 -0
- package/dist/plugin/collections.js +169 -0
- package/dist/plugin/endpoints.d.ts +23 -0
- package/dist/plugin/endpoints.js +84 -0
- package/dist/plugin/options.d.ts +4 -0
- package/dist/plugin/options.js +13 -0
- package/dist/plugin/types.d.ts +28 -0
- package/dist/plugin/types.js +1 -0
- package/dist/{payload/shared.d.ts → utils/data.d.ts} +2 -12
- package/package.json +1 -1
- package/dist/payload/proposalData.js +0 -578
- /package/dist/{payload → features}/collectionPermissions.d.ts +0 -0
- /package/dist/{payload → features/content}/documentTranslation.d.ts +0 -0
- /package/dist/{payload → features/content}/documentTranslation.js +0 -0
- /package/dist/{payload/textFieldGeneration.d.ts → features/content/fieldGeneration.d.ts} +0 -0
- /package/dist/{payload/textFieldGeneration.js → features/content/fieldGeneration.js} +0 -0
- /package/dist/{ai → features}/promptCaching.js +0 -0
- /package/dist/{ai/proposalRepair.js → features/proposals/repair.js} +0 -0
- /package/dist/{ai/providerOptions.d.ts → features/providers/options.d.ts} +0 -0
- /package/dist/{ai/providerOptions.js → features/providers/options.js} +0 -0
- /package/dist/{payload/normalizeData.d.ts → features/schema/normalize.d.ts} +0 -0
- /package/dist/{ai → features}/sensitiveData.d.ts +0 -0
- /package/dist/{ai → features}/tokenUsage.js +0 -0
- /package/dist/{payload/shared.js → utils/data.js} +0 -0
- /package/dist/{payload → utils}/logging.d.ts +0 -0
- /package/dist/{payload → utils}/logging.js +0 -0
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import type { PayloadHandler } from "payload";
|
|
2
|
-
import { type
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
type GenerateFieldOptions = {
|
|
6
|
-
allowUserApiKeys?: boolean;
|
|
2
|
+
import { type AIRequestOptions } from "../features/providers/requestContext.js";
|
|
3
|
+
import type { TextGenerationPageContext } from "../features/content/fieldGeneration.js";
|
|
4
|
+
type GenerateFieldOptions = AIRequestOptions & {
|
|
7
5
|
maxOutputTokens?: number;
|
|
8
|
-
maxTokenUsage?: ResolvedMaxTokenUsageOptions;
|
|
9
|
-
models?: AIModelConfig;
|
|
10
6
|
pageContexts: Map<string, TextGenerationPageContext>;
|
|
11
|
-
providers?: ResolvedAIProviderConfig[];
|
|
12
7
|
};
|
|
13
8
|
export declare const createGenerateFieldHandler: (options: GenerateFieldOptions) => PayloadHandler;
|
|
14
9
|
export {};
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { generateText } from "ai";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { redactSensitiveData } from "../ai/sensitiveData.js";
|
|
2
|
+
import { resolveAIRequestContext } from "../features/providers/requestContext.js";
|
|
3
|
+
import { redactSensitiveData } from "../features/sensitiveData.js";
|
|
4
|
+
import { jsonError, logHandlerError, readJSONBody, withAuthenticatedHandler } from "./http.js";
|
|
6
5
|
const maxContextLength = 12000;
|
|
7
6
|
const getCompactContext = (context)=>{
|
|
8
7
|
const redacted = redactSensitiveData(context);
|
|
@@ -47,94 +46,33 @@ const parseGeneratedValue = (fieldType, text)=>{
|
|
|
47
46
|
const withoutFence = value.replace(/^```(?:json)?\s*/i, "").replace(/\s*```$/, "");
|
|
48
47
|
return JSON.parse(withoutFence);
|
|
49
48
|
};
|
|
50
|
-
export const createGenerateFieldHandler = (options)=>async (req)=>{
|
|
51
|
-
|
|
52
|
-
error: "Unauthorized"
|
|
53
|
-
}, {
|
|
54
|
-
status: 401
|
|
55
|
-
});
|
|
56
|
-
const body = req.json ? await req.json().catch(()=>null) : null;
|
|
49
|
+
export const createGenerateFieldHandler = (options)=>withAuthenticatedHandler(async (req)=>{
|
|
50
|
+
const body = await readJSONBody(req);
|
|
57
51
|
const scopeType = body?.scope?.type;
|
|
58
52
|
const scopeSlug = body?.scope?.slug?.trim();
|
|
59
53
|
const fieldKey = body?.fieldKey?.trim();
|
|
60
54
|
if (!scopeType || !scopeSlug || !fieldKey) {
|
|
61
|
-
return
|
|
62
|
-
error: "Page scope and field are required."
|
|
63
|
-
}, {
|
|
64
|
-
status: 400
|
|
65
|
-
});
|
|
55
|
+
return jsonError("Page scope and field are required.");
|
|
66
56
|
}
|
|
67
57
|
const pageContext = options.pageContexts.get(`${scopeType}:${scopeSlug}`);
|
|
68
58
|
const fieldContext = pageContext?.fields.find((field)=>field.key === fieldKey);
|
|
69
59
|
if (!pageContext || !fieldContext) {
|
|
70
|
-
return
|
|
71
|
-
error: "This field is not available for AI generation."
|
|
72
|
-
}, {
|
|
73
|
-
status: 400
|
|
74
|
-
});
|
|
60
|
+
return jsonError("This field is not available for AI generation.");
|
|
75
61
|
}
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
maxTokenUsage: options.maxTokenUsage,
|
|
62
|
+
const aiRequestResolution = await resolveAIRequestContext({
|
|
63
|
+
options,
|
|
79
64
|
req,
|
|
80
|
-
|
|
65
|
+
requestedModel: body?.model,
|
|
66
|
+
requestedProvider: body?.provider,
|
|
67
|
+
user: req.user
|
|
81
68
|
});
|
|
82
|
-
if (
|
|
83
|
-
return
|
|
84
|
-
error: "AI token usage limit reached."
|
|
85
|
-
}, {
|
|
86
|
-
status: 429
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
const managedProviders = options.providers?.length ? options.providers : null;
|
|
90
|
-
const requestedProvider = body?.provider || (managedProviders ? managedProviders[0].id : user.aiProvider || "openai");
|
|
91
|
-
const managedProvider = managedProviders?.find((provider)=>provider.id === requestedProvider);
|
|
92
|
-
if (managedProviders && !managedProvider) {
|
|
93
|
-
return Response.json({
|
|
94
|
-
error: `Unsupported AI provider: ${requestedProvider}`
|
|
95
|
-
}, {
|
|
96
|
-
status: 400
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
if (!managedProvider && !isAIProvider(requestedProvider)) {
|
|
100
|
-
return Response.json({
|
|
101
|
-
error: `Unsupported AI provider: ${requestedProvider}`
|
|
102
|
-
}, {
|
|
103
|
-
status: 400
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
const provider = managedProvider?.provider || requestedProvider;
|
|
107
|
-
const requestedModel = body?.model || managedProvider?.defaultModel;
|
|
108
|
-
if (managedProvider && requestedModel && !managedProvider.models.some((model)=>model.value === requestedModel)) {
|
|
109
|
-
return Response.json({
|
|
110
|
-
error: `Unsupported model "${requestedModel}" for AI provider "${managedProvider.id}".`
|
|
111
|
-
}, {
|
|
112
|
-
status: 400
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
const providerConfig = getProviderConfig({
|
|
116
|
-
apiKey: managedProvider ? managedProvider.apiKey : options.allowUserApiKeys === false ? null : user.aiApiKey,
|
|
117
|
-
defaultModels: options.models?.defaults,
|
|
118
|
-
model: requestedModel,
|
|
119
|
-
provider
|
|
120
|
-
});
|
|
121
|
-
if (!providerConfig.apiKey) {
|
|
122
|
-
return Response.json({
|
|
123
|
-
error: "Configure an AI provider API key first."
|
|
124
|
-
}, {
|
|
125
|
-
status: 400
|
|
126
|
-
});
|
|
69
|
+
if (!aiRequestResolution.ok) {
|
|
70
|
+
return jsonError(aiRequestResolution.error.message, aiRequestResolution.error.code === "token_limit" ? 429 : 400);
|
|
127
71
|
}
|
|
72
|
+
const aiRequest = aiRequestResolution.context;
|
|
128
73
|
try {
|
|
129
74
|
const blockContext = getBlockContext(body?.context, body?.fieldPath);
|
|
130
|
-
const model = await
|
|
131
|
-
apiKey: providerConfig.apiKey,
|
|
132
|
-
...managedProvider?.baseURL ? {
|
|
133
|
-
baseURL: managedProvider.baseURL
|
|
134
|
-
} : {},
|
|
135
|
-
model: providerConfig.modelID,
|
|
136
|
-
provider
|
|
137
|
-
});
|
|
75
|
+
const model = await aiRequest.loadModel();
|
|
138
76
|
const result = await generateText({
|
|
139
77
|
maxOutputTokens: Math.min(options.maxOutputTokens || 300, 600),
|
|
140
78
|
model,
|
|
@@ -159,29 +97,20 @@ export const createGenerateFieldHandler = (options)=>async (req)=>{
|
|
|
159
97
|
"Return no labels or explanation. For JSON fields, return strict JSON; for all other fields, return plain text without quotes or Markdown."
|
|
160
98
|
].join(" ")
|
|
161
99
|
});
|
|
162
|
-
if (result.usage
|
|
163
|
-
await recordTokenUsage({
|
|
164
|
-
model: providerConfig.modelID,
|
|
165
|
-
provider: managedProvider?.id || provider,
|
|
166
|
-
req,
|
|
167
|
-
usage: result.usage,
|
|
168
|
-
userID: user.id
|
|
169
|
-
});
|
|
170
|
-
}
|
|
100
|
+
if (result.usage) await aiRequest.recordUsage(result.usage);
|
|
171
101
|
const value = parseGeneratedValue(fieldContext.fieldType, result.text);
|
|
172
102
|
return Response.json({
|
|
173
103
|
value: fieldContext.maxLength && typeof value === "string" ? value.slice(0, fieldContext.maxLength) : value
|
|
174
104
|
});
|
|
175
105
|
} catch (error) {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
status: 500
|
|
106
|
+
return logHandlerError({
|
|
107
|
+
details: {
|
|
108
|
+
fieldKey
|
|
109
|
+
},
|
|
110
|
+
error,
|
|
111
|
+
logMessage: "AI field generation failed",
|
|
112
|
+
publicMessage: "AI field generation failed.",
|
|
113
|
+
req
|
|
185
114
|
});
|
|
186
115
|
}
|
|
187
|
-
};
|
|
116
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { PayloadHandler } from "payload";
|
|
2
|
+
type HandlerRequest = Parameters<PayloadHandler>[0];
|
|
3
|
+
type AuthenticatedRequest = HandlerRequest & {
|
|
4
|
+
user: NonNullable<HandlerRequest["user"]>;
|
|
5
|
+
};
|
|
6
|
+
export declare const jsonError: (error: string, status?: number) => Response;
|
|
7
|
+
export declare const readJSONBody: <Body>(req: HandlerRequest) => Promise<Body | null>;
|
|
8
|
+
export declare const withAuthenticatedHandler: (handler: (req: AuthenticatedRequest) => Promise<Response> | Response) => PayloadHandler;
|
|
9
|
+
export declare const logHandlerError: ({ details, error, logMessage, publicMessage, req, status, }: {
|
|
10
|
+
details?: Record<string, unknown>;
|
|
11
|
+
error: unknown;
|
|
12
|
+
logMessage: string;
|
|
13
|
+
publicMessage: string;
|
|
14
|
+
req: HandlerRequest;
|
|
15
|
+
status?: number;
|
|
16
|
+
}) => Response;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const jsonError = (error, status = 400)=>Response.json({
|
|
2
|
+
error
|
|
3
|
+
}, {
|
|
4
|
+
status
|
|
5
|
+
});
|
|
6
|
+
export const readJSONBody = async (req)=>{
|
|
7
|
+
if (!req.json) return null;
|
|
8
|
+
return await req.json().catch(()=>null);
|
|
9
|
+
};
|
|
10
|
+
export const withAuthenticatedHandler = (handler)=>async (req)=>{
|
|
11
|
+
if (!req.user) return jsonError("Unauthorized", 401);
|
|
12
|
+
return handler(req);
|
|
13
|
+
};
|
|
14
|
+
export const logHandlerError = ({ details, error, logMessage, publicMessage, req, status = 500 })=>{
|
|
15
|
+
req.payload.logger.error({
|
|
16
|
+
...details,
|
|
17
|
+
err: error,
|
|
18
|
+
msg: logMessage
|
|
19
|
+
});
|
|
20
|
+
return jsonError(publicMessage, status);
|
|
21
|
+
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { addDataAndFileToRequest } from "payload";
|
|
2
|
-
import { getNumber, getString, isRecord } from "../
|
|
2
|
+
import { getNumber, getString, isRecord } from "../utils/data.js";
|
|
3
|
+
import { jsonError, logHandlerError } from "./http.js";
|
|
3
4
|
const mimeTypeMatches = (mimeType, acceptedMimeType)=>{
|
|
4
5
|
if (acceptedMimeType === mimeType) return true;
|
|
5
6
|
if (!acceptedMimeType.endsWith("/*")) return false;
|
|
@@ -33,42 +34,22 @@ export const createMediaUploadHandler = ({ acceptedMimeTypes, collectionSlug, ma
|
|
|
33
34
|
await addDataAndFileToRequest(uploadReq);
|
|
34
35
|
const collectionConfig = uploadReq.payload.config.collections.find((collection)=>collection.slug === collectionSlug);
|
|
35
36
|
if (!collectionConfig) {
|
|
36
|
-
return
|
|
37
|
-
error: `Upload collection not found: ${collectionSlug}`
|
|
38
|
-
}, {
|
|
39
|
-
status: 400
|
|
40
|
-
});
|
|
37
|
+
return jsonError(`Upload collection not found: ${collectionSlug}`);
|
|
41
38
|
}
|
|
42
39
|
if (!collectionConfig.upload) {
|
|
43
|
-
return
|
|
44
|
-
error: `Collection is not upload-enabled: ${collectionSlug}`
|
|
45
|
-
}, {
|
|
46
|
-
status: 400
|
|
47
|
-
});
|
|
40
|
+
return jsonError(`Collection is not upload-enabled: ${collectionSlug}`);
|
|
48
41
|
}
|
|
49
42
|
const file = uploadReq.file;
|
|
50
43
|
if (!file) {
|
|
51
|
-
return
|
|
52
|
-
error: "File is required"
|
|
53
|
-
}, {
|
|
54
|
-
status: 400
|
|
55
|
-
});
|
|
44
|
+
return jsonError("File is required");
|
|
56
45
|
}
|
|
57
46
|
const fileSize = typeof file.size === "number" && Number.isFinite(file.size) ? file.size : 0;
|
|
58
47
|
if (maxFileSize && fileSize > maxFileSize) {
|
|
59
|
-
return
|
|
60
|
-
error: `File exceeds max size of ${maxFileSize} bytes`
|
|
61
|
-
}, {
|
|
62
|
-
status: 413
|
|
63
|
-
});
|
|
48
|
+
return jsonError(`File exceeds max size of ${maxFileSize} bytes`, 413);
|
|
64
49
|
}
|
|
65
50
|
const mimeType = file.mimetype || "";
|
|
66
51
|
if (mimeType && !isAcceptedMimeType(mimeType, acceptedMimeTypes)) {
|
|
67
|
-
return
|
|
68
|
-
error: `File type is not accepted: ${mimeType}`
|
|
69
|
-
}, {
|
|
70
|
-
status: 415
|
|
71
|
-
});
|
|
52
|
+
return jsonError(`File type is not accepted: ${mimeType}`, 415);
|
|
72
53
|
}
|
|
73
54
|
const doc = await uploadReq.payload.create({
|
|
74
55
|
collection: collectionSlug,
|
|
@@ -86,14 +67,11 @@ export const createMediaUploadHandler = ({ acceptedMimeTypes, collectionSlug, ma
|
|
|
86
67
|
doc
|
|
87
68
|
});
|
|
88
69
|
} catch (err) {
|
|
89
|
-
|
|
90
|
-
err,
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
error: "Media upload failed."
|
|
95
|
-
}, {
|
|
96
|
-
status: 500
|
|
70
|
+
return logHandlerError({
|
|
71
|
+
error: err,
|
|
72
|
+
logMessage: "AI media upload failed",
|
|
73
|
+
publicMessage: "Media upload failed.",
|
|
74
|
+
req: uploadReq
|
|
97
75
|
});
|
|
98
76
|
}
|
|
99
77
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PayloadHandler } from "payload";
|
|
2
|
-
import { type ResolvedCollectionPermissionMap } from "../
|
|
2
|
+
import { type ResolvedCollectionPermissionMap } from "../features/collectionPermissions.js";
|
|
3
3
|
type MentionSuggestionsOptions = {
|
|
4
4
|
collections?: ResolvedCollectionPermissionMap;
|
|
5
5
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { isCollectionActionAllowed } from "../
|
|
2
|
-
import { getDocLabel } from "../
|
|
1
|
+
import { isCollectionActionAllowed } from "../features/collectionPermissions.js";
|
|
2
|
+
import { getDocLabel } from "../utils/data.js";
|
|
3
|
+
import { readJSONBody, withAuthenticatedHandler } from "./http.js";
|
|
3
4
|
const getLocaleCodes = (req)=>{
|
|
4
5
|
const localization = req.payload.config.localization;
|
|
5
6
|
if (!localization) return [];
|
|
@@ -20,13 +21,8 @@ const hasLocalizedFields = (fields)=>{
|
|
|
20
21
|
return Boolean(field.localized) || Boolean(field.fields?.length && hasLocalizedFields(field.fields)) || Boolean(field.tabs?.some((tab)=>hasLocalizedFields(tab.fields || [])));
|
|
21
22
|
});
|
|
22
23
|
};
|
|
23
|
-
export const createMentionSuggestionHandler = (options = {})=>async (req)=>{
|
|
24
|
-
|
|
25
|
-
error: "Unauthorized"
|
|
26
|
-
}, {
|
|
27
|
-
status: 401
|
|
28
|
-
});
|
|
29
|
-
const body = req.json ? await req.json().catch(()=>null) : null;
|
|
24
|
+
export const createMentionSuggestionHandler = (options = {})=>withAuthenticatedHandler(async (req)=>{
|
|
25
|
+
const body = await readJSONBody(req);
|
|
30
26
|
const query = body?.query?.trim();
|
|
31
27
|
const collectionSlug = body?.collectionSlug?.trim();
|
|
32
28
|
if (!query && !collectionSlug) return Response.json({
|
|
@@ -96,4 +92,4 @@ export const createMentionSuggestionHandler = (options = {})=>async (req)=>{
|
|
|
96
92
|
return Response.json({
|
|
97
93
|
suggestions: suggestions.slice(0, 5)
|
|
98
94
|
});
|
|
99
|
-
};
|
|
95
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PayloadHandler } from "payload";
|
|
2
|
-
import { type ResolvedCollectionPermissionMap } from "../
|
|
2
|
+
import { type ResolvedCollectionPermissionMap } from "../features/collectionPermissions.js";
|
|
3
3
|
type ProposalDiffOptions = {
|
|
4
4
|
collections?: ResolvedCollectionPermissionMap;
|
|
5
5
|
};
|