@purposeinplay/payload-ai-translate 0.1.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/LICENSE +21 -0
- package/README.md +714 -0
- package/dist/alerts-collection.d.ts +21 -0
- package/dist/alerts-collection.js +159 -0
- package/dist/api.d.ts +4 -0
- package/dist/api.js +918 -0
- package/dist/bulk-translate-batches-collection.d.ts +29 -0
- package/dist/bulk-translate-batches-collection.js +404 -0
- package/dist/bulk-translate-units-collection.d.ts +35 -0
- package/dist/bulk-translate-units-collection.js +310 -0
- package/dist/client/estimated-cost-cell.d.ts +6 -0
- package/dist/client/estimated-cost-cell.js +12 -0
- package/dist/client/excluded-fields-field.d.ts +45 -0
- package/dist/client/excluded-fields-field.js +553 -0
- package/dist/client/field-translate-button.d.ts +6 -0
- package/dist/client/field-translate-button.js +199 -0
- package/dist/client/index.d.ts +6 -0
- package/dist/client/index.js +6 -0
- package/dist/client/lib/use-global-kill-switches.d.ts +20 -0
- package/dist/client/lib/use-global-kill-switches.js +58 -0
- package/dist/client/translate-button.d.ts +2 -0
- package/dist/client/translate-button.js +228 -0
- package/dist/client/translate-modal.d.ts +16 -0
- package/dist/client/translate-modal.js +549 -0
- package/dist/client/translation-progress.d.ts +10 -0
- package/dist/client/translation-progress.js +297 -0
- package/dist/components/TranslationNavGroup.d.ts +45 -0
- package/dist/components/TranslationNavGroup.js +104 -0
- package/dist/defaults.d.ts +11 -0
- package/dist/defaults.js +16 -0
- package/dist/endpoints/client-config.d.ts +44 -0
- package/dist/endpoints/client-config.js +145 -0
- package/dist/endpoints/estimate.d.ts +5 -0
- package/dist/endpoints/estimate.js +237 -0
- package/dist/endpoints/progress.d.ts +2 -0
- package/dist/endpoints/progress.js +314 -0
- package/dist/endpoints/translate.d.ts +11 -0
- package/dist/endpoints/translate.js +376 -0
- package/dist/endpoints/translation-hub/_helpers.d.ts +140 -0
- package/dist/endpoints/translation-hub/_helpers.js +297 -0
- package/dist/endpoints/translation-hub/active.d.ts +21 -0
- package/dist/endpoints/translation-hub/active.js +220 -0
- package/dist/endpoints/translation-hub/cancel.d.ts +22 -0
- package/dist/endpoints/translation-hub/cancel.js +233 -0
- package/dist/endpoints/translation-hub/enqueue.d.ts +70 -0
- package/dist/endpoints/translation-hub/enqueue.js +529 -0
- package/dist/endpoints/translation-hub/failures.d.ts +12 -0
- package/dist/endpoints/translation-hub/failures.js +67 -0
- package/dist/endpoints/translation-hub/force-reset.d.ts +20 -0
- package/dist/endpoints/translation-hub/force-reset.js +144 -0
- package/dist/endpoints/translation-hub/index.d.ts +21 -0
- package/dist/endpoints/translation-hub/index.js +20 -0
- package/dist/endpoints/translation-hub/list.d.ts +40 -0
- package/dist/endpoints/translation-hub/list.js +182 -0
- package/dist/endpoints/translation-hub/preflight.d.ts +19 -0
- package/dist/endpoints/translation-hub/preflight.js +141 -0
- package/dist/endpoints/translation-hub/retry-failed.d.ts +38 -0
- package/dist/endpoints/translation-hub/retry-failed.js +235 -0
- package/dist/endpoints/translation-hub/revert.d.ts +88 -0
- package/dist/endpoints/translation-hub/revert.js +405 -0
- package/dist/endpoints/translation-hub/status.d.ts +45 -0
- package/dist/endpoints/translation-hub/status.js +391 -0
- package/dist/endpoints/translation-hub/usage-summary.d.ts +114 -0
- package/dist/endpoints/translation-hub/usage-summary.js +481 -0
- package/dist/exports/client.d.ts +6 -0
- package/dist/exports/client.js +6 -0
- package/dist/exports/components.d.ts +6 -0
- package/dist/exports/components.js +5 -0
- package/dist/exports/index.d.ts +8 -0
- package/dist/exports/index.js +7 -0
- package/dist/exports/providers.d.ts +9 -0
- package/dist/exports/providers.js +5 -0
- package/dist/exports/views-client.d.ts +23 -0
- package/dist/exports/views-client.js +22 -0
- package/dist/exports/views.d.ts +30 -0
- package/dist/exports/views.js +29 -0
- package/dist/hooks/after-change-global.d.ts +4 -0
- package/dist/hooks/after-change-global.js +109 -0
- package/dist/hooks/after-change.d.ts +16 -0
- package/dist/hooks/after-change.js +205 -0
- package/dist/hooks/after-delete.d.ts +30 -0
- package/dist/hooks/after-delete.js +95 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/jobs-collection.d.ts +17 -0
- package/dist/jobs-collection.js +139 -0
- package/dist/lexical/classifier.d.ts +3 -0
- package/dist/lexical/classifier.js +108 -0
- package/dist/lexical/deserializer.d.ts +4 -0
- package/dist/lexical/deserializer.js +263 -0
- package/dist/lexical/placeholder-integrity.d.ts +6 -0
- package/dist/lexical/placeholder-integrity.js +21 -0
- package/dist/lexical/placeholders.d.ts +21 -0
- package/dist/lexical/placeholders.js +117 -0
- package/dist/lexical/serializer.d.ts +21 -0
- package/dist/lexical/serializer.js +233 -0
- package/dist/lexical/types.d.ts +32 -0
- package/dist/lexical/types.js +1 -0
- package/dist/lib/auth-diagnostics.d.ts +14 -0
- package/dist/lib/auth-diagnostics.js +19 -0
- package/dist/lib/batch-counts.d.ts +58 -0
- package/dist/lib/batch-counts.js +105 -0
- package/dist/lib/bulk-translate-migrations.d.ts +92 -0
- package/dist/lib/bulk-translate-migrations.js +153 -0
- package/dist/lib/coalescing-queue.d.ts +38 -0
- package/dist/lib/coalescing-queue.js +69 -0
- package/dist/lib/content-extractor.d.ts +16 -0
- package/dist/lib/content-extractor.js +410 -0
- package/dist/lib/content-hash.d.ts +1 -0
- package/dist/lib/content-hash.js +19 -0
- package/dist/lib/content-patcher.d.ts +15 -0
- package/dist/lib/content-patcher.js +293 -0
- package/dist/lib/cost-guards.d.ts +2 -0
- package/dist/lib/cost-guards.js +18 -0
- package/dist/lib/daily-spend-cap.d.ts +58 -0
- package/dist/lib/daily-spend-cap.js +233 -0
- package/dist/lib/effective-locales.d.ts +181 -0
- package/dist/lib/effective-locales.js +302 -0
- package/dist/lib/error-messages.d.ts +245 -0
- package/dist/lib/error-messages.js +626 -0
- package/dist/lib/events.d.ts +39 -0
- package/dist/lib/events.js +146 -0
- package/dist/lib/exclude-fields.d.ts +3 -0
- package/dist/lib/exclude-fields.js +64 -0
- package/dist/lib/field-breadcrumb.d.ts +31 -0
- package/dist/lib/field-breadcrumb.js +227 -0
- package/dist/lib/field-diff.d.ts +1 -0
- package/dist/lib/field-diff.js +25 -0
- package/dist/lib/field-empty.d.ts +2 -0
- package/dist/lib/field-empty.js +68 -0
- package/dist/lib/field-resolver.d.ts +3 -0
- package/dist/lib/field-resolver.js +164 -0
- package/dist/lib/group-soft-skips.d.ts +39 -0
- package/dist/lib/group-soft-skips.js +45 -0
- package/dist/lib/locale-merge.d.ts +44 -0
- package/dist/lib/locale-merge.js +357 -0
- package/dist/lib/locale-row-check.d.ts +30 -0
- package/dist/lib/locale-row-check.js +64 -0
- package/dist/lib/logger.d.ts +74 -0
- package/dist/lib/logger.js +97 -0
- package/dist/lib/manual-edit-guard.d.ts +128 -0
- package/dist/lib/manual-edit-guard.js +393 -0
- package/dist/lib/output-validation.d.ts +48 -0
- package/dist/lib/output-validation.js +148 -0
- package/dist/lib/payload-read.d.ts +16 -0
- package/dist/lib/payload-read.js +51 -0
- package/dist/lib/per-doc-claim.d.ts +90 -0
- package/dist/lib/per-doc-claim.js +140 -0
- package/dist/lib/per-doc-lock.d.ts +94 -0
- package/dist/lib/per-doc-lock.js +119 -0
- package/dist/lib/persist-usage.d.ts +91 -0
- package/dist/lib/persist-usage.js +116 -0
- package/dist/lib/progress-store.d.ts +103 -0
- package/dist/lib/progress-store.js +314 -0
- package/dist/lib/rate-limiter.d.ts +3 -0
- package/dist/lib/rate-limiter.js +53 -0
- package/dist/lib/snapshot-select.d.ts +43 -0
- package/dist/lib/snapshot-select.js +108 -0
- package/dist/lib/translate-prompt.d.ts +31 -0
- package/dist/lib/translate-prompt.js +66 -0
- package/dist/lib/translation-token-bucket.d.ts +57 -0
- package/dist/lib/translation-token-bucket.js +365 -0
- package/dist/lib/truncate-source-value.d.ts +1 -0
- package/dist/lib/truncate-source-value.js +27 -0
- package/dist/manual-edit-collection.d.ts +22 -0
- package/dist/manual-edit-collection.js +124 -0
- package/dist/plugin.d.ts +3 -0
- package/dist/plugin.js +934 -0
- package/dist/providers/ai-sdk-adapter.d.ts +35 -0
- package/dist/providers/ai-sdk-adapter.js +100 -0
- package/dist/providers/anthropic.d.ts +31 -0
- package/dist/providers/anthropic.js +66 -0
- package/dist/providers/custom.d.ts +36 -0
- package/dist/providers/custom.js +24 -0
- package/dist/providers/gemini.d.ts +20 -0
- package/dist/providers/gemini.js +48 -0
- package/dist/providers/mock.d.ts +2 -0
- package/dist/providers/mock.js +29 -0
- package/dist/providers/openai.d.ts +28 -0
- package/dist/providers/openai.js +69 -0
- package/dist/settings-global.d.ts +74 -0
- package/dist/settings-global.js +216 -0
- package/dist/tasks/bulk-translate-coordinator.d.ts +115 -0
- package/dist/tasks/bulk-translate-coordinator.js +708 -0
- package/dist/tasks/bulk-translate-doc-task.d.ts +142 -0
- package/dist/tasks/bulk-translate-doc-task.js +1000 -0
- package/dist/tasks/bulk-translate-janitor.d.ts +87 -0
- package/dist/tasks/bulk-translate-janitor.js +311 -0
- package/dist/tasks/translate-job-task.d.ts +51 -0
- package/dist/tasks/translate-job-task.js +154 -0
- package/dist/translate.d.ts +113 -0
- package/dist/translate.js +911 -0
- package/dist/translation-daily-spend-collection.d.ts +24 -0
- package/dist/translation-daily-spend-collection.js +133 -0
- package/dist/translation-rate-limits-collection.d.ts +30 -0
- package/dist/translation-rate-limits-collection.js +144 -0
- package/dist/types.d.ts +672 -0
- package/dist/types.js +1 -0
- package/dist/usage-collection.d.ts +14 -0
- package/dist/usage-collection.js +377 -0
- package/dist/views/BulkRunsHub/BatchRow.d.ts +32 -0
- package/dist/views/BulkRunsHub/BatchRow.js +1222 -0
- package/dist/views/BulkRunsHub/BucketRow.d.ts +62 -0
- package/dist/views/BulkRunsHub/BucketRow.js +982 -0
- package/dist/views/BulkRunsHub/BulkRunsHub.client.d.ts +18 -0
- package/dist/views/BulkRunsHub/BulkRunsHub.client.js +331 -0
- package/dist/views/BulkRunsHub/EmptyState.d.ts +6 -0
- package/dist/views/BulkRunsHub/EmptyState.js +64 -0
- package/dist/views/BulkRunsHub/FilterBar.d.ts +16 -0
- package/dist/views/BulkRunsHub/FilterBar.js +284 -0
- package/dist/views/BulkRunsHub/InFlightBanner.d.ts +14 -0
- package/dist/views/BulkRunsHub/InFlightBanner.js +59 -0
- package/dist/views/BulkRunsHub/StatusBadge.d.ts +64 -0
- package/dist/views/BulkRunsHub/StatusBadge.js +248 -0
- package/dist/views/BulkRunsHub/SummaryStrip.d.ts +22 -0
- package/dist/views/BulkRunsHub/SummaryStrip.js +249 -0
- package/dist/views/BulkRunsHub/bucket-grouping.d.ts +200 -0
- package/dist/views/BulkRunsHub/bucket-grouping.js +344 -0
- package/dist/views/BulkRunsHub/bucketFailureSummary.d.ts +9 -0
- package/dist/views/BulkRunsHub/bucketFailureSummary.js +36 -0
- package/dist/views/BulkRunsHub/dedupedStatusFetch.d.ts +5 -0
- package/dist/views/BulkRunsHub/dedupedStatusFetch.js +45 -0
- package/dist/views/BulkRunsHub/index.d.ts +17 -0
- package/dist/views/BulkRunsHub/index.js +80 -0
- package/dist/views/BulkRunsHub/urlFilters.d.ts +14 -0
- package/dist/views/BulkRunsHub/urlFilters.js +50 -0
- package/dist/views/BulkRunsHub/useBulkRunsList.d.ts +26 -0
- package/dist/views/BulkRunsHub/useBulkRunsList.js +204 -0
- package/dist/views/BulkRunsHub/useUrlFilters.d.ts +10 -0
- package/dist/views/BulkRunsHub/useUrlFilters.js +88 -0
- package/dist/views/TranslationHub/ActiveJobs.d.ts +6 -0
- package/dist/views/TranslationHub/ActiveJobs.js +320 -0
- package/dist/views/TranslationHub/AdvancedPanel.d.ts +17 -0
- package/dist/views/TranslationHub/AdvancedPanel.js +996 -0
- package/dist/views/TranslationHub/AlertBanner.d.ts +6 -0
- package/dist/views/TranslationHub/AlertBanner.js +568 -0
- package/dist/views/TranslationHub/AuditPanel.d.ts +6 -0
- package/dist/views/TranslationHub/AuditPanel.helpers.d.ts +44 -0
- package/dist/views/TranslationHub/AuditPanel.helpers.js +71 -0
- package/dist/views/TranslationHub/AuditPanel.js +1367 -0
- package/dist/views/TranslationHub/BulkTranslate.types.d.ts +242 -0
- package/dist/views/TranslationHub/BulkTranslate.types.js +36 -0
- package/dist/views/TranslationHub/BulkTranslateFailureDrawer.d.ts +19 -0
- package/dist/views/TranslationHub/BulkTranslateFailureDrawer.js +332 -0
- package/dist/views/TranslationHub/BulkTranslateMonitor.d.ts +28 -0
- package/dist/views/TranslationHub/BulkTranslateMonitor.js +305 -0
- package/dist/views/TranslationHub/BulkTranslateNarrowViewportBanner.d.ts +3 -0
- package/dist/views/TranslationHub/BulkTranslateNarrowViewportBanner.js +42 -0
- package/dist/views/TranslationHub/BulkTranslatePostEnqueueTransition.d.ts +26 -0
- package/dist/views/TranslationHub/BulkTranslatePostEnqueueTransition.js +95 -0
- package/dist/views/TranslationHub/BulkTranslatePreflightModal.d.ts +22 -0
- package/dist/views/TranslationHub/BulkTranslatePreflightModal.js +879 -0
- package/dist/views/TranslationHub/BulkTranslateTerminalCard.d.ts +29 -0
- package/dist/views/TranslationHub/BulkTranslateTerminalCard.js +445 -0
- package/dist/views/TranslationHub/BulkTranslateTrigger.d.ts +66 -0
- package/dist/views/TranslationHub/BulkTranslateTrigger.js +161 -0
- package/dist/views/TranslationHub/EditorRecentRunsPanel.d.ts +33 -0
- package/dist/views/TranslationHub/EditorRecentRunsPanel.js +290 -0
- package/dist/views/TranslationHub/Hub.client.d.ts +74 -0
- package/dist/views/TranslationHub/Hub.client.js +357 -0
- package/dist/views/TranslationHub/ModelCombobox.d.ts +14 -0
- package/dist/views/TranslationHub/ModelCombobox.js +415 -0
- package/dist/views/TranslationHub/PerCollectionConfig.d.ts +10 -0
- package/dist/views/TranslationHub/PerCollectionConfig.helpers.d.ts +16 -0
- package/dist/views/TranslationHub/PerCollectionConfig.helpers.js +19 -0
- package/dist/views/TranslationHub/PerCollectionConfig.js +759 -0
- package/dist/views/TranslationHub/SettingsRail.d.ts +11 -0
- package/dist/views/TranslationHub/SettingsRail.js +382 -0
- package/dist/views/TranslationHub/StatusStrip.d.ts +6 -0
- package/dist/views/TranslationHub/StatusStrip.js +451 -0
- package/dist/views/TranslationHub/UsageTable.d.ts +6 -0
- package/dist/views/TranslationHub/UsageTable.helpers.d.ts +69 -0
- package/dist/views/TranslationHub/UsageTable.helpers.js +49 -0
- package/dist/views/TranslationHub/UsageTable.js +1240 -0
- package/dist/views/TranslationHub/alertGrouping.d.ts +70 -0
- package/dist/views/TranslationHub/alertGrouping.js +99 -0
- package/dist/views/TranslationHub/index.d.ts +20 -0
- package/dist/views/TranslationHub/index.js +109 -0
- package/dist/views/TranslationHub/tabNavigation.d.ts +53 -0
- package/dist/views/TranslationHub/tabNavigation.js +74 -0
- package/dist/views/TranslationHub/terminalBannerVisibility.d.ts +33 -0
- package/dist/views/TranslationHub/terminalBannerVisibility.js +124 -0
- package/dist/views/TranslationHub/useBulkTranslateActive.d.ts +49 -0
- package/dist/views/TranslationHub/useBulkTranslateActive.js +251 -0
- package/dist/views/TranslationHub/useFocusTrap.d.ts +6 -0
- package/dist/views/TranslationHub/useFocusTrap.js +81 -0
- package/dist/views/TranslationHub/useTranslationHubUsageSummary.d.ts +77 -0
- package/dist/views/TranslationHub/useTranslationHubUsageSummary.js +267 -0
- package/dist/views/shared/EditorError.d.ts +97 -0
- package/dist/views/shared/EditorError.js +205 -0
- package/dist/views/shared/ModelCell.d.ts +18 -0
- package/dist/views/shared/ModelCell.js +31 -0
- package/dist/views/shared/docHref.d.ts +16 -0
- package/dist/views/shared/docHref.js +26 -0
- package/dist/views/shared/fetch-error-body.d.ts +25 -0
- package/dist/views/shared/fetch-error-body.js +42 -0
- package/dist/views/shared/filterPillStyle.d.ts +35 -0
- package/dist/views/shared/filterPillStyle.js +40 -0
- package/dist/views/shared/format.d.ts +75 -0
- package/dist/views/shared/format.js +131 -0
- package/package.json +141 -0
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
export const DEFAULT_BULK_TRANSLATE_UNITS_COLLECTION_SLUG = 'bulk-translate-units';
|
|
2
|
+
/**
|
|
3
|
+
* Per-(collection, documentId, locale) work item for a bulk translate
|
|
4
|
+
* batch. Plugin v1.2.0+.
|
|
5
|
+
*
|
|
6
|
+
* Source of truth for unit-level state in a bulk run. Read by:
|
|
7
|
+
* 1. The `shouldSkipDocument`-equivalent check at task-entry and the
|
|
8
|
+
* per-doc retry endpoint (Decision #19 v2): "is there already a
|
|
9
|
+
* pending/running unit for this (collection, doc, locale) in some
|
|
10
|
+
* other in-flight batch?". A partial unique index on
|
|
11
|
+
* `(collection, document_id, locale) WHERE status IN
|
|
12
|
+
* ('pending','running')` enforces the invariant in Postgres
|
|
13
|
+
* regardless of application-layer races (F-DA-TOCTOU).
|
|
14
|
+
* 2. The revert action: paginates over `success` units, reads
|
|
15
|
+
* `preRunSnapshot` + `schemaHash`, restores the pre-run value.
|
|
16
|
+
* 3. The Hub monitor UI's drill-down view of failed units.
|
|
17
|
+
*
|
|
18
|
+
* `preRunSnapshot` is jsonb and stores ONLY the localized translatable
|
|
19
|
+
* fields, captured via Payload `select` (Decision #30 + F-SEC-SNAPSHOT).
|
|
20
|
+
* Never the full document — that would leak `password` / `email` /
|
|
21
|
+
* `roles` and other `excludeFields` content into a queryable
|
|
22
|
+
* collection.
|
|
23
|
+
*
|
|
24
|
+
* Read access is locked to `admin` role only (Decision #31, unchanged
|
|
25
|
+
* in 1.2.8). The snapshot column contains pre-translation source
|
|
26
|
+
* content which, even scoped to translatable fields, may include
|
|
27
|
+
* unpublished drafts editor-role users should not see. Editors who
|
|
28
|
+
* need unit-level drill-down (e.g., per-locale outcomes, failure
|
|
29
|
+
* reasons) read through the shaped `/api/translation-hub/bulk-translate/:id`
|
|
30
|
+
* (`status` endpoint, 1.2.8 opened to editor+admin) and `/failures`
|
|
31
|
+
* endpoints — those serialize a redacted view that excludes
|
|
32
|
+
* `preRunSnapshot` entirely.
|
|
33
|
+
*/ export function createBulkTranslateUnitsCollection(readAccess, slug = DEFAULT_BULK_TRANSLATE_UNITS_COLLECTION_SLUG, batchesCollectionSlug = 'bulk-translate-batches') {
|
|
34
|
+
const isAdminDefault = ({ req })=>{
|
|
35
|
+
const user = req.user;
|
|
36
|
+
const roles = user?.roles;
|
|
37
|
+
if (Array.isArray(roles) && roles.includes('admin')) return true;
|
|
38
|
+
return false;
|
|
39
|
+
};
|
|
40
|
+
return {
|
|
41
|
+
slug,
|
|
42
|
+
// System rows are never edited in the admin document view, so
|
|
43
|
+
// Payload's document-locking buys nothing here — and its lock check
|
|
44
|
+
// costs a second pool connection inside every update transaction
|
|
45
|
+
// (core's checkDocumentLockStatus runs a find without `req`). Under
|
|
46
|
+
// concurrent updates (e.g. dismiss-all on alerts) that exhausted the
|
|
47
|
+
// pool and deadlocked a consumer in prod on 2026-06-10.
|
|
48
|
+
lockDocuments: false,
|
|
49
|
+
labels: {
|
|
50
|
+
singular: 'Bulk Translate Unit',
|
|
51
|
+
plural: 'Bulk Translate Units'
|
|
52
|
+
},
|
|
53
|
+
admin: {
|
|
54
|
+
group: 'Translation',
|
|
55
|
+
useAsTitle: 'id',
|
|
56
|
+
defaultColumns: [
|
|
57
|
+
'batchId',
|
|
58
|
+
'collection',
|
|
59
|
+
'documentId',
|
|
60
|
+
'locale',
|
|
61
|
+
'status',
|
|
62
|
+
'attempts',
|
|
63
|
+
'failureCode',
|
|
64
|
+
'completedAt'
|
|
65
|
+
],
|
|
66
|
+
hidden: ({ user })=>{
|
|
67
|
+
const roles = user?.roles;
|
|
68
|
+
return !Array.isArray(roles) || !roles.includes('admin');
|
|
69
|
+
},
|
|
70
|
+
description: 'Per-(doc, locale) work item for a bulk-translate batch. One row per translation unit. Status transitions: pending → running → success | failed | skipped. Reverted units track replay of pre-run snapshots.'
|
|
71
|
+
},
|
|
72
|
+
access: {
|
|
73
|
+
read: readAccess ?? isAdminDefault,
|
|
74
|
+
create: ()=>false,
|
|
75
|
+
update: ()=>false,
|
|
76
|
+
delete: isAdminDefault
|
|
77
|
+
},
|
|
78
|
+
fields: [
|
|
79
|
+
{
|
|
80
|
+
name: 'batchId',
|
|
81
|
+
type: 'relationship',
|
|
82
|
+
relationTo: batchesCollectionSlug,
|
|
83
|
+
required: true,
|
|
84
|
+
index: true,
|
|
85
|
+
admin: {
|
|
86
|
+
readOnly: true
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
name: 'collection',
|
|
91
|
+
type: 'text',
|
|
92
|
+
required: true,
|
|
93
|
+
index: true,
|
|
94
|
+
admin: {
|
|
95
|
+
readOnly: true
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: 'documentId',
|
|
100
|
+
type: 'text',
|
|
101
|
+
required: true,
|
|
102
|
+
index: true,
|
|
103
|
+
admin: {
|
|
104
|
+
readOnly: true
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
name: 'locale',
|
|
109
|
+
type: 'text',
|
|
110
|
+
required: true,
|
|
111
|
+
index: true,
|
|
112
|
+
admin: {
|
|
113
|
+
readOnly: true
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: 'status',
|
|
118
|
+
type: 'select',
|
|
119
|
+
required: true,
|
|
120
|
+
index: true,
|
|
121
|
+
defaultValue: 'pending',
|
|
122
|
+
options: [
|
|
123
|
+
{
|
|
124
|
+
label: 'Pending (queued)',
|
|
125
|
+
value: 'pending'
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
label: 'Running',
|
|
129
|
+
value: 'running'
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
label: 'Success',
|
|
133
|
+
value: 'success'
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
label: 'Failed',
|
|
137
|
+
value: 'failed'
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
label: 'Skipped (no change)',
|
|
141
|
+
value: 'skipped'
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
label: 'Reverted',
|
|
145
|
+
value: 'reverted'
|
|
146
|
+
}
|
|
147
|
+
],
|
|
148
|
+
admin: {
|
|
149
|
+
readOnly: true
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
name: 'attempts',
|
|
154
|
+
type: 'number',
|
|
155
|
+
defaultValue: 0,
|
|
156
|
+
admin: {
|
|
157
|
+
readOnly: true
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
// Classifies the failure for retry policy + UI drill-down. The
|
|
161
|
+
// worker maps known errors to these classes; unknown errors fall
|
|
162
|
+
// back to `unknown`. Permanent classes never auto-retry.
|
|
163
|
+
{
|
|
164
|
+
name: 'failureCode',
|
|
165
|
+
type: 'select',
|
|
166
|
+
options: [
|
|
167
|
+
{
|
|
168
|
+
label: 'Transient — rate-limited',
|
|
169
|
+
value: 'transient.rate_limited'
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
label: 'Transient — provider 5xx',
|
|
173
|
+
value: 'transient.provider'
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
label: 'Transient — crashed (janitor)',
|
|
177
|
+
value: 'transient.crashed'
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
label: 'Permanent — schema invalid',
|
|
181
|
+
value: 'permanent.schema'
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
label: 'Permanent — too large',
|
|
185
|
+
value: 'permanent.too_large'
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
label: 'Permanent — auth/config',
|
|
189
|
+
value: 'permanent.config'
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
label: 'Permanent — doc deleted',
|
|
193
|
+
value: 'permanent.deleted'
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
label: 'Unknown',
|
|
197
|
+
value: 'unknown'
|
|
198
|
+
}
|
|
199
|
+
],
|
|
200
|
+
admin: {
|
|
201
|
+
readOnly: true
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
name: 'failureMessage',
|
|
206
|
+
type: 'textarea',
|
|
207
|
+
admin: {
|
|
208
|
+
readOnly: true
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
name: 'preRunSnapshot',
|
|
213
|
+
type: 'json',
|
|
214
|
+
admin: {
|
|
215
|
+
readOnly: true,
|
|
216
|
+
description: 'TARGET-locale values of ONLY the localized translatable fields, captured by the worker just before its first write for this unit (v1.2.12+). Used by revert. Never the full doc — see F-SEC-SNAPSHOT. Rows written before v1.2.12 hold SOURCE-locale values (captured at enqueue) and are refused by revert — replaying them stamped source-language content over translated locales.'
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
// v1.2.12: which locale's values `preRunSnapshot` holds. Revert
|
|
221
|
+
// requires snapshotLocale === locale; legacy rows (null) are
|
|
222
|
+
// refused — their snapshots were captured from the SOURCE-locale
|
|
223
|
+
// enumeration read and replaying them destroys translations.
|
|
224
|
+
name: 'snapshotLocale',
|
|
225
|
+
type: 'text',
|
|
226
|
+
admin: {
|
|
227
|
+
readOnly: true
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
// Hash of the localized translatable fields' schema at snapshot
|
|
231
|
+
// time. Revert refuses if schema-hash differs at restore time
|
|
232
|
+
// unless the admin sets `force: true` (Decision #34 +
|
|
233
|
+
// F-DA-REVERT-SCHEMA). Prevents silent data drift when a field
|
|
234
|
+
// is renamed or removed between snapshot and revert.
|
|
235
|
+
{
|
|
236
|
+
name: 'schemaHash',
|
|
237
|
+
type: 'text',
|
|
238
|
+
admin: {
|
|
239
|
+
readOnly: true
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
name: 'costUsd',
|
|
244
|
+
type: 'number',
|
|
245
|
+
defaultValue: 0,
|
|
246
|
+
admin: {
|
|
247
|
+
readOnly: true
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
name: 'startedAt',
|
|
252
|
+
type: 'date',
|
|
253
|
+
admin: {
|
|
254
|
+
readOnly: true,
|
|
255
|
+
description: 'When the worker handler entered for this unit. Includes any pending-queue wait the unit served before being picked up.'
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
name: 'completedAt',
|
|
260
|
+
type: 'date',
|
|
261
|
+
admin: {
|
|
262
|
+
readOnly: true,
|
|
263
|
+
description: 'When the worker handler finished (success or terminal failure).'
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
// Real translation-call duration in milliseconds. Captured around
|
|
268
|
+
// the `translateApi.translateDocument(...)` call inside the worker —
|
|
269
|
+
// excludes token-bucket wait, provider rate-limit backoff, and
|
|
270
|
+
// queue scheduling. This is what the editor cares about: "how long
|
|
271
|
+
// did the AI actually spend on this." `completedAt - startedAt`
|
|
272
|
+
// includes throttle wait and is reported separately as
|
|
273
|
+
// wallclock-in-worker for engineering.
|
|
274
|
+
name: 'processingDurationMs',
|
|
275
|
+
type: 'number',
|
|
276
|
+
admin: {
|
|
277
|
+
readOnly: true,
|
|
278
|
+
description: 'Time the AI translation call itself took, in milliseconds. Excludes throttle / rate-limit wait — that gets folded into the difference between startedAt and completedAt instead.'
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
],
|
|
282
|
+
indexes: [
|
|
283
|
+
// Composite index for the shouldSkipDocument-equivalent lookup at
|
|
284
|
+
// task entry + retry endpoint. The application-layer query is:
|
|
285
|
+
// findFirst WHERE collection=? AND documentId=? AND status IN
|
|
286
|
+
// ('pending','running')
|
|
287
|
+
// A partial unique index on the same predicate is added via raw
|
|
288
|
+
// SQL migration (F-DA-PARTIAL-IDX) — Payload's index generator
|
|
289
|
+
// doesn't emit partial uniqueness today.
|
|
290
|
+
//
|
|
291
|
+
// TODO(migration): hand-write the partial unique index as part
|
|
292
|
+
// of the v1.2.0 migrations bundle. Exact SQL:
|
|
293
|
+
//
|
|
294
|
+
// CREATE UNIQUE INDEX bulk_translate_units_active_dedup
|
|
295
|
+
// ON bulk_translate_units (collection, document_id, locale)
|
|
296
|
+
// WHERE status IN ('pending','running');
|
|
297
|
+
//
|
|
298
|
+
// Note the three-column uniqueness — `(collection, doc, locale)`,
|
|
299
|
+
// not `(collection, doc)`. Allows different locales for the same
|
|
300
|
+
// doc to run concurrently while serializing per-locale writes.
|
|
301
|
+
{
|
|
302
|
+
fields: [
|
|
303
|
+
'collection',
|
|
304
|
+
'documentId',
|
|
305
|
+
'status'
|
|
306
|
+
]
|
|
307
|
+
}
|
|
308
|
+
]
|
|
309
|
+
};
|
|
310
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { formatCost } from '../views/shared/format.js';
|
|
5
|
+
export function EstimatedCostCell({ cellData }) {
|
|
6
|
+
if (cellData === null || cellData === undefined) return /*#__PURE__*/ _jsx("span", {
|
|
7
|
+
children: "—"
|
|
8
|
+
});
|
|
9
|
+
return /*#__PURE__*/ _jsx("span", {
|
|
10
|
+
children: formatCost(cellData)
|
|
11
|
+
});
|
|
12
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
type Props = {
|
|
3
|
+
/**
|
|
4
|
+
* Field path Payload assigns at render time, e.g.
|
|
5
|
+
* `perCollection.0.excludedFieldPaths`. We strip the trailing
|
|
6
|
+
* segment to address the sibling `slug` field of the same row.
|
|
7
|
+
*/
|
|
8
|
+
path: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Custom admin component for `perCollection[i].excludedFieldPaths`.
|
|
12
|
+
*
|
|
13
|
+
* Stores an exclude-list (top-level field paths the admin opted OUT of
|
|
14
|
+
* translation). Rendered as a grouped list — one checkbox per
|
|
15
|
+
* top-level field on the surface. Unchecking a top-level field
|
|
16
|
+
* excludes EVERY descendant path under it (prefix-match in
|
|
17
|
+
* `isPathExcluded`).
|
|
18
|
+
*
|
|
19
|
+
* Design rationale:
|
|
20
|
+
*
|
|
21
|
+
* 1. **Editor mental model.** Editors think in terms of the fields
|
|
22
|
+
* they see in the doc editor ("Layout", "Meta"), not internal dot-
|
|
23
|
+
* paths. The earlier flat list of paths like
|
|
24
|
+
* `layout.columns.link.label` was technically correct but useless
|
|
25
|
+
* for non-developers.
|
|
26
|
+
* 2. **One checkbox per top-level field.** Coarse but predictable:
|
|
27
|
+
* "uncheck Layout" → nothing under `layout.*` is translated.
|
|
28
|
+
* Per-leaf exclusions are still expressible via direct DB writes
|
|
29
|
+
* or future per-field controls if needed; the common case is
|
|
30
|
+
* coverage at the section level.
|
|
31
|
+
* 3. **Disclosure of details.** A collapsible "Show 14 sub-paths"
|
|
32
|
+
* affordance reveals every descendant path the resolver found, so
|
|
33
|
+
* a developer / careful editor can verify what's actually
|
|
34
|
+
* affected. Read-only — not interactive.
|
|
35
|
+
* 4. **Exclude-list semantics.** Default = empty array = translate
|
|
36
|
+
* everything. New localized fields added later start "checked"
|
|
37
|
+
* automatically.
|
|
38
|
+
*
|
|
39
|
+
* Sibling slug derivation: Payload doesn't give the component direct
|
|
40
|
+
* access to its row neighbours, so we strip the trailing
|
|
41
|
+
* `.excludedFieldPaths` segment from `path` and append `.slug` to
|
|
42
|
+
* address the sibling.
|
|
43
|
+
*/
|
|
44
|
+
export declare function ExcludedFieldsField({ path }: Props): React.JSX.Element;
|
|
45
|
+
export {};
|