@focus-reactive/payload-plugin-translator 0.4.0 → 0.5.1
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/client/shared/ui/Button/Button.d.ts +4 -4
- package/dist/client/shared/ui/Button/Button.js +18 -18
- package/dist/client/shared/ui/Button/styles.module.scss +1 -1
- package/dist/client/shared/ui/Popup/Popup.d.ts +10 -4
- package/dist/client/shared/ui/Popup/Popup.js +4 -3
- package/dist/client/shared/ui/Select/Select.d.ts +9 -7
- package/dist/client/shared/ui/Select/Select.js +18 -17
- package/dist/client/shared/ui/Select/styles.module.scss +5 -0
- 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/features/translate-field/resolveFieldSubtree.d.ts +31 -0
- package/dist/server/features/translate-field/resolveFieldSubtree.js +45 -0
- 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/stages/data-reconciler/DataReconciler.d.ts +3 -9
- package/dist/server/modules/translation-pipeline/stages/data-reconciler/DataReconciler.js +71 -78
- package/dist/server/modules/translation-pipeline/stages/field-collector/FieldChunkCollector.d.ts +11 -22
- package/dist/server/modules/translation-pipeline/stages/field-collector/FieldChunkCollector.js +85 -106
- 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/server/shared/field-traversal/findFieldByPath.d.ts +40 -0
- package/dist/server/shared/field-traversal/findFieldByPath.js +88 -0
- package/dist/server/shared/field-traversal/index.d.ts +5 -0
- package/dist/server/shared/field-traversal/index.js +5 -0
- package/dist/server/shared/field-traversal/kernel.d.ts +85 -0
- package/dist/server/shared/field-traversal/kernel.js +145 -0
- package/dist/server/shared/field-traversal/types.d.ts +191 -0
- package/dist/server/shared/field-traversal/types.js +41 -0
- package/dist/server/shared/field-traversal/walkFields.d.ts +51 -0
- package/dist/server/shared/field-traversal/walkFields.js +164 -0
- package/dist/server/shared/utils/filterLocalizedFields.d.ts +3 -3
- package/dist/server/shared/utils/filterLocalizedFields.js +52 -63
- package/dist/types/AccessGuard.d.ts +24 -1
- package/dist/types/AccessGuard.js +12 -1
- package/package.json +2 -2
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { classifyField, tabScopes } from "./kernel";
|
|
2
|
+
/**
|
|
3
|
+
* Internal engine backing {@link walkFields}. Methods return `true` to mean "stop requested —
|
|
4
|
+
* unwind and halt the entire walk". A class is used (over nested functions) because the three
|
|
5
|
+
* steps are mutually recursive; methods can reference each other without use-before-define
|
|
6
|
+
* ordering.
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/ class FieldTreeWalker {
|
|
10
|
+
walker;
|
|
11
|
+
constructor(walker){
|
|
12
|
+
this.walker = walker;
|
|
13
|
+
}
|
|
14
|
+
run(fields, root) {
|
|
15
|
+
const out = [];
|
|
16
|
+
if (this.level(fields, root, out)) return undefined;
|
|
17
|
+
return this.walker.combine({
|
|
18
|
+
kind: "root",
|
|
19
|
+
field: null
|
|
20
|
+
}, out, root);
|
|
21
|
+
}
|
|
22
|
+
/** Walk one data level (root, a group/tab body, or a list element), pushing child outputs into `out`. */ level(fields, cursor, out) {
|
|
23
|
+
for (const field of fields){
|
|
24
|
+
const structure = classifyField(field);
|
|
25
|
+
switch(structure.kind){
|
|
26
|
+
case "presentational":
|
|
27
|
+
break;
|
|
28
|
+
case "transparent":
|
|
29
|
+
if (this.level(structure.fields, cursor, out)) return true;
|
|
30
|
+
break;
|
|
31
|
+
case "tabs":
|
|
32
|
+
for (const scope of tabScopes(structure.field)){
|
|
33
|
+
if (scope.named) {
|
|
34
|
+
if (this.object(scope.tab, scope.tab.name, scope.tab.fields, cursor, out)) return true;
|
|
35
|
+
} else if (this.level(scope.fields, cursor, out)) {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
break;
|
|
40
|
+
case "group":
|
|
41
|
+
if (this.object(structure.field, structure.name, structure.fields, cursor, out)) return true;
|
|
42
|
+
break;
|
|
43
|
+
case "array":
|
|
44
|
+
case "blocks":
|
|
45
|
+
if (this.list(structure.field, structure.name, cursor, out)) return true;
|
|
46
|
+
break;
|
|
47
|
+
case "leaf":
|
|
48
|
+
{
|
|
49
|
+
const leafOut = this.walker.leaf(structure.field, cursor);
|
|
50
|
+
if (leafOut !== undefined) out.push({
|
|
51
|
+
key: structure.name,
|
|
52
|
+
out: leafOut
|
|
53
|
+
});
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
default:
|
|
57
|
+
{
|
|
58
|
+
// Exhaustiveness guard: if a new FieldStructure kind is added, this errors at compile time.
|
|
59
|
+
const exhaustive = structure;
|
|
60
|
+
throw new Error(`unhandled field structure: ${String(exhaustive)}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
/** Descend a single-object boundary (named group or named tab) and assemble it. */ object(field, key, childFields, cursor, out) {
|
|
67
|
+
const result = this.walker.enterObject(field, cursor);
|
|
68
|
+
if (result === "stop") return true;
|
|
69
|
+
if (result === "skip") return false;
|
|
70
|
+
const childOut = [];
|
|
71
|
+
if (this.level(childFields, result, childOut)) return true;
|
|
72
|
+
const assembled = this.walker.combine({
|
|
73
|
+
kind: "object",
|
|
74
|
+
field,
|
|
75
|
+
key
|
|
76
|
+
}, childOut, result);
|
|
77
|
+
if (assembled !== undefined) out.push({
|
|
78
|
+
key,
|
|
79
|
+
out: assembled
|
|
80
|
+
});
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
/** Descend an array/blocks boundary, assembling each element then the list itself. */ list(field, key, cursor, out) {
|
|
84
|
+
const result = this.walker.enterList(field, cursor);
|
|
85
|
+
if (result === "stop") return true;
|
|
86
|
+
if (result === "skip") return false;
|
|
87
|
+
const elements = [];
|
|
88
|
+
for (const child of result){
|
|
89
|
+
const childOut = [];
|
|
90
|
+
if (this.level(child.fields, child.cursor, childOut)) return true;
|
|
91
|
+
const elementOut = this.walker.combine({
|
|
92
|
+
kind: "element",
|
|
93
|
+
field,
|
|
94
|
+
key: child.key
|
|
95
|
+
}, childOut, child.cursor);
|
|
96
|
+
if (elementOut !== undefined) elements.push({
|
|
97
|
+
key: child.key,
|
|
98
|
+
out: elementOut
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
const listOut = this.walker.combine({
|
|
102
|
+
kind: "list",
|
|
103
|
+
field,
|
|
104
|
+
key
|
|
105
|
+
}, elements, cursor);
|
|
106
|
+
if (listOut !== undefined) out.push({
|
|
107
|
+
key,
|
|
108
|
+
out: listOut
|
|
109
|
+
});
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Depth-first walk of a Payload field **schema**, driving a caller-supplied
|
|
115
|
+
* {@link FieldWalker}. The single traversal engine this package's data operations build on
|
|
116
|
+
* (filtering, reconciling, collecting, navigating).
|
|
117
|
+
*
|
|
118
|
+
* The engine owns structural dispatch (via {@link classifyField} / {@link tabScopes}) and the
|
|
119
|
+
* recursion; the caller owns the **data** through the opaque `Cursor` and decides what to
|
|
120
|
+
* produce. The engine never reads the cursor — so the caller can thread one, two, or more
|
|
121
|
+
* parallel data trees (plus a path) inside it. Containers are assembled bottom-up via
|
|
122
|
+
* `combine`, after their children.
|
|
123
|
+
*
|
|
124
|
+
* @template Cursor - The caller's data position threaded through the walk (e.g. the current
|
|
125
|
+
* data object, a `{ source, target }` pair, plus a path). Constrained to `object` so a cursor
|
|
126
|
+
* can never collide with a {@link WalkSignal} string (`'skip'`/`'stop'`).
|
|
127
|
+
* @template Out - What the walker produces per node and assembles per container (e.g. a
|
|
128
|
+
* rebuilt data subtree, or `void` for a collect-only walk).
|
|
129
|
+
*
|
|
130
|
+
* @param fields - The schema to walk (a collection/global/group `fields` array).
|
|
131
|
+
* @param root - The initial `Cursor` paired with the top-level `fields`.
|
|
132
|
+
* @param walker - The behavior to drive: `enterObject` / `enterList` derive child cursors (or
|
|
133
|
+
* return a {@link WalkSignal} to `'skip'` a branch or `'stop'` the whole walk), `leaf`
|
|
134
|
+
* produces a value per data-affecting leaf, and `combine` assembles each container from its
|
|
135
|
+
* children.
|
|
136
|
+
* @returns The root `combine` output. `undefined` if the walk was halted by `'stop'` before the
|
|
137
|
+
* root assembled, OR if the root `combine` itself returned `undefined` (e.g. a collect-only
|
|
138
|
+
* walker). To distinguish "stopped" from "empty result", track it via the cursor, not this value.
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* Keep only localized leaves and rebuild the data tree (a "filter" walk):
|
|
142
|
+
* ```ts
|
|
143
|
+
* type Cursor = { data: Record<string, unknown> };
|
|
144
|
+
*
|
|
145
|
+
* const filtered = walkFields<Cursor, unknown>(schema, { data }, {
|
|
146
|
+
* enterObject: (field, c) =>
|
|
147
|
+
* isRecord(c.data[field.name]) ? { data: c.data[field.name] } : "skip",
|
|
148
|
+
* enterList: (field, c) => toItemCursors(field, c), // one ChildCursor per element
|
|
149
|
+
* leaf: (field, c) => (field.localized ? c.data[field.name] : undefined),
|
|
150
|
+
* combine: (container, children) => {
|
|
151
|
+
* if (children.length === 0) return undefined; // drop empty containers
|
|
152
|
+
* if (container.kind === "list") return children.map((ch) => ch.out);
|
|
153
|
+
* return Object.fromEntries(children.map((ch) => [ch.key, ch.out]));
|
|
154
|
+
* },
|
|
155
|
+
* });
|
|
156
|
+
* ```
|
|
157
|
+
*
|
|
158
|
+
* @see {@link FieldWalker} for the full visitor contract and the caller shapes it subsumes.
|
|
159
|
+
* @public
|
|
160
|
+
*/ export function walkFields(fields, root, walker) {
|
|
161
|
+
return new FieldTreeWalker(walker).run(fields, root);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
//# sourceMappingURL=walkFields.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { Field } from
|
|
1
|
+
import type { Field } from "payload";
|
|
2
2
|
/**
|
|
3
|
-
* Filters data to keep only translatable localized fields
|
|
4
|
-
*
|
|
3
|
+
* Filters data to keep only translatable localized fields, recursively for container fields
|
|
4
|
+
* (group, array, blocks, named tabs). Built on the shared {@link walkFields} engine.
|
|
5
5
|
*
|
|
6
6
|
* @param schema - Payload field schema (original, not sanitized)
|
|
7
7
|
* @param data - Document data to filter
|
|
@@ -1,72 +1,61 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { isObject } from
|
|
4
|
-
import { isEmpty } from './isEmpty';
|
|
1
|
+
import { resolveBlockFields, walkFields } from "../field-traversal";
|
|
2
|
+
import { isLocalizedField, isTranslatableField } from "../guards";
|
|
3
|
+
import { isObject } from "./isObject";
|
|
5
4
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* Filter walker: keeps only translatable, localized leaves, rebuilding the surrounding
|
|
6
|
+
* object/array/blocks structure and dropping any container left empty. `id` (array/block
|
|
7
|
+
* elements) and `blockType` (block elements) are preserved since they aren't schema fields.
|
|
8
|
+
*/ const filterWalker = {
|
|
9
|
+
enterObject (field, cursor) {
|
|
10
|
+
const value = cursor.data[field.name];
|
|
11
|
+
return isObject(value) ? {
|
|
12
|
+
data: value
|
|
13
|
+
} : "skip";
|
|
14
|
+
},
|
|
15
|
+
enterList (field, cursor) {
|
|
16
|
+
const value = cursor.data[field.name];
|
|
17
|
+
if (!Array.isArray(value)) return "skip";
|
|
18
|
+
const children = [];
|
|
19
|
+
value.forEach((item, index)=>{
|
|
20
|
+
if (!isObject(item)) return; // drop non-object elements
|
|
21
|
+
const fields = field.type === "blocks" ? resolveBlockFields(field, item) : field.fields;
|
|
22
|
+
if (fields) children.push({
|
|
23
|
+
cursor: {
|
|
24
|
+
data: item
|
|
25
|
+
},
|
|
26
|
+
fields,
|
|
27
|
+
key: index
|
|
28
|
+
}); // unknown blockType → fields null → drop
|
|
29
|
+
});
|
|
30
|
+
return children;
|
|
31
|
+
},
|
|
32
|
+
leaf (field, cursor) {
|
|
33
|
+
return isTranslatableField(field) && isLocalizedField(field) ? cursor.data[field.name] : undefined;
|
|
34
|
+
},
|
|
35
|
+
combine (container, children, cursor) {
|
|
36
|
+
if (children.length === 0) return undefined; // drop empty containers/lists
|
|
37
|
+
if (container.kind === "list") return children.map((child)=>child.out);
|
|
38
|
+
const result = {};
|
|
39
|
+
for (const child of children)result[child.key] = child.out;
|
|
40
|
+
if (container.kind === "element") {
|
|
41
|
+
const item = cursor.data;
|
|
42
|
+
if (item.id !== undefined) result.id = item.id;
|
|
43
|
+
if (container.field.type === "blocks") result.blockType = item.blockType;
|
|
44
|
+
}
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Filters data to keep only translatable localized fields, recursively for container fields
|
|
50
|
+
* (group, array, blocks, named tabs). Built on the shared {@link walkFields} engine.
|
|
8
51
|
*
|
|
9
52
|
* @param schema - Payload field schema (original, not sanitized)
|
|
10
53
|
* @param data - Document data to filter
|
|
11
54
|
* @returns Filtered data containing only translatable localized fields
|
|
12
55
|
*/ export function filterLocalizedFields(schema, data) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
for (const tab of field.tabs){
|
|
17
|
-
if (hasFields(tab)) Object.assign(result, filterLocalizedFields(tab.fields, data));
|
|
18
|
-
}
|
|
19
|
-
continue;
|
|
20
|
-
}
|
|
21
|
-
if (!fieldAffectsData(field)) {
|
|
22
|
-
if (hasFields(field)) Object.assign(result, filterLocalizedFields(field.fields, data));
|
|
23
|
-
continue;
|
|
24
|
-
}
|
|
25
|
-
const value = data[field.name];
|
|
26
|
-
if (value === undefined) continue;
|
|
27
|
-
if (fieldIsGroupType(field) && isObject(value)) {
|
|
28
|
-
const filtered = filterLocalizedFields(field.fields, value);
|
|
29
|
-
if (!isEmpty(filtered)) result[field.name] = filtered;
|
|
30
|
-
continue;
|
|
31
|
-
}
|
|
32
|
-
if (fieldIsArrayType(field) && Array.isArray(value)) {
|
|
33
|
-
const filteredArray = value.map((item)=>{
|
|
34
|
-
if (isObject(item)) {
|
|
35
|
-
const filtered = filterLocalizedFields(field.fields, item);
|
|
36
|
-
if (!isEmpty(filtered)) return {
|
|
37
|
-
...filtered,
|
|
38
|
-
id: item.id
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
return null;
|
|
42
|
-
}).filter(Boolean);
|
|
43
|
-
if (!isEmpty(filteredArray)) result[field.name] = filteredArray;
|
|
44
|
-
continue;
|
|
45
|
-
}
|
|
46
|
-
if (fieldIsBlockType(field) && Array.isArray(value)) {
|
|
47
|
-
const filteredBlocks = value.map((item)=>{
|
|
48
|
-
if (isBlockItem(item)) {
|
|
49
|
-
const block = field.blocks.find((b)=>b.slug === item.blockType);
|
|
50
|
-
if (block) {
|
|
51
|
-
const filtered = filterLocalizedFields(block.fields, item);
|
|
52
|
-
if (!isEmpty(filtered)) return {
|
|
53
|
-
...filtered,
|
|
54
|
-
blockType: item.blockType,
|
|
55
|
-
id: item.id
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
return null;
|
|
60
|
-
}).filter(Boolean);
|
|
61
|
-
if (!isEmpty(filteredBlocks)) result[field.name] = filteredBlocks;
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
if (isTranslatableField(field) && isLocalizedField(field)) {
|
|
65
|
-
result[field.name] = value;
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return result;
|
|
56
|
+
return walkFields(schema, {
|
|
57
|
+
data
|
|
58
|
+
}, filterWalker) ?? {};
|
|
70
59
|
}
|
|
71
60
|
|
|
72
61
|
//# sourceMappingURL=filterLocalizedFields.js.map
|
|
@@ -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.1",
|
|
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",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"lint:fix": "ultracite fix",
|
|
56
56
|
"test": "vitest run",
|
|
57
57
|
"test:watch": "vitest",
|
|
58
|
-
"check-types": "tsgo --noEmit"
|
|
58
|
+
"check-types": "tsgo --noEmit -p tsconfig.check.json"
|
|
59
59
|
},
|
|
60
60
|
"peerDependencies": {
|
|
61
61
|
"@payloadcms/richtext-lexical": "^3.76.0",
|