sanity-plugin-transifex

5.1.205.1.21
~

Modified (2 files)

Index: package/package.json
===================================================================
--- package/package.json
+++ package/package.json
@@ -1,7 +1,7 @@
 {
   "name": "sanity-plugin-transifex",
-  "version": "5.1.20",
+  "version": "5.1.21",
   "description": "This plugin provides an in-studio integration with Transifex. It allows your editors to send any document to Transifex with the click of a button, monitor ongoing translations, and import partial or complete translations back into the studio.",
   "keywords": [
     "sanity",
     "sanity-plugin"
@@ -26,16 +26,16 @@
     ".": "./dist/index.js",
     "./package.json": "./package.json"
   },
   "dependencies": {
-    "sanity-translations-tab": "^6.1.20"
+    "sanity-translations-tab": "^6.1.21"
   },
   "devDependencies": {
     "@sanity/tsconfig": "^2.2.1",
     "@sanity/tsdown-config": "^0.26.0",
     "@types/react": "^19.2.18",
     "@types/react-dom": "^19.2.4",
-    "babel-plugin-react-compiler": "^1.0.0",
+    "oxc-transform-react": "^0.145.0",
     "react": "^19.2.8",
     "react-dom": "^19.2.8",
     "sanity": "^6.10.1",
     "styled-components": "^6.5.3",
Index: package/dist/index.js.map
===================================================================
--- package/dist/index.js.map
+++ package/dist/index.js.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"index.js","names":["Secrets","baseTransifexUrl","getHeaders","secrets","Record","token","projOrgSlug","organization","project","Adapter","Secrets","baseTransifexUrl","projOrgSlug","getHeaders","getLocales","secrets","locales","response","fetch","headers","ok","Error","status","json","then","res","data","map","lang","Record","enabled","description","localeId","Adapter","Secrets","getLocales","baseTransifexUrl","projOrgSlug","getHeaders","getTranslationTask","documentId","secrets","taskId","locales","projectFilter","resourceFilter","task","fetch","headers","then","res","ok","json","status","data","Error","map","locale","Record","reviewedStrings","Number","totalStrings","localeId","split","progress","isFinite","Math","floor","localeIds","l","validLocales","filter","find","id","Adapter","Secrets","getTranslationTask","baseTransifexUrl","projOrgSlug","getHeaders","createResource","doc","Record","documentId","secrets","resourceCreateBody","data","attributes","accept_translations","name","slug","relationships","i18n_format","id","type","project","response","fetch","headers","method","body","JSON","stringify","ok","Error","status","res","json","resourceId","createTask","document","_localeIds","resourceResponse","resource","resourceUploadUrl","resourceUploadBody","content","content_encoding","uploadResponse","Adapter","Secrets","baseTransifexUrl","getHeaders","pollForFileDownloadLocation","resourceDownloadUrl","translationDownloadId","headers","Record","retryCount","maxRetries","Promise","response","fetch","Error","status","console","info","resolve","setTimeout","redirected","url","error","handleFileDownload","then","res","text","getTranslation","taskId","localeId","secrets","resourceDownloadBody","data","attributes","content_encoding","relationships","language","id","type","resource","downloadResponse","method","body","JSON","stringify","ok","download","json","location","Adapter","createTask","getLocales","getTranslation","getTranslationTask","TransifexAdapter","baseDocumentLevelConfig","legacyDocumentLevelConfig","baseLegacyDocumentLevelConfig","baseFieldLevelConfig","baseI18nArrayConfig","Adapter","TranslationFunctionContext","TransifexAdapter","findLatestDraft","BaseDocumentDeserializer","BaseDocumentSerializer","BaseDocumentMerger","defaultStopTypes","customSerializers","legacyDocumentLevelPatch","documentLevelPatch","fieldLevelPatch","i18nArrayPatch","TranslationsTab","ConfigOptions","adapter","secretsNamespace","exportForTranslation","id","context","Promise","Record","importTranslation","localeId","doc","defaultDocumentLevelConfig","defaultFieldLevelConfig","defaultI18nArrayConfig"],"sources":["../src/transifexAdapter/helpers.ts","../src/transifexAdapter/getLocales.ts","../src/transifexAdapter/getTranslationTask.ts","../src/transifexAdapter/createTask.ts","../src/transifexAdapter/getTranslation.ts","../src/transifexAdapter/index.ts","../src/index.ts"],"sourcesContent":["import type {Secrets} from 'sanity-translations-tab'\n\nexport const baseTransifexUrl = 'https://rest.api.transifex.com'\n\nexport const getHeaders = (secrets: Secrets | null): Record<string, string> => ({\n  'Authorization': `Bearer ${secrets?.token}`,\n  'Content-Type': 'application/vnd.api+json',\n})\n\nexport const projOrgSlug = (secrets: Secrets | null): string =>\n  `o:${secrets?.organization}:p:${secrets?.project}`\n","import type {Adapter, Secrets} from 'sanity-translations-tab'\n\nimport {baseTransifexUrl, projOrgSlug, getHeaders} from './helpers'\n\nexport const getLocales: Adapter['getLocales'] = async (secrets: Secrets | null) => {\n  let locales = []\n  if (secrets) {\n    const response = await fetch(`${baseTransifexUrl}/projects/${projOrgSlug(secrets)}/languages`, {\n      headers: getHeaders(secrets),\n    })\n\n    if (!response.ok) {\n      throw Error(`Failed to retrieve locales from Transifex. Status: ${response.status}`)\n    }\n\n    locales = await response.json().then((res) =>\n      res.data.map((lang: Record<string, any>) => ({\n        enabled: true,\n        description: lang['attributes']['name'],\n        localeId: lang['attributes']['code'],\n      })),\n    )\n  }\n  return locales\n}\n","import type {Adapter, Secrets} from 'sanity-translations-tab'\n\nimport {getLocales} from './getLocales'\nimport {baseTransifexUrl, projOrgSlug, getHeaders} from './helpers'\n\nexport const getTranslationTask: Adapter['getTranslationTask'] = async (\n  documentId: string,\n  secrets: Secrets | null,\n) => {\n  if (!documentId || !secrets) {\n    return {\n      taskId: documentId,\n      documentId: documentId,\n      locales: [],\n    }\n  }\n  const projectFilter = `filter[project]=${projOrgSlug(secrets)}`\n  const resourceFilter = `filter[resource]=${projOrgSlug(secrets)}:r:${documentId}`\n  const task = await fetch(\n    `${baseTransifexUrl}/resource_language_stats?${projectFilter}&${resourceFilter}`,\n    {headers: getHeaders(secrets)},\n  )\n    .then((res) => {\n      if (res.ok) {\n        return res.json()\n      }\n      //normal -- just means that this task doesn't exist yet.\n      else if (res.status === 404) {\n        return {data: []}\n      }\n      throw Error(`Failed to retrieve tasks from Transifex. Status: ${res.status}`)\n    })\n    .then((res) => ({\n      taskId: `${projOrgSlug(secrets)}:r:${documentId}`,\n      documentId: documentId,\n      locales: res.data.map((locale: Record<string, any>) => {\n        const reviewedStrings = Number(locale['attributes']['reviewed_strings'])\n        const totalStrings = Number(locale['attributes']['total_strings'])\n\n        return {\n          localeId: locale['relationships']['language']['data']['id'].split(':')[1],\n          progress:\n            Number.isFinite(reviewedStrings) && Number.isFinite(totalStrings) && totalStrings > 0\n              ? Math.floor((100 * reviewedStrings) / totalStrings)\n              : 0,\n        }\n      }),\n    }))\n\n  const locales = await getLocales(secrets)\n  const localeIds = locales.map((l: Record<string, any>) => l['localeId'])\n  const validLocales = task.locales.filter((locale: Record<string, any>) =>\n    localeIds.find((id: string) => id === locale['localeId']),\n  )\n  task.locales = validLocales\n\n  return task\n}\n","import type {Adapter, Secrets} from 'sanity-translations-tab'\n\nimport {getTranslationTask} from './getTranslationTask'\nimport {baseTransifexUrl, projOrgSlug, getHeaders} from './helpers'\n\nconst createResource = async (\n  doc: Record<string, any>,\n  documentId: string,\n  secrets: Secrets | null,\n) => {\n  const resourceCreateBody = {\n    data: {\n      attributes: {\n        accept_translations: true,\n        name: doc['name'],\n        slug: documentId,\n      },\n      relationships: {\n        i18n_format: {\n          data: {\n            id: 'HTML_FRAGMENT',\n            type: 'i18n_formats',\n          },\n        },\n        project: {\n          data: {\n            id: projOrgSlug(secrets),\n            type: 'projects',\n          },\n        },\n      },\n      type: 'resources',\n    },\n  }\n\n  const response = await fetch(`${baseTransifexUrl}/resources`, {\n    headers: getHeaders(secrets),\n    method: 'POST',\n    body: JSON.stringify(resourceCreateBody),\n  })\n\n  if (!response.ok) {\n    throw Error(`Failed to create Transifex resource. Status: ${response.status}`)\n  }\n\n  const res = await response.json()\n  const resourceId = res?.data?.id\n\n  if (!resourceId) {\n    throw Error('Failed to create Transifex resource. Missing resource id in response.')\n  }\n\n  return resourceId\n}\n\nexport const createTask: Adapter['createTask'] = async (\n  documentId: string,\n  document: Record<string, any>,\n  _localeIds: string[],\n  secrets: Secrets | null,\n) => {\n  if (!documentId || !secrets) {\n    throw Error('Missing documentId or Transifex secrets.')\n  }\n\n  const resourceResponse = await fetch(\n    `${baseTransifexUrl}/resources/${projOrgSlug(secrets)}:r:${documentId}`,\n    {headers: getHeaders(secrets)},\n  )\n  let resourceId: string | null = null\n\n  if (resourceResponse.status === 404) {\n    resourceId = null\n  } else if (!resourceResponse.ok) {\n    throw Error(`Failed to retrieve Transifex resource. Status: ${resourceResponse.status}`)\n  } else {\n    const resource = await resourceResponse.json()\n    resourceId = resource.data ? resource.data.id : null\n  }\n\n  if (!resourceId) {\n    resourceId = await createResource(document, documentId, secrets)\n  }\n\n  const resourceUploadUrl = `${baseTransifexUrl}/resource_strings_async_uploads`\n  const resourceUploadBody = {\n    data: {\n      attributes: {\n        content: document['content'],\n        content_encoding: 'text',\n      },\n      relationships: {\n        resource: {\n          data: {\n            id: resourceId,\n            type: 'resources',\n          },\n        },\n      },\n      type: 'resource_strings_async_uploads',\n    },\n  }\n\n  const uploadResponse = await fetch(resourceUploadUrl, {\n    method: 'POST',\n    body: JSON.stringify(resourceUploadBody),\n    headers: getHeaders(secrets),\n  })\n\n  if (!uploadResponse.ok) {\n    throw Error(`Failed to upload resource strings to Transifex. Status: ${uploadResponse.status}`)\n  }\n\n  return getTranslationTask(documentId, secrets)\n}\n","import type {Adapter, Secrets} from 'sanity-translations-tab'\n\nimport {baseTransifexUrl, getHeaders} from './helpers'\n\nconst pollForFileDownloadLocation = async (\n  resourceDownloadUrl: string,\n  translationDownloadId: string,\n  headers: Record<string, any>,\n  retryCount = 0,\n  maxRetries = 20,\n): Promise<string> => {\n  const response = await fetch(`${resourceDownloadUrl}/${translationDownloadId}`, {\n    headers: headers,\n  })\n\n  if (retryCount >= maxRetries) {\n    throw Error(\n      `Failed to retrieve download location for translation download ID ${translationDownloadId} after ${maxRetries} retries.`,\n    )\n  }\n\n  if (response.status === 500) {\n    //eslint-disable-next-line no-console -- this is for developer feedback/debugging\n    console.info(\n      `Transifex plugin message: Received 500 for translation download ID ${translationDownloadId}. Trying to reconnect...`,\n    )\n    await new Promise((resolve) => setTimeout(resolve, 3000))\n    return pollForFileDownloadLocation(\n      resourceDownloadUrl,\n      translationDownloadId,\n      headers,\n      retryCount + 1,\n      maxRetries,\n    )\n  } else if (response.redirected) {\n    //eslint-disable-next-line no-console -- this is for developer feedback/debugging\n    console.info(\n      `Transifex plugin message: Received redirect for translation download ID ${translationDownloadId}. Following redirect now for file download.`,\n    )\n    return response.url\n  } else if (response.status === 200) {\n    //eslint-disable-next-line no-console -- this is for developer feedback/debugging\n    console.info(\n      `Transifex plugin message: Requested download location for translation download ID ${translationDownloadId}. Location is still pending, trying again.`,\n    )\n    await new Promise((resolve) => setTimeout(resolve, 3000))\n    return pollForFileDownloadLocation(\n      resourceDownloadUrl,\n      translationDownloadId,\n      headers,\n      retryCount + 1,\n      maxRetries,\n    )\n  } else if (response.status === 401 || response.status === 403) {\n    throw Error(\n      `Failed to retrieve download location for translation download ID ${translationDownloadId}. Status: ${response.status}`,\n    )\n  }\n  console.error(\n    `Transifex plugin message: Requested download location for translation download ID ${translationDownloadId} but received error code ${response.status}. Waiting and trying again.`,\n  )\n  await new Promise((resolve) => setTimeout(resolve, 3000))\n  return pollForFileDownloadLocation(\n    resourceDownloadUrl,\n    translationDownloadId,\n    headers,\n    retryCount + 1,\n    maxRetries,\n  )\n}\n\nconst handleFileDownload = (url: string) => {\n  return fetch(url).then((res) => res.text())\n}\n\nexport const getTranslation: Adapter['getTranslation'] = async (\n  taskId: string,\n  localeId: string,\n  secrets: Secrets | null,\n) => {\n  if (!secrets) {\n    throw Error('Missing Transifex secrets.')\n  }\n\n  const resourceDownloadBody = {\n    data: {\n      attributes: {\n        content_encoding: 'text',\n      },\n      relationships: {\n        language: {\n          data: {\n            id: `l:${localeId}`,\n            type: 'languages',\n          },\n        },\n        resource: {\n          data: {\n            id: taskId,\n            type: 'resources',\n          },\n        },\n      },\n      type: 'resource_translations_async_downloads',\n    },\n  }\n\n  const resourceDownloadUrl = `${baseTransifexUrl}/resource_translations_async_downloads`\n  const downloadResponse = await fetch(resourceDownloadUrl, {\n    headers: getHeaders(secrets),\n    method: 'POST',\n    body: JSON.stringify(resourceDownloadBody),\n  })\n\n  if (!downloadResponse.ok) {\n    throw Error(\n      `Failed to create translation download request in Transifex. Status: ${downloadResponse.status}`,\n    )\n  }\n\n  const download = await downloadResponse.json()\n  const translationDownloadId = download?.data?.id\n\n  if (!translationDownloadId) {\n    throw Error('Failed to create translation download request in Transifex. Missing download id.')\n  }\n\n  const headers = getHeaders(secrets)\n  const location = await pollForFileDownloadLocation(\n    resourceDownloadUrl,\n    translationDownloadId,\n    headers,\n  )\n  return handleFileDownload(location)\n}\n","import type {Adapter} from 'sanity-translations-tab'\n\nimport {createTask} from './createTask'\nimport {getLocales} from './getLocales'\nimport {getTranslation} from './getTranslation'\nimport {getTranslationTask} from './getTranslationTask'\n\nexport const TransifexAdapter: Adapter = {\n  getLocales,\n  getTranslationTask,\n  createTask,\n  getTranslation,\n}\n","import {\n  baseDocumentLevelConfig,\n  legacyDocumentLevelConfig as baseLegacyDocumentLevelConfig,\n  baseFieldLevelConfig,\n  baseI18nArrayConfig,\n} from 'sanity-translations-tab'\nimport type {Adapter, TranslationFunctionContext} from 'sanity-translations-tab'\n\nimport {TransifexAdapter} from './transifexAdapter'\n\nexport {\n  findLatestDraft,\n  BaseDocumentDeserializer,\n  BaseDocumentSerializer,\n  BaseDocumentMerger,\n  defaultStopTypes,\n  customSerializers,\n  legacyDocumentLevelPatch,\n  documentLevelPatch,\n  fieldLevelPatch,\n  i18nArrayPatch,\n  TranslationsTab,\n} from 'sanity-translations-tab'\n\ninterface ConfigOptions {\n  adapter: Adapter\n  secretsNamespace: string | null\n  exportForTranslation: (\n    id: string,\n    context: TranslationFunctionContext,\n  ) => Promise<Record<string, any>>\n  importTranslation: (\n    id: string,\n    localeId: string,\n    doc: string,\n    context: TranslationFunctionContext,\n  ) => Promise<void>\n}\nconst defaultDocumentLevelConfig: ConfigOptions = {\n  ...baseDocumentLevelConfig,\n  adapter: TransifexAdapter,\n  secretsNamespace: 'transifex',\n}\n\nconst legacyDocumentLevelConfig: ConfigOptions = {\n  ...baseLegacyDocumentLevelConfig,\n  adapter: TransifexAdapter,\n  secretsNamespace: 'transifex',\n}\n\nconst defaultFieldLevelConfig: ConfigOptions = {\n  ...baseFieldLevelConfig,\n  adapter: TransifexAdapter,\n  secretsNamespace: 'transifex',\n}\n\n//for documents using sanity-plugin-internationalized-array fields\nconst defaultI18nArrayConfig: ConfigOptions = {\n  ...baseI18nArrayConfig,\n  adapter: TransifexAdapter,\n  secretsNamespace: 'transifex',\n}\n\nexport {\n  TransifexAdapter,\n  defaultDocumentLevelConfig,\n  defaultFieldLevelConfig,\n  defaultI18nArrayConfig,\n  legacyDocumentLevelConfig,\n}\n"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"index.js","names":[],"sources":["../src/transifexAdapter/helpers.ts","../src/transifexAdapter/getLocales.ts","../src/transifexAdapter/getTranslationTask.ts","../src/transifexAdapter/createTask.ts","../src/transifexAdapter/getTranslation.ts","../src/transifexAdapter/index.ts","../src/index.ts"],"sourcesContent":["import type {Secrets} from 'sanity-translations-tab'\n\nexport const baseTransifexUrl = 'https://rest.api.transifex.com'\n\nexport const getHeaders = (secrets: Secrets | null): Record<string, string> => ({\n  'Authorization': `Bearer ${secrets?.token}`,\n  'Content-Type': 'application/vnd.api+json',\n})\n\nexport const projOrgSlug = (secrets: Secrets | null): string =>\n  `o:${secrets?.organization}:p:${secrets?.project}`\n","import type {Adapter, Secrets} from 'sanity-translations-tab'\n\nimport {baseTransifexUrl, projOrgSlug, getHeaders} from './helpers'\n\nexport const getLocales: Adapter['getLocales'] = async (secrets: Secrets | null) => {\n  let locales = []\n  if (secrets) {\n    const response = await fetch(`${baseTransifexUrl}/projects/${projOrgSlug(secrets)}/languages`, {\n      headers: getHeaders(secrets),\n    })\n\n    if (!response.ok) {\n      throw Error(`Failed to retrieve locales from Transifex. Status: ${response.status}`)\n    }\n\n    locales = await response.json().then((res) =>\n      res.data.map((lang: Record<string, any>) => ({\n        enabled: true,\n        description: lang['attributes']['name'],\n        localeId: lang['attributes']['code'],\n      })),\n    )\n  }\n  return locales\n}\n","import type {Adapter, Secrets} from 'sanity-translations-tab'\n\nimport {getLocales} from './getLocales'\nimport {baseTransifexUrl, projOrgSlug, getHeaders} from './helpers'\n\nexport const getTranslationTask: Adapter['getTranslationTask'] = async (\n  documentId: string,\n  secrets: Secrets | null,\n) => {\n  if (!documentId || !secrets) {\n    return {\n      taskId: documentId,\n      documentId: documentId,\n      locales: [],\n    }\n  }\n  const projectFilter = `filter[project]=${projOrgSlug(secrets)}`\n  const resourceFilter = `filter[resource]=${projOrgSlug(secrets)}:r:${documentId}`\n  const task = await fetch(\n    `${baseTransifexUrl}/resource_language_stats?${projectFilter}&${resourceFilter}`,\n    {headers: getHeaders(secrets)},\n  )\n    .then((res) => {\n      if (res.ok) {\n        return res.json()\n      }\n      //normal -- just means that this task doesn't exist yet.\n      else if (res.status === 404) {\n        return {data: []}\n      }\n      throw Error(`Failed to retrieve tasks from Transifex. Status: ${res.status}`)\n    })\n    .then((res) => ({\n      taskId: `${projOrgSlug(secrets)}:r:${documentId}`,\n      documentId: documentId,\n      locales: res.data.map((locale: Record<string, any>) => {\n        const reviewedStrings = Number(locale['attributes']['reviewed_strings'])\n        const totalStrings = Number(locale['attributes']['total_strings'])\n\n        return {\n          localeId: locale['relationships']['language']['data']['id'].split(':')[1],\n          progress:\n            Number.isFinite(reviewedStrings) && Number.isFinite(totalStrings) && totalStrings > 0\n              ? Math.floor((100 * reviewedStrings) / totalStrings)\n              : 0,\n        }\n      }),\n    }))\n\n  const locales = await getLocales(secrets)\n  const localeIds = locales.map((l: Record<string, any>) => l['localeId'])\n  const validLocales = task.locales.filter((locale: Record<string, any>) =>\n    localeIds.find((id: string) => id === locale['localeId']),\n  )\n  task.locales = validLocales\n\n  return task\n}\n","import type {Adapter, Secrets} from 'sanity-translations-tab'\n\nimport {getTranslationTask} from './getTranslationTask'\nimport {baseTransifexUrl, projOrgSlug, getHeaders} from './helpers'\n\nconst createResource = async (\n  doc: Record<string, any>,\n  documentId: string,\n  secrets: Secrets | null,\n) => {\n  const resourceCreateBody = {\n    data: {\n      attributes: {\n        accept_translations: true,\n        name: doc['name'],\n        slug: documentId,\n      },\n      relationships: {\n        i18n_format: {\n          data: {\n            id: 'HTML_FRAGMENT',\n            type: 'i18n_formats',\n          },\n        },\n        project: {\n          data: {\n            id: projOrgSlug(secrets),\n            type: 'projects',\n          },\n        },\n      },\n      type: 'resources',\n    },\n  }\n\n  const response = await fetch(`${baseTransifexUrl}/resources`, {\n    headers: getHeaders(secrets),\n    method: 'POST',\n    body: JSON.stringify(resourceCreateBody),\n  })\n\n  if (!response.ok) {\n    throw Error(`Failed to create Transifex resource. Status: ${response.status}`)\n  }\n\n  const res = await response.json()\n  const resourceId = res?.data?.id\n\n  if (!resourceId) {\n    throw Error('Failed to create Transifex resource. Missing resource id in response.')\n  }\n\n  return resourceId\n}\n\nexport const createTask: Adapter['createTask'] = async (\n  documentId: string,\n  document: Record<string, any>,\n  _localeIds: string[],\n  secrets: Secrets | null,\n) => {\n  if (!documentId || !secrets) {\n    throw Error('Missing documentId or Transifex secrets.')\n  }\n\n  const resourceResponse = await fetch(\n    `${baseTransifexUrl}/resources/${projOrgSlug(secrets)}:r:${documentId}`,\n    {headers: getHeaders(secrets)},\n  )\n  let resourceId: string | null = null\n\n  if (resourceResponse.status === 404) {\n    resourceId = null\n  } else if (!resourceResponse.ok) {\n    throw Error(`Failed to retrieve Transifex resource. Status: ${resourceResponse.status}`)\n  } else {\n    const resource = await resourceResponse.json()\n    resourceId = resource.data ? resource.data.id : null\n  }\n\n  if (!resourceId) {\n    resourceId = await createResource(document, documentId, secrets)\n  }\n\n  const resourceUploadUrl = `${baseTransifexUrl}/resource_strings_async_uploads`\n  const resourceUploadBody = {\n    data: {\n      attributes: {\n        content: document['content'],\n        content_encoding: 'text',\n      },\n      relationships: {\n        resource: {\n          data: {\n            id: resourceId,\n            type: 'resources',\n          },\n        },\n      },\n      type: 'resource_strings_async_uploads',\n    },\n  }\n\n  const uploadResponse = await fetch(resourceUploadUrl, {\n    method: 'POST',\n    body: JSON.stringify(resourceUploadBody),\n    headers: getHeaders(secrets),\n  })\n\n  if (!uploadResponse.ok) {\n    throw Error(`Failed to upload resource strings to Transifex. Status: ${uploadResponse.status}`)\n  }\n\n  return getTranslationTask(documentId, secrets)\n}\n","import type {Adapter, Secrets} from 'sanity-translations-tab'\n\nimport {baseTransifexUrl, getHeaders} from './helpers'\n\nconst pollForFileDownloadLocation = async (\n  resourceDownloadUrl: string,\n  translationDownloadId: string,\n  headers: Record<string, any>,\n  retryCount = 0,\n  maxRetries = 20,\n): Promise<string> => {\n  const response = await fetch(`${resourceDownloadUrl}/${translationDownloadId}`, {\n    headers: headers,\n  })\n\n  if (retryCount >= maxRetries) {\n    throw Error(\n      `Failed to retrieve download location for translation download ID ${translationDownloadId} after ${maxRetries} retries.`,\n    )\n  }\n\n  if (response.status === 500) {\n    //eslint-disable-next-line no-console -- this is for developer feedback/debugging\n    console.info(\n      `Transifex plugin message: Received 500 for translation download ID ${translationDownloadId}. Trying to reconnect...`,\n    )\n    await new Promise((resolve) => setTimeout(resolve, 3000))\n    return pollForFileDownloadLocation(\n      resourceDownloadUrl,\n      translationDownloadId,\n      headers,\n      retryCount + 1,\n      maxRetries,\n    )\n  } else if (response.redirected) {\n    //eslint-disable-next-line no-console -- this is for developer feedback/debugging\n    console.info(\n      `Transifex plugin message: Received redirect for translation download ID ${translationDownloadId}. Following redirect now for file download.`,\n    )\n    return response.url\n  } else if (response.status === 200) {\n    //eslint-disable-next-line no-console -- this is for developer feedback/debugging\n    console.info(\n      `Transifex plugin message: Requested download location for translation download ID ${translationDownloadId}. Location is still pending, trying again.`,\n    )\n    await new Promise((resolve) => setTimeout(resolve, 3000))\n    return pollForFileDownloadLocation(\n      resourceDownloadUrl,\n      translationDownloadId,\n      headers,\n      retryCount + 1,\n      maxRetries,\n    )\n  } else if (response.status === 401 || response.status === 403) {\n    throw Error(\n      `Failed to retrieve download location for translation download ID ${translationDownloadId}. Status: ${response.status}`,\n    )\n  }\n  console.error(\n    `Transifex plugin message: Requested download location for translation download ID ${translationDownloadId} but received error code ${response.status}. Waiting and trying again.`,\n  )\n  await new Promise((resolve) => setTimeout(resolve, 3000))\n  return pollForFileDownloadLocation(\n    resourceDownloadUrl,\n    translationDownloadId,\n    headers,\n    retryCount + 1,\n    maxRetries,\n  )\n}\n\nconst handleFileDownload = (url: string) => {\n  return fetch(url).then((res) => res.text())\n}\n\nexport const getTranslation: Adapter['getTranslation'] = async (\n  taskId: string,\n  localeId: string,\n  secrets: Secrets | null,\n) => {\n  if (!secrets) {\n    throw Error('Missing Transifex secrets.')\n  }\n\n  const resourceDownloadBody = {\n    data: {\n      attributes: {\n        content_encoding: 'text',\n      },\n      relationships: {\n        language: {\n          data: {\n            id: `l:${localeId}`,\n            type: 'languages',\n          },\n        },\n        resource: {\n          data: {\n            id: taskId,\n            type: 'resources',\n          },\n        },\n      },\n      type: 'resource_translations_async_downloads',\n    },\n  }\n\n  const resourceDownloadUrl = `${baseTransifexUrl}/resource_translations_async_downloads`\n  const downloadResponse = await fetch(resourceDownloadUrl, {\n    headers: getHeaders(secrets),\n    method: 'POST',\n    body: JSON.stringify(resourceDownloadBody),\n  })\n\n  if (!downloadResponse.ok) {\n    throw Error(\n      `Failed to create translation download request in Transifex. Status: ${downloadResponse.status}`,\n    )\n  }\n\n  const download = await downloadResponse.json()\n  const translationDownloadId = download?.data?.id\n\n  if (!translationDownloadId) {\n    throw Error('Failed to create translation download request in Transifex. Missing download id.')\n  }\n\n  const headers = getHeaders(secrets)\n  const location = await pollForFileDownloadLocation(\n    resourceDownloadUrl,\n    translationDownloadId,\n    headers,\n  )\n  return handleFileDownload(location)\n}\n","import type {Adapter} from 'sanity-translations-tab'\n\nimport {createTask} from './createTask'\nimport {getLocales} from './getLocales'\nimport {getTranslation} from './getTranslation'\nimport {getTranslationTask} from './getTranslationTask'\n\nexport const TransifexAdapter: Adapter = {\n  getLocales,\n  getTranslationTask,\n  createTask,\n  getTranslation,\n}\n","import {\n  baseDocumentLevelConfig,\n  legacyDocumentLevelConfig as baseLegacyDocumentLevelConfig,\n  baseFieldLevelConfig,\n  baseI18nArrayConfig,\n} from 'sanity-translations-tab'\nimport type {Adapter, TranslationFunctionContext} from 'sanity-translations-tab'\n\nimport {TransifexAdapter} from './transifexAdapter'\n\nexport {\n  findLatestDraft,\n  BaseDocumentDeserializer,\n  BaseDocumentSerializer,\n  BaseDocumentMerger,\n  defaultStopTypes,\n  customSerializers,\n  legacyDocumentLevelPatch,\n  documentLevelPatch,\n  fieldLevelPatch,\n  i18nArrayPatch,\n  TranslationsTab,\n} from 'sanity-translations-tab'\n\ninterface ConfigOptions {\n  adapter: Adapter\n  secretsNamespace: string | null\n  exportForTranslation: (\n    id: string,\n    context: TranslationFunctionContext,\n  ) => Promise<Record<string, any>>\n  importTranslation: (\n    id: string,\n    localeId: string,\n    doc: string,\n    context: TranslationFunctionContext,\n  ) => Promise<void>\n}\nconst defaultDocumentLevelConfig: ConfigOptions = {\n  ...baseDocumentLevelConfig,\n  adapter: TransifexAdapter,\n  secretsNamespace: 'transifex',\n}\n\nconst legacyDocumentLevelConfig: ConfigOptions = {\n  ...baseLegacyDocumentLevelConfig,\n  adapter: TransifexAdapter,\n  secretsNamespace: 'transifex',\n}\n\nconst defaultFieldLevelConfig: ConfigOptions = {\n  ...baseFieldLevelConfig,\n  adapter: TransifexAdapter,\n  secretsNamespace: 'transifex',\n}\n\n//for documents using sanity-plugin-internationalized-array fields\nconst defaultI18nArrayConfig: ConfigOptions = {\n  ...baseI18nArrayConfig,\n  adapter: TransifexAdapter,\n  secretsNamespace: 'transifex',\n}\n\nexport {\n  TransifexAdapter,\n  defaultDocumentLevelConfig,\n  defaultFieldLevelConfig,\n  defaultI18nArrayConfig,\n  legacyDocumentLevelConfig,\n}\n"],"mappings":"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"}
\ No newline at end of file