@focus-reactive/payload-plugin-translator 0.4.0 → 0.5.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 +44 -29
- package/dist/index.d.ts +16 -14
- package/dist/index.js +9 -7
- package/dist/plugin.d.ts +15 -4
- package/dist/plugin.js +34 -57
- package/dist/server/features/cancel/handler.d.ts +2 -2
- package/dist/server/features/cancel/handler.js +3 -1
- package/dist/server/features/cancel/route.d.ts +4 -4
- package/dist/server/features/cancel/route.js +4 -4
- package/dist/server/features/cancel-by-collection/handler.d.ts +3 -3
- package/dist/server/features/cancel-by-collection/handler.js +1 -1
- package/dist/server/features/cancel-by-collection/route.d.ts +5 -5
- package/dist/server/features/cancel-by-collection/route.js +4 -4
- package/dist/server/features/createTranslationRoutes.d.ts +23 -0
- package/dist/server/features/createTranslationRoutes.js +27 -0
- package/dist/server/features/enqueue-translation/handler.d.ts +3 -3
- package/dist/server/features/enqueue-translation/handler.js +1 -1
- package/dist/server/features/enqueue-translation/route.d.ts +5 -5
- package/dist/server/features/enqueue-translation/route.js +4 -4
- package/dist/server/features/get-collection-status/handler.d.ts +3 -3
- package/dist/server/features/get-collection-status/handler.js +1 -1
- package/dist/server/features/get-collection-status/route.d.ts +5 -5
- package/dist/server/features/get-collection-status/route.js +4 -4
- package/dist/server/features/get-document-status/handler.d.ts +3 -3
- package/dist/server/features/get-document-status/handler.js +1 -1
- package/dist/server/features/get-document-status/route.d.ts +5 -5
- package/dist/server/features/get-document-status/route.js +4 -4
- package/dist/server/features/index.d.ts +7 -6
- package/dist/server/features/index.js +7 -6
- package/dist/server/features/run-translation/handler.d.ts +2 -2
- package/dist/server/features/run-translation/route.d.ts +4 -4
- package/dist/server/features/run-translation/route.js +4 -4
- package/dist/server/features/translate-document/handler.js +7 -11
- package/dist/server/modules/task-runner/TaskRunnerProvider.interface.d.ts +18 -1
- package/dist/server/modules/task-runner/index.d.ts +6 -6
- package/dist/server/modules/task-runner/index.js +2 -2
- package/dist/server/modules/task-runner/payload-jobs-runner/PayloadJobsRunnerProvider.d.ts +16 -1
- package/dist/server/modules/task-runner/payload-jobs-runner/PayloadJobsRunnerProvider.js +16 -1
- package/dist/server/modules/task-runner/sync-runner/SyncRunnerProvider.d.ts +18 -10
- package/dist/server/modules/task-runner/sync-runner/SyncRunnerProvider.js +24 -14
- package/dist/server/modules/translation-levels/PluginConfigBuilder.d.ts +46 -0
- package/dist/server/modules/translation-levels/PluginConfigBuilder.js +108 -0
- package/dist/server/modules/translation-levels/collectionLevel.d.ts +15 -0
- package/dist/server/modules/translation-levels/collectionLevel.js +24 -0
- package/dist/server/modules/translation-levels/documentLevel.d.ts +19 -0
- package/dist/server/modules/translation-levels/documentLevel.js +28 -0
- package/dist/server/modules/translation-levels/index.d.ts +3 -0
- package/dist/server/modules/translation-levels/index.js +4 -0
- package/dist/server/modules/translation-levels/types.d.ts +42 -0
- package/dist/server/modules/translation-levels/types.js +10 -0
- package/dist/server/modules/translation-levels/useDocTranslationApi.d.ts +8 -0
- package/dist/server/modules/translation-levels/useDocTranslationApi.js +18 -0
- package/dist/server/modules/translation-pipeline/index.d.ts +5 -3
- package/dist/server/modules/translation-pipeline/index.js +3 -2
- package/dist/server/modules/translation-pipeline/translateContent.d.ts +35 -0
- package/dist/server/modules/translation-pipeline/translateContent.js +30 -0
- package/dist/server/modules/translation-providers/OpenAITranslation.provider.d.ts +4 -3
- package/dist/server/modules/translation-providers/OpenAITranslation.provider.js +15 -15
- package/dist/types/AccessGuard.d.ts +24 -1
- package/dist/types/AccessGuard.js +12 -1
- package/package.json +1 -1
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { TranslateDocumentExport } from "../../../client/widgets/translate-document";
|
|
2
|
+
import { useDocTranslationApi } from "./useDocTranslationApi";
|
|
3
|
+
/**
|
|
4
|
+
* Per-document translation: a popup control on the document edit view, backed by
|
|
5
|
+
* the shared document-translation API (async/job by default; synchronous if the
|
|
6
|
+
* configured `runner` is a sync runner).
|
|
7
|
+
*
|
|
8
|
+
* @since 0.5.0
|
|
9
|
+
* @returns An opaque {@link TranslationLevel} to list in `translatorPlugin({ levels })`.
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* translatorPlugin({
|
|
13
|
+
* collections: [Posts],
|
|
14
|
+
* translationProvider,
|
|
15
|
+
* runner: createPayloadJobsRunner(),
|
|
16
|
+
* levels: [documentLevel(), collectionLevel()], // this is the default — omit for the same result
|
|
17
|
+
* })
|
|
18
|
+
* ```
|
|
19
|
+
*/ export function documentLevel() {
|
|
20
|
+
return {
|
|
21
|
+
extend (ctx) {
|
|
22
|
+
useDocTranslationApi(ctx);
|
|
23
|
+
ctx.addCollectionComponent("beforeDocumentControls", (collection)=>new TranslateDocumentExport(collection, ctx.access));
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
//# sourceMappingURL=documentLevel.js.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { CollectionConfig, Endpoint } from "payload";
|
|
2
|
+
import type { AccessGuard } from "../../../types/AccessGuard";
|
|
3
|
+
import type { RawPayloadComponentExport } from "../../../client/shared/types/PayloadComponentExport";
|
|
4
|
+
import type { TaskRunnerFactory } from "../task-runner";
|
|
5
|
+
export type CollectionAdminSlot = "beforeDocumentControls" | "beforeListTable";
|
|
6
|
+
/**
|
|
7
|
+
* A composable translation surface (document / collection / field).
|
|
8
|
+
*
|
|
9
|
+
* Treat it as an **opaque value**: create one with `documentLevel()` /
|
|
10
|
+
* `collectionLevel()` (and, later, `fieldLevel()`) and list it in
|
|
11
|
+
* `translatorPlugin({ levels })`. It is produced only by those built-in
|
|
12
|
+
* factories — not externally implementable yet, since {@link LevelContext} is
|
|
13
|
+
* intentionally not exported. Opening it later (export `LevelContext`, drop the
|
|
14
|
+
* `@internal` tag) is additive and non-breaking.
|
|
15
|
+
*
|
|
16
|
+
* @since 0.5.0
|
|
17
|
+
*/
|
|
18
|
+
export interface TranslationLevel {
|
|
19
|
+
/**
|
|
20
|
+
* Not a stable contract yet — produce via the level factories.
|
|
21
|
+
* @internal
|
|
22
|
+
*/
|
|
23
|
+
extend(ctx: LevelContext): void;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Public-ready shape, kept internal until external levels are needed.
|
|
27
|
+
*
|
|
28
|
+
* A level contributes via these generic primitives; it never mutates the raw
|
|
29
|
+
* Payload config. The plugin deduplicates endpoints by method + path on apply.
|
|
30
|
+
* (fieldLevel — Phase 2 — will also read `schemaMap` + `translationProvider`.)
|
|
31
|
+
* @internal
|
|
32
|
+
*/
|
|
33
|
+
export interface LevelContext {
|
|
34
|
+
readonly collections: CollectionConfig[];
|
|
35
|
+
readonly basePath: string;
|
|
36
|
+
readonly access?: AccessGuard;
|
|
37
|
+
readonly taskRunnerFactory: TaskRunnerFactory;
|
|
38
|
+
/** Register endpoints. Deduplicated by method + path when applied. */
|
|
39
|
+
addEndpoints(endpoints: Endpoint[]): void;
|
|
40
|
+
/** Attach an admin component to a slot on every managed collection. */
|
|
41
|
+
addCollectionComponent(slot: CollectionAdminSlot, make: (collection: CollectionConfig) => RawPayloadComponentExport): void;
|
|
42
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public-ready shape, kept internal until external levels are needed.
|
|
3
|
+
*
|
|
4
|
+
* A level contributes via these generic primitives; it never mutates the raw
|
|
5
|
+
* Payload config. The plugin deduplicates endpoints by method + path on apply.
|
|
6
|
+
* (fieldLevel — Phase 2 — will also read `schemaMap` + `translationProvider`.)
|
|
7
|
+
* @internal
|
|
8
|
+
*/ export { };
|
|
9
|
+
|
|
10
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { LevelContext } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Contribute the runner-agnostic document-translation API — the shared 6-route
|
|
4
|
+
* bundle, bound to the level context's runner. Both `documentLevel` and
|
|
5
|
+
* `collectionLevel` call this; the plugin deduplicates the endpoints by method +
|
|
6
|
+
* path, so the bundle registers exactly once.
|
|
7
|
+
*/
|
|
8
|
+
export declare function useDocTranslationApi(ctx: LevelContext): void;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createTranslationRoutes } from "../../features/createTranslationRoutes";
|
|
2
|
+
/**
|
|
3
|
+
* Contribute the runner-agnostic document-translation API — the shared 6-route
|
|
4
|
+
* bundle, bound to the level context's runner. Both `documentLevel` and
|
|
5
|
+
* `collectionLevel` call this; the plugin deduplicates the endpoints by method +
|
|
6
|
+
* path, so the bundle registers exactly once.
|
|
7
|
+
*/ export function useDocTranslationApi(ctx) {
|
|
8
|
+
ctx.addEndpoints(createTranslationRoutes({
|
|
9
|
+
taskRunnerFactory: ctx.taskRunnerFactory,
|
|
10
|
+
collectionConfig: {
|
|
11
|
+
availableCollections: new Set(ctx.collections.map((collection)=>collection.slug))
|
|
12
|
+
},
|
|
13
|
+
access: ctx.access,
|
|
14
|
+
basePath: ctx.basePath
|
|
15
|
+
}));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
//# sourceMappingURL=useDocTranslationApi.js.map
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
export { TranslationPipeline } from
|
|
2
|
-
export
|
|
3
|
-
export {
|
|
1
|
+
export { TranslationPipeline } from "./TranslationPipeline";
|
|
2
|
+
export { translateContent } from "./translateContent";
|
|
3
|
+
export type { TranslateContentArgs } from "./translateContent";
|
|
4
|
+
export type { TranslationStrategy } from "./strategies";
|
|
5
|
+
export { OverwriteStrategy, SkipExistingStrategy } from "./strategies";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export { TranslationPipeline } from
|
|
2
|
-
export {
|
|
1
|
+
export { TranslationPipeline } from "./TranslationPipeline";
|
|
2
|
+
export { translateContent } from "./translateContent";
|
|
3
|
+
export { OverwriteStrategy, SkipExistingStrategy } from "./strategies";
|
|
3
4
|
|
|
4
5
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Field } from "payload";
|
|
2
|
+
import type { TranslationProvider } from "../translation-providers";
|
|
3
|
+
import type { TranslationStrategyName } from "./strategies";
|
|
4
|
+
export type TranslateContentArgs = {
|
|
5
|
+
/** Schema subtree to translate (e.g. `[declaredFieldConfig]`). */
|
|
6
|
+
schema: Field[];
|
|
7
|
+
/** Source values, rooted to match `schema` (e.g. `{ [fieldName]: value }`). */
|
|
8
|
+
sourceData: Record<string, unknown>;
|
|
9
|
+
/**
|
|
10
|
+
* Existing target-locale values to reconcile against (target wins when
|
|
11
|
+
* non-empty under `skip_existing`). Defaults to `{}` — i.e. translate the
|
|
12
|
+
* source in place (`overwrite`).
|
|
13
|
+
*/
|
|
14
|
+
targetData?: Record<string, unknown>;
|
|
15
|
+
/** Source language code, or `''` for provider auto-detect. */
|
|
16
|
+
sourceLng: string;
|
|
17
|
+
targetLng: string;
|
|
18
|
+
translationProvider: TranslationProvider;
|
|
19
|
+
/** @default 'overwrite' */
|
|
20
|
+
strategy?: TranslationStrategyName;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Translate a content object over a schema subtree — no DB, no document.
|
|
24
|
+
*
|
|
25
|
+
* A thin reusable entry over {@link TranslationPipeline}, which is already pure
|
|
26
|
+
* and walks any `Field[]` + matching data (a subtree + partial data works
|
|
27
|
+
* unchanged). The document level routes through this wrapper today (instead of
|
|
28
|
+
* constructing the pipeline inline); the upcoming field level will too —
|
|
29
|
+
* passing a single declared field's subtree + its current unsaved form value.
|
|
30
|
+
*
|
|
31
|
+
* Only `localized` text/richText leaves are translated; non-localized values
|
|
32
|
+
* are reconciled through unchanged. Returns the translated data (same shape as
|
|
33
|
+
* `sourceData`) or `null` when nothing was translatable.
|
|
34
|
+
*/
|
|
35
|
+
export declare function translateContent({ schema, sourceData, targetData, sourceLng, targetLng, translationProvider, strategy, }: TranslateContentArgs): Promise<Record<string, unknown> | null>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { TranslationPipeline } from "./TranslationPipeline";
|
|
2
|
+
import { createTranslationStrategy } from "./strategies";
|
|
3
|
+
/**
|
|
4
|
+
* Translate a content object over a schema subtree — no DB, no document.
|
|
5
|
+
*
|
|
6
|
+
* A thin reusable entry over {@link TranslationPipeline}, which is already pure
|
|
7
|
+
* and walks any `Field[]` + matching data (a subtree + partial data works
|
|
8
|
+
* unchanged). The document level routes through this wrapper today (instead of
|
|
9
|
+
* constructing the pipeline inline); the upcoming field level will too —
|
|
10
|
+
* passing a single declared field's subtree + its current unsaved form value.
|
|
11
|
+
*
|
|
12
|
+
* Only `localized` text/richText leaves are translated; non-localized values
|
|
13
|
+
* are reconciled through unchanged. Returns the translated data (same shape as
|
|
14
|
+
* `sourceData`) or `null` when nothing was translatable.
|
|
15
|
+
*/ export async function translateContent({ schema, sourceData, targetData = {}, sourceLng, targetLng, translationProvider, strategy = "overwrite" }) {
|
|
16
|
+
const pipeline = new TranslationPipeline({
|
|
17
|
+
translationProvider,
|
|
18
|
+
translationStrategy: createTranslationStrategy(strategy)
|
|
19
|
+
});
|
|
20
|
+
const result = await pipeline.execute({
|
|
21
|
+
schema,
|
|
22
|
+
sourceData,
|
|
23
|
+
targetData,
|
|
24
|
+
sourceLng,
|
|
25
|
+
targetLng
|
|
26
|
+
});
|
|
27
|
+
return result ? result.translatedData : null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
//# sourceMappingURL=translateContent.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { TranslationProvider, TranslationInput, TranslationOutput } from
|
|
2
|
-
import type { ChatModel } from
|
|
1
|
+
import type { TranslationProvider, TranslationInput, TranslationOutput } from "./TranslationProvider.interface";
|
|
2
|
+
import type { ChatModel } from "openai/resources/index.mjs";
|
|
3
3
|
/**
|
|
4
4
|
* Function to transform text in dry run mode.
|
|
5
5
|
* Receives the original text and returns the transformed text.
|
|
@@ -30,6 +30,7 @@ export type SystemPromptContext = {
|
|
|
30
30
|
*/
|
|
31
31
|
type SystemPromptBuilder = (context: SystemPromptContext) => string;
|
|
32
32
|
export type OpenAIProviderConfig = {
|
|
33
|
+
/** OpenAI API key (required). Read it from an env var — never hard-code it. */
|
|
33
34
|
apiKey: string;
|
|
34
35
|
/**
|
|
35
36
|
* OpenAI model to use for translation.
|
|
@@ -78,8 +79,8 @@ export type OpenAIProviderConfig = {
|
|
|
78
79
|
};
|
|
79
80
|
/** @deprecated Use `createOpenAIProvider` function instead */
|
|
80
81
|
export declare class OpenAITranslationProvider implements TranslationProvider {
|
|
81
|
-
private readonly config;
|
|
82
82
|
private openAiClient;
|
|
83
|
+
private readonly config;
|
|
83
84
|
constructor(config: OpenAIProviderConfig);
|
|
84
85
|
translate(content: TranslationInput, souceLng: string, targetLng: string): Promise<TranslationOutput | null>;
|
|
85
86
|
/**
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import OpenAI from
|
|
2
|
-
import { isObject } from
|
|
1
|
+
import OpenAI from "openai";
|
|
2
|
+
import { isObject } from "../../shared";
|
|
3
3
|
/** @deprecated Use `createOpenAIProvider` function instead */ export class OpenAITranslationProvider {
|
|
4
|
-
config;
|
|
5
4
|
openAiClient;
|
|
5
|
+
config;
|
|
6
6
|
constructor(config){
|
|
7
|
-
this.config = config;
|
|
8
7
|
this.openAiClient = new OpenAI({
|
|
9
8
|
apiKey: config.apiKey
|
|
10
9
|
});
|
|
10
|
+
this.config = config;
|
|
11
11
|
}
|
|
12
12
|
async translate(content, souceLng, targetLng) {
|
|
13
13
|
if (this.config.dryRun) {
|
|
14
|
-
console.info(
|
|
14
|
+
console.info("[DRY RUN] Translation simulation:", {
|
|
15
15
|
content,
|
|
16
16
|
sourceLang: souceLng,
|
|
17
17
|
targetLang: targetLng,
|
|
18
|
-
provider:
|
|
18
|
+
provider: "OpenAI"
|
|
19
19
|
});
|
|
20
20
|
const timeout = this.getDryRunTimeout();
|
|
21
21
|
if (timeout > 0) await new Promise((resolve)=>setTimeout(resolve, timeout));
|
|
@@ -26,21 +26,21 @@ import { isObject } from '../../shared';
|
|
|
26
26
|
const chatCompletion = await this.openAiClient.chat.completions.create({
|
|
27
27
|
messages: [
|
|
28
28
|
{
|
|
29
|
-
role:
|
|
29
|
+
role: "system",
|
|
30
30
|
content: systemPrompt
|
|
31
31
|
},
|
|
32
32
|
{
|
|
33
|
-
role:
|
|
33
|
+
role: "user",
|
|
34
34
|
content: JSON.stringify(content)
|
|
35
35
|
}
|
|
36
36
|
],
|
|
37
|
-
model: this.config.model ??
|
|
37
|
+
model: this.config.model ?? "gpt-4o",
|
|
38
38
|
temperature: 0,
|
|
39
39
|
top_p: 1,
|
|
40
40
|
frequency_penalty: 0,
|
|
41
41
|
presence_penalty: 0,
|
|
42
42
|
response_format: {
|
|
43
|
-
type:
|
|
43
|
+
type: "json_object"
|
|
44
44
|
}
|
|
45
45
|
});
|
|
46
46
|
const translatedContent = chatCompletion.choices[0].message.content;
|
|
@@ -54,7 +54,7 @@ import { isObject } from '../../shared';
|
|
|
54
54
|
/**
|
|
55
55
|
* Builds the system prompt for translation.
|
|
56
56
|
*/ buildSystemPrompt(sourceLang, targetLang) {
|
|
57
|
-
const defaultPrompt = `Translate the values from the JSON that the user will send you${sourceLang ? ` from ${sourceLang}` :
|
|
57
|
+
const defaultPrompt = `Translate the values from the JSON that the user will send you${sourceLang ? ` from ${sourceLang}` : ""} into ${targetLang}. Keep all JSON keys exactly as they are, only translate the values.
|
|
58
58
|
The response should be a valid JSON object with the same structure and keys as the input, but with translated values.
|
|
59
59
|
Maintain any special formatting, placeholders, or variables within the values if they exist.`;
|
|
60
60
|
if (this.config.systemPrompt) {
|
|
@@ -71,17 +71,17 @@ Maintain any special formatting, placeholders, or variables within the values if
|
|
|
71
71
|
* If dryRun is an object with transform, returns it.
|
|
72
72
|
* If dryRun is true, returns the default transformer that reverses text.
|
|
73
73
|
*/ getDryRunTransformer() {
|
|
74
|
-
if (typeof this.config.dryRun ===
|
|
74
|
+
if (typeof this.config.dryRun === "object" && this.config.dryRun.transform) {
|
|
75
75
|
return this.config.dryRun.transform;
|
|
76
76
|
}
|
|
77
|
-
return (text)=>text.split(
|
|
77
|
+
return (text)=>text.split("").reverse().join("");
|
|
78
78
|
}
|
|
79
79
|
/**
|
|
80
80
|
* Returns the timeout for dry run mode.
|
|
81
81
|
* If dryRun is an object with timeout, returns it.
|
|
82
82
|
* Otherwise returns 0 (no delay).
|
|
83
83
|
*/ getDryRunTimeout() {
|
|
84
|
-
if (typeof this.config.dryRun ===
|
|
84
|
+
if (typeof this.config.dryRun === "object" && this.config.dryRun.timeout) {
|
|
85
85
|
return this.config.dryRun.timeout;
|
|
86
86
|
}
|
|
87
87
|
return 0;
|
|
@@ -89,7 +89,7 @@ Maintain any special formatting, placeholders, or variables within the values if
|
|
|
89
89
|
async createMockTranslation(content, transformer) {
|
|
90
90
|
try {
|
|
91
91
|
const mockTranslation = await this.transformObjectValues(content, async (value)=>{
|
|
92
|
-
if (typeof value ===
|
|
92
|
+
if (typeof value === "string" && value.trim()) return transformer(value);
|
|
93
93
|
return value;
|
|
94
94
|
});
|
|
95
95
|
return mockTranslation;
|
|
@@ -1,10 +1,33 @@
|
|
|
1
|
-
import type { BasePayload, TypedUser } from
|
|
1
|
+
import type { BasePayload, TypedUser } from "payload";
|
|
2
|
+
/**
|
|
3
|
+
* The request context an {@link AccessGuard} receives when deciding whether to
|
|
4
|
+
* allow a translation API call.
|
|
5
|
+
*/
|
|
2
6
|
export type AccessGuardRequest = {
|
|
7
|
+
/** Incoming request headers (e.g. for token/cookie checks). */
|
|
3
8
|
headers: Headers;
|
|
9
|
+
/** The authenticated user, or `null`/`undefined` if the request is anonymous. */
|
|
4
10
|
user?: TypedUser | null;
|
|
11
|
+
/** The Payload instance, for any DB/permission lookups the guard needs. */
|
|
5
12
|
payload: BasePayload;
|
|
6
13
|
};
|
|
14
|
+
/**
|
|
15
|
+
* Gate for the translation API endpoints. Provide one via `translatorPlugin({ access })`
|
|
16
|
+
* to control who may trigger translations; omit it to leave the endpoints open.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* const adminsOnly: AccessGuard = {
|
|
21
|
+
* check: ({ req }) => req.user?.role === 'admin',
|
|
22
|
+
* }
|
|
23
|
+
* translatorPlugin({ collections, translationProvider, runner, access: adminsOnly })
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
7
26
|
export interface AccessGuard {
|
|
27
|
+
/**
|
|
28
|
+
* Return `true` to allow the request, `false` to reject it with `403 Forbidden`.
|
|
29
|
+
* May be async (e.g. to query permissions).
|
|
30
|
+
*/
|
|
8
31
|
check<R extends AccessGuardRequest>({ req }: {
|
|
9
32
|
req: R;
|
|
10
33
|
}): Promise<boolean> | boolean;
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Gate for the translation API endpoints. Provide one via `translatorPlugin({ access })`
|
|
3
|
+
* to control who may trigger translations; omit it to leave the endpoints open.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* const adminsOnly: AccessGuard = {
|
|
8
|
+
* check: ({ req }) => req.user?.role === 'admin',
|
|
9
|
+
* }
|
|
10
|
+
* translatorPlugin({ collections, translationProvider, runner, access: adminsOnly })
|
|
11
|
+
* ```
|
|
12
|
+
*/ export { };
|
|
2
13
|
|
|
3
14
|
//# sourceMappingURL=AccessGuard.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@focus-reactive/payload-plugin-translator",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Translation plugin for Payload CMS 3.x. Automatically translate your localized content using any translation provider.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|