@focus-reactive/payload-plugin-translator 0.10.3 → 0.10.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.
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Namespace re-export: callers `import { Locales }` and use `Locales.dedupe(...)`,
3
+ * `Locales.resolveTargets(...)`, etc. Grouped this way (rather than loose named exports) so the domain
4
+ * reads at the call site; `export * as` keeps each member individually tree-shakeable.
5
+ */
6
+ export * as Locales from "./resolveLocales";
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Namespace re-export: callers `import { Locales }` and use `Locales.dedupe(...)`,
3
+ * `Locales.resolveTargets(...)`, etc. Grouped this way (rather than loose named exports) so the domain
4
+ * reads at the call site; `export * as` keeps each member individually tree-shakeable.
5
+ */ export * as Locales from "./resolveLocales";
6
+
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,59 @@
1
+ /**
2
+ * The single, canonical home for the locale-set invariants shared by every enqueue path: dedup,
3
+ * unknown-locale dropping, and source-locale exclusion. Previously each was hand-written in 2–3 places
4
+ * (the manual `/enqueue` resolver, the auto-translate config-time filter, and the auto-translate runtime
5
+ * task builder), which risked silent drift if one copy changed. These are the primitives; each path
6
+ * composes the ones it needs at whatever phase it runs (manual: one shot at request time; auto: dedup +
7
+ * unknown-drop at config time, source-exclusion per-document at runtime).
8
+ *
9
+ * Consumed as a namespace — the barrel re-exports this module as `Locales`, so call sites read
10
+ * `Locales.dedupe(...)` / `Locales.resolveTargets(...)`. Members are named for that dotted form (no
11
+ * `Locales` suffix), since the namespace carries the domain.
12
+ *
13
+ * Payload-free (plain `string[]` / `Set<string>`), so it stays a pure kernel usable from both the
14
+ * server features and the auto-translate module without pulling framework types in. Not part of the
15
+ * plugin's public API — an implementation detail of the enqueue paths.
16
+ *
17
+ * @internal
18
+ */
19
+ /** Whether a single locale code is one of the configured locales. The atomic "is this known?" check
20
+ * that {@link dropUnknown} is built on — shared so "unknown locale" means one thing everywhere. */
21
+ export declare function isKnown(locale: string, known: Set<string>): boolean;
22
+ /** Remove duplicate locale codes, preserving first-seen order. */
23
+ export declare function dedupe(locales: string[]): string[];
24
+ /** Split a locale list into those that are configured (`kept`) and those that are not (`dropped`),
25
+ * preserving order within each. */
26
+ export declare function dropUnknown(locales: string[], known: Set<string>): {
27
+ kept: string[];
28
+ dropped: string[];
29
+ };
30
+ /** Remove the source locale from a target list; report whether it was present (so the caller can note
31
+ * it was excluded). */
32
+ export declare function excludeSource(targets: string[], source: string): {
33
+ kept: string[];
34
+ wasPresent: boolean;
35
+ };
36
+ /**
37
+ * Resolved target locales for a manual enqueue, plus what was dropped so the handler can log precisely.
38
+ */
39
+ export type ResolvedTargets = {
40
+ /** The concrete locales to fan out to — de-duplicated, source excluded, unknown removed. */
41
+ targets: string[];
42
+ /** Requested locales that are not configured (dropped). */
43
+ droppedUnknown: string[];
44
+ /** Whether the source locale was requested as a target and excluded. */
45
+ droppedSource: boolean;
46
+ };
47
+ /**
48
+ * One-shot resolution for the manual enqueue path: coerce scalar→array, then dedup → exclude source →
49
+ * drop unknown, in that order. A pure composition of the primitives above.
50
+ *
51
+ * @param knownLocales - the configured locale codes. Never null: the caller must reject a
52
+ * localization-less config before reaching here (translating without localization has no valid target
53
+ * and would corrupt data), so "no localization" is not representable as an input.
54
+ */
55
+ export declare function resolveTargets(args: {
56
+ target_lng: string | string[];
57
+ source_lng: string;
58
+ knownLocales: Set<string>;
59
+ }): ResolvedTargets;
@@ -0,0 +1,68 @@
1
+ /**
2
+ * The single, canonical home for the locale-set invariants shared by every enqueue path: dedup,
3
+ * unknown-locale dropping, and source-locale exclusion. Previously each was hand-written in 2–3 places
4
+ * (the manual `/enqueue` resolver, the auto-translate config-time filter, and the auto-translate runtime
5
+ * task builder), which risked silent drift if one copy changed. These are the primitives; each path
6
+ * composes the ones it needs at whatever phase it runs (manual: one shot at request time; auto: dedup +
7
+ * unknown-drop at config time, source-exclusion per-document at runtime).
8
+ *
9
+ * Consumed as a namespace — the barrel re-exports this module as `Locales`, so call sites read
10
+ * `Locales.dedupe(...)` / `Locales.resolveTargets(...)`. Members are named for that dotted form (no
11
+ * `Locales` suffix), since the namespace carries the domain.
12
+ *
13
+ * Payload-free (plain `string[]` / `Set<string>`), so it stays a pure kernel usable from both the
14
+ * server features and the auto-translate module without pulling framework types in. Not part of the
15
+ * plugin's public API — an implementation detail of the enqueue paths.
16
+ *
17
+ * @internal
18
+ */ /** Whether a single locale code is one of the configured locales. The atomic "is this known?" check
19
+ * that {@link dropUnknown} is built on — shared so "unknown locale" means one thing everywhere. */ export function isKnown(locale, known) {
20
+ return known.has(locale);
21
+ }
22
+ /** Remove duplicate locale codes, preserving first-seen order. */ export function dedupe(locales) {
23
+ return [
24
+ ...new Set(locales)
25
+ ];
26
+ }
27
+ /** Split a locale list into those that are configured (`kept`) and those that are not (`dropped`),
28
+ * preserving order within each. */ export function dropUnknown(locales, known) {
29
+ const kept = [];
30
+ const dropped = [];
31
+ for (const locale of locales){
32
+ (isKnown(locale, known) ? kept : dropped).push(locale);
33
+ }
34
+ return {
35
+ kept,
36
+ dropped
37
+ };
38
+ }
39
+ /** Remove the source locale from a target list; report whether it was present (so the caller can note
40
+ * it was excluded). */ export function excludeSource(targets, source) {
41
+ const kept = targets.filter((target)=>target !== source);
42
+ return {
43
+ kept,
44
+ wasPresent: kept.length !== targets.length
45
+ };
46
+ }
47
+ /**
48
+ * One-shot resolution for the manual enqueue path: coerce scalar→array, then dedup → exclude source →
49
+ * drop unknown, in that order. A pure composition of the primitives above.
50
+ *
51
+ * @param knownLocales - the configured locale codes. Never null: the caller must reject a
52
+ * localization-less config before reaching here (translating without localization has no valid target
53
+ * and would corrupt data), so "no localization" is not representable as an input.
54
+ */ export function resolveTargets(args) {
55
+ const { target_lng, source_lng, knownLocales } = args;
56
+ const requested = Array.isArray(target_lng) ? target_lng : [
57
+ target_lng
58
+ ];
59
+ const { kept: withoutSource, wasPresent: droppedSource } = excludeSource(dedupe(requested), source_lng);
60
+ const { kept: targets, dropped: droppedUnknown } = dropUnknown(withoutSource, knownLocales);
61
+ return {
62
+ targets,
63
+ droppedUnknown,
64
+ droppedSource
65
+ };
66
+ }
67
+
68
+ //# sourceMappingURL=resolveLocales.js.map
@@ -1,8 +1,8 @@
1
1
  import { ServerResponse } from "../../shared";
2
2
  import { extractLocaleCodes } from "../../modules/auto-translate";
3
3
  import { isCollectionAvailable, getAllCollectionIds } from "../_lib/collection-utils";
4
+ import { Locales } from "../../../core/domain/locales";
4
5
  import { EnqueueInputSchema } from "./model";
5
- import { resolveTargetLocales } from "./resolveTargetLocales";
6
6
  /**
7
7
  * Enqueues translation tasks for documents
8
8
  */ export class EnqueueTranslationHandler {
@@ -26,7 +26,7 @@ import { resolveTargetLocales } from "./resolveTargetLocales";
26
26
  if (!knownLocales) return ServerResponse.badRequest("Localization is not enabled in this Payload config; there are no target locales to translate into");
27
27
  // Normalize the scalar-or-array target into the concrete locales to fan out to: de-dup, exclude the
28
28
  // source, and drop locales that are not configured.
29
- const { targets, droppedUnknown } = resolveTargetLocales({
29
+ const { targets, droppedUnknown } = Locales.resolveTargets({
30
30
  target_lng,
31
31
  source_lng,
32
32
  knownLocales
@@ -1,10 +1,9 @@
1
+ import { Locales } from "../../../core/domain/locales";
1
2
  /** Apply defaults to a raw config: strategy → "overwrite", debounce → 0. Duplicate target locales are
2
3
  * de-duplicated so a misconfigured `targets: ["de","de"]` never enqueues two racing jobs for the same
3
4
  * (document, locale) in one batch (the runner's supersession only dedupes against already-stored jobs). */ export function normalizeAutoTranslateConfig(config) {
4
5
  return {
5
- targets: [
6
- ...new Set(config.targets)
7
- ],
6
+ targets: Locales.dedupe(config.targets),
8
7
  strategy: config.strategy ?? "overwrite",
9
8
  debounceMs: config.debounceMs ?? 0,
10
9
  sourceLocale: config.sourceLocale
@@ -20,15 +19,15 @@
20
19
  * either error at the DB (Postgres locale enum) or write orphaned, invisible data (Mongo/SQLite). Pure:
21
20
  * returns a new policy and reports the drops; the caller (config-time wiring) emits the warning.
22
21
  */ export function filterPolicyToKnownLocales(policy, knownLocales) {
23
- const droppedTargets = policy.targets.filter((target)=>!knownLocales.has(target));
24
- const sourceUnknown = policy.sourceLocale !== undefined && !knownLocales.has(policy.sourceLocale);
22
+ const { kept, dropped } = Locales.dropUnknown(policy.targets, knownLocales);
23
+ const sourceUnknown = policy.sourceLocale !== undefined && !Locales.isKnown(policy.sourceLocale, knownLocales);
25
24
  return {
26
25
  policy: {
27
26
  ...policy,
28
- targets: policy.targets.filter((target)=>knownLocales.has(target)),
27
+ targets: kept,
29
28
  sourceLocale: sourceUnknown ? undefined : policy.sourceLocale
30
29
  },
31
- droppedTargets,
30
+ droppedTargets: dropped,
32
31
  droppedSourceLocale: sourceUnknown ? policy.sourceLocale ?? null : null
33
32
  };
34
33
  }
@@ -63,7 +62,7 @@
63
62
  const { policy, collectionSlug, documentId, sourceLocale, doc, hasDrafts, now } = args;
64
63
  const publishOnTranslation = resolvePublishOnTranslation(doc, hasDrafts);
65
64
  const waitUntil = policy.debounceMs > 0 ? new Date(now + policy.debounceMs) : undefined;
66
- return policy.targets.filter((target)=>target !== sourceLocale).map((target)=>({
65
+ return Locales.excludeSource(policy.targets, sourceLocale).kept.map((target)=>({
67
66
  collectionSlug,
68
67
  collectionId: documentId,
69
68
  sourceLng: sourceLocale,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@focus-reactive/payload-plugin-translator",
3
- "version": "0.10.3",
3
+ "version": "0.10.4",
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",
@@ -1,30 +0,0 @@
1
- /**
2
- * Resolved target locales for a manual enqueue, plus what was dropped so the handler can log precisely.
3
- */
4
- export type ResolvedTargetLocales = {
5
- /** The concrete locales to fan out to — de-duplicated, source excluded, unknown removed. */
6
- targets: string[];
7
- /** Requested locales that are not configured (dropped). */
8
- droppedUnknown: string[];
9
- /** Whether the source locale was requested as a target and excluded. */
10
- droppedSource: boolean;
11
- };
12
- /**
13
- * Normalize the enqueue `target_lng` input (scalar or array) into the concrete list of target locales
14
- * to translate into. Applies, in order: array-coercion, de-duplication (first-seen order preserved),
15
- * source-locale exclusion, and dropping unknown (unconfigured) locales.
16
- *
17
- * De-dup and unknown-dropping are the manual-enqueue counterparts of the auto-translate policy filter:
18
- * the runner only supersedes against already-stored jobs, so duplicates within one enqueue must be
19
- * collapsed here; and an unknown locale must never reach the pipeline — it burns a provider call and
20
- * either errors on a Postgres locale enum or writes orphaned, invisible data on Mongo/SQLite.
21
- *
22
- * @param knownLocales - the configured locale codes. Never null: the caller must reject a
23
- * localization-less config before reaching here (translating without localization has no valid
24
- * target and would corrupt data), so "no localization" is not representable as an input.
25
- */
26
- export declare function resolveTargetLocales(args: {
27
- target_lng: string | string[];
28
- source_lng: string;
29
- knownLocales: Set<string>;
30
- }): ResolvedTargetLocales;
@@ -1,35 +0,0 @@
1
- /**
2
- * Resolved target locales for a manual enqueue, plus what was dropped so the handler can log precisely.
3
- */ /**
4
- * Normalize the enqueue `target_lng` input (scalar or array) into the concrete list of target locales
5
- * to translate into. Applies, in order: array-coercion, de-duplication (first-seen order preserved),
6
- * source-locale exclusion, and dropping unknown (unconfigured) locales.
7
- *
8
- * De-dup and unknown-dropping are the manual-enqueue counterparts of the auto-translate policy filter:
9
- * the runner only supersedes against already-stored jobs, so duplicates within one enqueue must be
10
- * collapsed here; and an unknown locale must never reach the pipeline — it burns a provider call and
11
- * either errors on a Postgres locale enum or writes orphaned, invisible data on Mongo/SQLite.
12
- *
13
- * @param knownLocales - the configured locale codes. Never null: the caller must reject a
14
- * localization-less config before reaching here (translating without localization has no valid
15
- * target and would corrupt data), so "no localization" is not representable as an input.
16
- */ export function resolveTargetLocales(args) {
17
- const { target_lng, source_lng, knownLocales } = args;
18
- const requested = Array.isArray(target_lng) ? target_lng : [
19
- target_lng
20
- ];
21
- const deduped = [
22
- ...new Set(requested)
23
- ];
24
- const droppedSource = deduped.includes(source_lng);
25
- const withoutSource = deduped.filter((target)=>target !== source_lng);
26
- const droppedUnknown = withoutSource.filter((target)=>!knownLocales.has(target));
27
- const targets = withoutSource.filter((target)=>knownLocales.has(target));
28
- return {
29
- targets,
30
- droppedUnknown,
31
- droppedSource
32
- };
33
- }
34
-
35
- //# sourceMappingURL=resolveTargetLocales.js.map