sanity-plugin-studio-smartling

5.0.75.0.8
~

Modified (4 files)

Index: package/dist/index.js
===================================================================
--- package/dist/index.js
+++ package/dist/index.js
@@ -121,9 +121,11 @@
 	getTranslationTask,
 	createTask: async (documentId, document, localeIds, secrets, workflowUid, callbackUrl) => {
 		if (!secrets?.project || !secrets?.secret || !secrets?.proxy) throw Error("The Smartling adapter requires a project ID, a secret key, and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.");
 		let accessToken = await authenticate(secrets), taskId = await findExistingJob(document.name, secrets, accessToken);
-		return taskId ||= await createJob(document.name, secrets, localeIds, accessToken, documentId), await uploadFileToBatch(await createJobBatch(taskId, secrets, documentId, accessToken, localeIds, workflowUid), documentId, document, secrets, localeIds, accessToken, callbackUrl), getTranslationTask(documentId, secrets);
+		taskId ||= await createJob(document.name, secrets, localeIds, accessToken, documentId);
+		let batchUid = await createJobBatch(taskId, secrets, documentId, accessToken, localeIds, workflowUid);
+		return await uploadFileToBatch(batchUid, documentId, document, secrets, localeIds, accessToken, callbackUrl), getTranslationTask(documentId, secrets);
 	},
 	getTranslation: async (taskId, localeId, secrets) => {
 		if (!secrets?.project || !secrets?.secret || !secrets?.proxy) throw Error("The Smartling adapter requires a project ID, a secret key, and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.");
 		let { project, proxy } = secrets, url = `https://api.smartling.com/files-api/v2/projects/${project}/locales/${localeId}/file?fileUri=${taskId}&retrievalType=pending`, accessToken = await authenticate(secrets);
Index: package/package.json
===================================================================
--- package/package.json
+++ package/package.json
@@ -1,7 +1,7 @@
 {
   "name": "sanity-plugin-studio-smartling",
-  "version": "5.0.7",
+  "version": "5.0.8",
   "description": "This plugin provides an in-studio integration with Smartling. It allows your editors to send any document to Smartling with the click of a button, monitor ongoing translations, and import partial or complete translations back into the studio.",
   "keywords": [
     "sanity",
     "sanity-plugin"
@@ -26,21 +26,21 @@
     ".": "./dist/index.js",
     "./package.json": "./package.json"
   },
   "dependencies": {
-    "sanity-translations-tab": "^6.1.11"
+    "sanity-translations-tab": "^6.1.12"
   },
   "devDependencies": {
     "@sanity/tsconfig": "^2.2.0",
-    "@sanity/tsdown-config": "^0.11.0",
+    "@sanity/tsdown-config": "^0.13.1",
     "@types/react": "^19.2.17",
     "@types/react-dom": "^19.2.3",
     "babel-plugin-react-compiler": "^1.0.0",
     "react": "^19.2.7",
     "react-dom": "^19.2.7",
     "sanity": "^6.3.0",
     "styled-components": "^6.4.3",
-    "tsdown": "^0.22.3"
+    "tsdown": "^0.22.5"
   },
   "peerDependencies": {
     "react": "^19.2",
     "react-dom": "^19.2",
Index: package/dist/index.d.ts.map
===================================================================
--- package/dist/index.d.ts.map
+++ package/dist/index.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"index.d.ts","names":[],"sources":["../src/adapter/index.ts","../src/index.ts"],"mappings":";cAOa,gBAAA,EAAkB,OAK9B;AAAA,cCcK,0BAAA,EAA4B,8BAGjC;AAAA,cAEK,yBAAA,EAA2B,8BAGhC;AAAA,cAEK,uBAAA,EAAyB,8BAG9B"}
\ No newline at end of file
+{"version":3,"file":"index.d.ts","names":[],"sources":["../src/adapter/index.ts","../src/index.ts"],"mappings":";cAOa,kBAAkB;cCmBzB,4BAA4B;cAK5B,2BAA2B;cAK3B,yBAAyB"}
\ No newline at end of file
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","authenticate","secrets","Promise","url","headers","secret","proxy","Error","fetch","method","body","JSON","stringify","then","res","json","response","data","accessToken","getHeaders","Record","findExistingJob","documentId","project","items","length","refUrl","fileUris","correctJob","filter","item","jobStatus","find","jobName","referenceNumber","translationJobUid","Adapter","Secrets","authenticate","getHeaders","findExistingJob","WorkflowProgressItem","workflowStepSummaryReportItemList","wordCount","SmartlingProgressItem","targetLocaleId","progress","percentComplete","totalWordCount","workflowProgressReportList","getTranslationTask","documentId","secrets","project","secret","proxy","taskId","locales","accessToken","progressUrl","smartlingTask","fetch","method","headers","then","res","json","response","data","contentProgressReport","map","item","progressItem","length","lastStep","at","Math","floor","localeId","linkToVendorTask","Adapter","Secrets","SerializedDocument","getTranslationTask","authenticate","getHeaders","findExistingJob","createJob","jobName","secrets","localeIds","accessToken","documentId","project","proxy","Error","url","fetch","method","headers","body","JSON","stringify","targetLocaleIds","referenceNumber","then","res","json","response","data","translationJobUid","createJobBatch","jobId","workflowUid","reqBody","authorize","fileUris","localeWorkflows","targetLocaleId","map","l","batchUid","uploadFileToBatch","document","callbackUrl","formData","FormData","append","Blob","content","name","forEach","localeId","createTask","secret","taskId","Adapter","Secrets","authenticate","getHeaders","getLocales","secrets","project","secret","proxy","url","accessToken","fetch","method","headers","then","res","json","response","data","targetLocales","Adapter","Secrets","authenticate","getHeaders","getTranslation","taskId","localeId","secrets","project","secret","proxy","Error","url","accessToken","translatedHTML","fetch","method","headers","then","res","json","body","response","errors","errMsg","message","Adapter","createTask","getLocales","getTranslation","getTranslationTask","SmartlingAdapter","baseLegacyDocumentLevelConfig"],"sources":["../src/adapter/helpers.ts","../src/adapter/getTranslationTask.ts","../src/adapter/createTask.ts","../src/adapter/getLocales.ts","../src/adapter/getTranslation.ts","../src/adapter/index.ts","../src/index.ts"],"sourcesContent":["import type {Secrets} from 'sanity-translations-tab'\n\nexport const authenticate = (secrets: Secrets): Promise<string> => {\n  const url = 'https://api.smartling.com/auth-api/v2/authenticate'\n  const headers = {\n    'content-type': 'application/json',\n    'X-URL': url,\n  }\n  const {secret, proxy} = secrets\n  if (!secret || !proxy) {\n    throw new Error(\n      'The Smartling adapter requires a secret key and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n    )\n  }\n  return fetch(proxy, {\n    headers,\n    method: 'POST',\n    body: JSON.stringify(secret),\n  })\n    .then((res) => res.json())\n    .then((res) => res.response.data.accessToken)\n}\n\nexport const getHeaders = (url: string, accessToken: string): Record<string, string> => ({\n  'Authorization': `Bearer ${accessToken}`,\n  'X-URL': url,\n})\n\nexport const findExistingJob = async (\n  documentId: string,\n  secrets: Secrets,\n  accessToken: string,\n): Promise<string> => {\n  const {project, proxy} = secrets\n  if (!project || !proxy) {\n    throw new Error(\n      'The Smartling adapter requires a Smartling project identifier and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n    )\n  }\n  const url = `https://api.smartling.com/jobs-api/v3/projects/${project}/jobs?jobName=${documentId}`\n  //first, try fetching from name resolution\n  let items = await fetch(proxy, {\n    headers: getHeaders(url, accessToken),\n  })\n    .then((res) => res.json())\n    .then((res) => res?.response?.data?.items)\n\n  if (!items || !items.length) {\n    //if that fails, try fetching by fileUri and check the referenceNumber\n    const refUrl = `https://api.smartling.com/jobs-api/v3/projects/${project}/jobs/search`\n    items = await fetch(proxy, {\n      headers: {\n        ...getHeaders(refUrl, accessToken),\n        'content-type': 'application/json',\n      },\n      method: 'POST',\n      body: JSON.stringify({\n        fileUris: [documentId],\n      }),\n    })\n      .then((res) => res.json())\n      .then((res) => res?.response?.data?.items)\n  }\n\n  if (items.length) {\n    //smartling will fuzzy match job names. We need to be precise.\n    const correctJob = items\n      .filter((item: {jobStatus: string}) => item.jobStatus !== 'DELETED')\n      .find(\n        (item: {jobName: string; referenceNumber: string}) =>\n          (item.jobName && item.jobName === documentId) ||\n          (item.referenceNumber && item.referenceNumber === documentId),\n      )\n\n    if (correctJob) {\n      return correctJob.translationJobUid\n    }\n  }\n  return ''\n}\n","import type {Adapter, Secrets} from 'sanity-translations-tab'\n\nimport {authenticate, getHeaders, findExistingJob} from './helpers'\n\ninterface WorkflowProgressItem {\n  workflowStepSummaryReportItemList: {\n    wordCount: number\n  }[]\n}\n\ninterface SmartlingProgressItem {\n  targetLocaleId: string\n  progress: {\n    percentComplete: number\n    totalWordCount: number\n  }\n  workflowProgressReportList: WorkflowProgressItem[]\n}\n\nexport const getTranslationTask: Adapter['getTranslationTask'] = async (\n  documentId: string,\n  secrets: Secrets | null,\n) => {\n  if (!secrets?.project || !secrets?.secret || !secrets?.proxy) {\n    return {\n      documentId,\n      taskId: documentId,\n      locales: [],\n    }\n  }\n\n  const {project, proxy} = secrets\n\n  const accessToken = await authenticate(secrets)\n  const taskId = await findExistingJob(documentId, secrets, accessToken)\n  if (!taskId) {\n    return {\n      documentId,\n      taskId: documentId,\n      locales: [],\n    }\n  }\n\n  const progressUrl = `https://api.smartling.com/jobs-api/v3/projects/${project}/jobs/${taskId}/progress`\n  const smartlingTask = await fetch(proxy, {\n    method: 'GET',\n    headers: getHeaders(progressUrl, accessToken),\n  })\n    .then((res) => res.json())\n    .then((res) => res.response.data)\n\n  let locales = []\n  if (smartlingTask && smartlingTask.contentProgressReport) {\n    locales = smartlingTask.contentProgressReport.map((item: SmartlingProgressItem) => {\n      let progress = item.progress ? item.progress.percentComplete : 0\n      //default to the first workflow -- it's likely what is being used\n      const progressItem = item.workflowProgressReportList?.[0]\n      if (progressItem && item.progress) {\n        //this is a list of the various steps in the workflow\n        if (\n          progressItem.workflowStepSummaryReportItemList &&\n          progressItem.workflowStepSummaryReportItemList.length > 1\n        ) {\n          //get the last step in the workflow -- usually \"published\"\n          const lastStep = progressItem.workflowStepSummaryReportItemList.at(-1)\n          //get the percentage of how many words have reached the last step\n          if (lastStep && lastStep.wordCount >= 0) {\n            progress = Math.floor((lastStep.wordCount / item.progress.totalWordCount) * 100) ?? 0\n          }\n        }\n      }\n      return {\n        localeId: item.targetLocaleId,\n        progress,\n      }\n    })\n  }\n\n  return {\n    documentId,\n    locales,\n    //since our download is tied to document id for smartling, keep track of it as a task\n    taskId: documentId,\n    linkToVendorTask: `https://dashboard.smartling.com/app/projects/${project}/account-jobs/${project}:${taskId}`,\n  }\n}\n","import type {Adapter, Secrets, SerializedDocument} from 'sanity-translations-tab'\n\nimport {getTranslationTask} from './getTranslationTask'\nimport {authenticate, getHeaders, findExistingJob} from './helpers'\n\nconst createJob = (\n  jobName: string,\n  secrets: Secrets,\n  localeIds: string[],\n  accessToken: string,\n  documentId: string,\n) => {\n  const {project, proxy} = secrets\n  if (!project || !proxy) {\n    throw new Error(\n      'The Smartling adapter requires a Smartling project identifier and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n    )\n  }\n\n  const url = `https://api.smartling.com/jobs-api/v3/projects/${project}/jobs`\n  return fetch(proxy, {\n    method: 'POST',\n    headers: {\n      ...getHeaders(url, accessToken),\n      'content-type': 'application/json',\n    },\n    body: JSON.stringify({\n      jobName,\n      targetLocaleIds: localeIds,\n      referenceNumber: documentId,\n    }),\n  })\n    .then((res) => res.json())\n    .then((res) => res.response.data.translationJobUid)\n}\n\n/* we're using batches here because it eliminates some\n * new string authorization issues for updating existing jobs,\n * and is able to be used for new bulk\n * job functionality.\n */\n\nconst createJobBatch = (\n  jobId: string,\n  secrets: Secrets,\n  documentId: string,\n  accessToken: string,\n  localeIds: string[],\n  workflowUid?: string,\n) => {\n  const {project, proxy} = secrets\n  if (!project || !proxy) {\n    throw new Error(\n      'The Smartling adapter requires a Smartling project identifier and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n    )\n  }\n  const url = `https://api.smartling.com/job-batches-api/v2/projects/${project}/batches`\n  const reqBody: {\n    authorize: boolean\n    translationJobUid: string\n    fileUris: string[]\n    localeWorkflows?: {targetLocaleId: string; workflowUid: string}[]\n  } = {\n    authorize: true,\n    translationJobUid: jobId,\n    fileUris: [documentId],\n  }\n\n  if (workflowUid) {\n    reqBody.localeWorkflows = localeIds.map((l) => ({\n      targetLocaleId: l,\n      workflowUid,\n    }))\n  }\n\n  return fetch(proxy, {\n    method: 'POST',\n    headers: {\n      ...getHeaders(url, accessToken),\n      'content-type': 'application/json',\n    },\n    body: JSON.stringify(reqBody),\n  })\n    .then((res) => res.json())\n    .then((res) => res.response.data.batchUid)\n}\n\nconst uploadFileToBatch = (\n  batchUid: string,\n  documentId: string,\n  document: SerializedDocument,\n  secrets: Secrets,\n  localeIds: string[],\n  accessToken: string,\n  callbackUrl?: string,\n) => {\n  const {project, proxy} = secrets\n  if (!project || !proxy) {\n    throw new Error(\n      'The Smartling adapter requires a Smartling project identifier and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n    )\n  }\n  const url = `https://api.smartling.com/job-batches-api/v2/projects/${project}/batches/${batchUid}/file`\n  const formData = new FormData()\n  formData.append('fileUri', documentId)\n  formData.append('fileType', 'html')\n  formData.append('file', new Blob([document.content]), `${document.name}.html`)\n  localeIds.forEach((localeId) => formData.append('localeIdsToAuthorize[]', localeId))\n  if (callbackUrl) {\n    formData.append('callbackUrl', callbackUrl)\n  }\n\n  return fetch(proxy, {\n    method: 'POST',\n    headers: getHeaders(url, accessToken),\n    body: formData,\n  }).then((res) => res.json())\n}\n\nexport const createTask: Adapter['createTask'] = async (\n  documentId: string,\n  document: SerializedDocument,\n  localeIds: string[],\n  secrets: Secrets | null,\n  workflowUid?: string,\n  callbackUrl?: string,\n) => {\n  if (!secrets?.project || !secrets?.secret || !secrets?.proxy) {\n    throw new Error(\n      'The Smartling adapter requires a project ID, a secret key, and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n    )\n  }\n\n  const accessToken = await authenticate(secrets)\n\n  let taskId = await findExistingJob(document.name, secrets, accessToken)\n  if (!taskId) {\n    taskId = await createJob(document.name, secrets, localeIds, accessToken, documentId)\n  }\n\n  const batchUid = await createJobBatch(\n    taskId,\n    secrets,\n    documentId,\n    accessToken,\n    localeIds,\n    workflowUid,\n  )\n  await uploadFileToBatch(\n    batchUid,\n    documentId,\n    document,\n    secrets,\n    localeIds,\n    accessToken,\n    callbackUrl,\n  )\n\n  return getTranslationTask(documentId, secrets)\n}\n","import type {Adapter, Secrets} from 'sanity-translations-tab'\n\nimport {authenticate, getHeaders} from './helpers'\n\nexport const getLocales: Adapter['getLocales'] = async (secrets: Secrets | null) => {\n  if (!secrets?.project || !secrets?.secret || !secrets?.proxy) {\n    return []\n  }\n  const {project, proxy} = secrets\n  const url = `https://api.smartling.com/projects-api/v2/projects/${project}`\n  const accessToken = await authenticate(secrets)\n  return fetch(proxy, {\n    method: 'GET',\n    headers: getHeaders(url, accessToken),\n  })\n    .then((res) => res.json())\n    .then((res) => res.response.data.targetLocales)\n}\n","import type {Adapter, Secrets} from 'sanity-translations-tab'\n\nimport {authenticate, getHeaders} from './helpers'\n\nexport const getTranslation: Adapter['getTranslation'] = async (\n  taskId: string,\n  localeId: string,\n  secrets: Secrets | null,\n) => {\n  if (!secrets?.project || !secrets?.secret || !secrets?.proxy) {\n    throw new Error(\n      'The Smartling adapter requires a project ID, a secret key, and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n    )\n  }\n\n  const {project, proxy} = secrets\n\n  const url = `https://api.smartling.com/files-api/v2/projects/${project}/locales/${localeId}/file?fileUri=${taskId}&retrievalType=pending`\n  const accessToken = await authenticate(secrets)\n  const translatedHTML = await fetch(proxy, {\n    method: 'GET',\n    headers: getHeaders(url, accessToken),\n  })\n    .then((res) => res.json())\n    .then((res) => {\n      if (res.body) {\n        return res.body\n      } else if (res.response.errors) {\n        const errMsg =\n          res.response.errors[0]?.message || 'Error retrieving translation from Smartling'\n        throw new Error(errMsg)\n      }\n      return ''\n    })\n\n  return translatedHTML\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 SmartlingAdapter: Adapter = {\n  getLocales,\n  getTranslationTask,\n  createTask,\n  getTranslation,\n}\n","import {\n  baseDocumentLevelConfig,\n  baseFieldLevelConfig,\n  legacyDocumentLevelConfig as baseLegacyDocumentLevelConfig,\n} from 'sanity-translations-tab'\nimport type {TranslationsTabConfigOptions} from 'sanity-translations-tab'\n\nimport {SmartlingAdapter} from './adapter'\n\nexport {\n  BaseDocumentDeserializer,\n  BaseDocumentMerger,\n  BaseDocumentSerializer,\n  customSerializers,\n  defaultStopTypes,\n  documentLevelPatch,\n  fieldLevelPatch,\n  findLatestDraft,\n  legacyDocumentLevelPatch,\n  TranslationsTab,\n} from 'sanity-translations-tab'\nexport type {\n  TranslationFunctionContext,\n  TranslationsTabConfigOptions,\n} from 'sanity-translations-tab'\n\nconst defaultDocumentLevelConfig: TranslationsTabConfigOptions = {\n  ...baseDocumentLevelConfig,\n  adapter: SmartlingAdapter,\n}\n\nconst legacyDocumentLevelConfig: TranslationsTabConfigOptions = {\n  ...baseLegacyDocumentLevelConfig,\n  adapter: SmartlingAdapter,\n}\n\nconst defaultFieldLevelConfig: TranslationsTabConfigOptions = {\n  ...baseFieldLevelConfig,\n  adapter: SmartlingAdapter,\n}\n\nexport {\n  defaultDocumentLevelConfig,\n  defaultFieldLevelConfig,\n  legacyDocumentLevelConfig,\n  SmartlingAdapter,\n}\n"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"index.js","names":["Secrets","authenticate","secrets","Promise","url","headers","secret","proxy","Error","fetch","method","body","JSON","stringify","then","res","json","response","data","accessToken","getHeaders","Record","findExistingJob","documentId","project","items","length","refUrl","fileUris","correctJob","filter","item","jobStatus","find","jobName","referenceNumber","translationJobUid","Adapter","Secrets","authenticate","getHeaders","findExistingJob","WorkflowProgressItem","workflowStepSummaryReportItemList","wordCount","SmartlingProgressItem","targetLocaleId","progress","percentComplete","totalWordCount","workflowProgressReportList","getTranslationTask","documentId","secrets","project","secret","proxy","taskId","locales","accessToken","progressUrl","smartlingTask","fetch","method","headers","then","res","json","response","data","contentProgressReport","map","item","progressItem","length","lastStep","at","Math","floor","localeId","linkToVendorTask","Adapter","Secrets","SerializedDocument","getTranslationTask","authenticate","getHeaders","findExistingJob","createJob","jobName","secrets","localeIds","accessToken","documentId","project","proxy","Error","url","fetch","method","headers","body","JSON","stringify","targetLocaleIds","referenceNumber","then","res","json","response","data","translationJobUid","createJobBatch","jobId","workflowUid","reqBody","authorize","fileUris","localeWorkflows","targetLocaleId","map","l","batchUid","uploadFileToBatch","document","callbackUrl","formData","FormData","append","Blob","content","name","forEach","localeId","createTask","secret","taskId","Adapter","Secrets","authenticate","getHeaders","getLocales","secrets","project","secret","proxy","url","accessToken","fetch","method","headers","then","res","json","response","data","targetLocales","Adapter","Secrets","authenticate","getHeaders","getTranslation","taskId","localeId","secrets","project","secret","proxy","Error","url","accessToken","translatedHTML","fetch","method","headers","then","res","json","body","response","errors","errMsg","message","Adapter","createTask","getLocales","getTranslation","getTranslationTask","SmartlingAdapter","baseLegacyDocumentLevelConfig"],"sources":["../src/adapter/helpers.ts","../src/adapter/getTranslationTask.ts","../src/adapter/createTask.ts","../src/adapter/getLocales.ts","../src/adapter/getTranslation.ts","../src/adapter/index.ts","../src/index.ts"],"sourcesContent":["import type {Secrets} from 'sanity-translations-tab'\n\nexport const authenticate = (secrets: Secrets): Promise<string> => {\n  const url = 'https://api.smartling.com/auth-api/v2/authenticate'\n  const headers = {\n    'content-type': 'application/json',\n    'X-URL': url,\n  }\n  const {secret, proxy} = secrets\n  if (!secret || !proxy) {\n    throw new Error(\n      'The Smartling adapter requires a secret key and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n    )\n  }\n  return fetch(proxy, {\n    headers,\n    method: 'POST',\n    body: JSON.stringify(secret),\n  })\n    .then((res) => res.json())\n    .then((res) => res.response.data.accessToken)\n}\n\nexport const getHeaders = (url: string, accessToken: string): Record<string, string> => ({\n  'Authorization': `Bearer ${accessToken}`,\n  'X-URL': url,\n})\n\nexport const findExistingJob = async (\n  documentId: string,\n  secrets: Secrets,\n  accessToken: string,\n): Promise<string> => {\n  const {project, proxy} = secrets\n  if (!project || !proxy) {\n    throw new Error(\n      'The Smartling adapter requires a Smartling project identifier and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n    )\n  }\n  const url = `https://api.smartling.com/jobs-api/v3/projects/${project}/jobs?jobName=${documentId}`\n  //first, try fetching from name resolution\n  let items = await fetch(proxy, {\n    headers: getHeaders(url, accessToken),\n  })\n    .then((res) => res.json())\n    .then((res) => res?.response?.data?.items)\n\n  if (!items || !items.length) {\n    //if that fails, try fetching by fileUri and check the referenceNumber\n    const refUrl = `https://api.smartling.com/jobs-api/v3/projects/${project}/jobs/search`\n    items = await fetch(proxy, {\n      headers: {\n        ...getHeaders(refUrl, accessToken),\n        'content-type': 'application/json',\n      },\n      method: 'POST',\n      body: JSON.stringify({\n        fileUris: [documentId],\n      }),\n    })\n      .then((res) => res.json())\n      .then((res) => res?.response?.data?.items)\n  }\n\n  if (items.length) {\n    //smartling will fuzzy match job names. We need to be precise.\n    const correctJob = items\n      .filter((item: {jobStatus: string}) => item.jobStatus !== 'DELETED')\n      .find(\n        (item: {jobName: string; referenceNumber: string}) =>\n          (item.jobName && item.jobName === documentId) ||\n          (item.referenceNumber && item.referenceNumber === documentId),\n      )\n\n    if (correctJob) {\n      return correctJob.translationJobUid\n    }\n  }\n  return ''\n}\n","import type {Adapter, Secrets} from 'sanity-translations-tab'\n\nimport {authenticate, getHeaders, findExistingJob} from './helpers'\n\ninterface WorkflowProgressItem {\n  workflowStepSummaryReportItemList: {\n    wordCount: number\n  }[]\n}\n\ninterface SmartlingProgressItem {\n  targetLocaleId: string\n  progress: {\n    percentComplete: number\n    totalWordCount: number\n  }\n  workflowProgressReportList: WorkflowProgressItem[]\n}\n\nexport const getTranslationTask: Adapter['getTranslationTask'] = async (\n  documentId: string,\n  secrets: Secrets | null,\n) => {\n  if (!secrets?.project || !secrets?.secret || !secrets?.proxy) {\n    return {\n      documentId,\n      taskId: documentId,\n      locales: [],\n    }\n  }\n\n  const {project, proxy} = secrets\n\n  const accessToken = await authenticate(secrets)\n  const taskId = await findExistingJob(documentId, secrets, accessToken)\n  if (!taskId) {\n    return {\n      documentId,\n      taskId: documentId,\n      locales: [],\n    }\n  }\n\n  const progressUrl = `https://api.smartling.com/jobs-api/v3/projects/${project}/jobs/${taskId}/progress`\n  const smartlingTask = await fetch(proxy, {\n    method: 'GET',\n    headers: getHeaders(progressUrl, accessToken),\n  })\n    .then((res) => res.json())\n    .then((res) => res.response.data)\n\n  let locales = []\n  if (smartlingTask && smartlingTask.contentProgressReport) {\n    locales = smartlingTask.contentProgressReport.map((item: SmartlingProgressItem) => {\n      let progress = item.progress ? item.progress.percentComplete : 0\n      //default to the first workflow -- it's likely what is being used\n      const progressItem = item.workflowProgressReportList?.[0]\n      if (progressItem && item.progress) {\n        //this is a list of the various steps in the workflow\n        if (\n          progressItem.workflowStepSummaryReportItemList &&\n          progressItem.workflowStepSummaryReportItemList.length > 1\n        ) {\n          //get the last step in the workflow -- usually \"published\"\n          const lastStep = progressItem.workflowStepSummaryReportItemList.at(-1)\n          //get the percentage of how many words have reached the last step\n          if (lastStep && lastStep.wordCount >= 0) {\n            progress = Math.floor((lastStep.wordCount / item.progress.totalWordCount) * 100) ?? 0\n          }\n        }\n      }\n      return {\n        localeId: item.targetLocaleId,\n        progress,\n      }\n    })\n  }\n\n  return {\n    documentId,\n    locales,\n    //since our download is tied to document id for smartling, keep track of it as a task\n    taskId: documentId,\n    linkToVendorTask: `https://dashboard.smartling.com/app/projects/${project}/account-jobs/${project}:${taskId}`,\n  }\n}\n","import type {Adapter, Secrets, SerializedDocument} from 'sanity-translations-tab'\n\nimport {getTranslationTask} from './getTranslationTask'\nimport {authenticate, getHeaders, findExistingJob} from './helpers'\n\nconst createJob = (\n  jobName: string,\n  secrets: Secrets,\n  localeIds: string[],\n  accessToken: string,\n  documentId: string,\n) => {\n  const {project, proxy} = secrets\n  if (!project || !proxy) {\n    throw new Error(\n      'The Smartling adapter requires a Smartling project identifier and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n    )\n  }\n\n  const url = `https://api.smartling.com/jobs-api/v3/projects/${project}/jobs`\n  return fetch(proxy, {\n    method: 'POST',\n    headers: {\n      ...getHeaders(url, accessToken),\n      'content-type': 'application/json',\n    },\n    body: JSON.stringify({\n      jobName,\n      targetLocaleIds: localeIds,\n      referenceNumber: documentId,\n    }),\n  })\n    .then((res) => res.json())\n    .then((res) => res.response.data.translationJobUid)\n}\n\n/* we're using batches here because it eliminates some\n * new string authorization issues for updating existing jobs,\n * and is able to be used for new bulk\n * job functionality.\n */\n\nconst createJobBatch = (\n  jobId: string,\n  secrets: Secrets,\n  documentId: string,\n  accessToken: string,\n  localeIds: string[],\n  workflowUid?: string,\n) => {\n  const {project, proxy} = secrets\n  if (!project || !proxy) {\n    throw new Error(\n      'The Smartling adapter requires a Smartling project identifier and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n    )\n  }\n  const url = `https://api.smartling.com/job-batches-api/v2/projects/${project}/batches`\n  const reqBody: {\n    authorize: boolean\n    translationJobUid: string\n    fileUris: string[]\n    localeWorkflows?: {targetLocaleId: string; workflowUid: string}[]\n  } = {\n    authorize: true,\n    translationJobUid: jobId,\n    fileUris: [documentId],\n  }\n\n  if (workflowUid) {\n    reqBody.localeWorkflows = localeIds.map((l) => ({\n      targetLocaleId: l,\n      workflowUid,\n    }))\n  }\n\n  return fetch(proxy, {\n    method: 'POST',\n    headers: {\n      ...getHeaders(url, accessToken),\n      'content-type': 'application/json',\n    },\n    body: JSON.stringify(reqBody),\n  })\n    .then((res) => res.json())\n    .then((res) => res.response.data.batchUid)\n}\n\nconst uploadFileToBatch = (\n  batchUid: string,\n  documentId: string,\n  document: SerializedDocument,\n  secrets: Secrets,\n  localeIds: string[],\n  accessToken: string,\n  callbackUrl?: string,\n) => {\n  const {project, proxy} = secrets\n  if (!project || !proxy) {\n    throw new Error(\n      'The Smartling adapter requires a Smartling project identifier and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n    )\n  }\n  const url = `https://api.smartling.com/job-batches-api/v2/projects/${project}/batches/${batchUid}/file`\n  const formData = new FormData()\n  formData.append('fileUri', documentId)\n  formData.append('fileType', 'html')\n  formData.append('file', new Blob([document.content]), `${document.name}.html`)\n  localeIds.forEach((localeId) => formData.append('localeIdsToAuthorize[]', localeId))\n  if (callbackUrl) {\n    formData.append('callbackUrl', callbackUrl)\n  }\n\n  return fetch(proxy, {\n    method: 'POST',\n    headers: getHeaders(url, accessToken),\n    body: formData,\n  }).then((res) => res.json())\n}\n\nexport const createTask: Adapter['createTask'] = async (\n  documentId: string,\n  document: SerializedDocument,\n  localeIds: string[],\n  secrets: Secrets | null,\n  workflowUid?: string,\n  callbackUrl?: string,\n) => {\n  if (!secrets?.project || !secrets?.secret || !secrets?.proxy) {\n    throw new Error(\n      'The Smartling adapter requires a project ID, a secret key, and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n    )\n  }\n\n  const accessToken = await authenticate(secrets)\n\n  let taskId = await findExistingJob(document.name, secrets, accessToken)\n  if (!taskId) {\n    taskId = await createJob(document.name, secrets, localeIds, accessToken, documentId)\n  }\n\n  const batchUid = await createJobBatch(\n    taskId,\n    secrets,\n    documentId,\n    accessToken,\n    localeIds,\n    workflowUid,\n  )\n  await uploadFileToBatch(\n    batchUid,\n    documentId,\n    document,\n    secrets,\n    localeIds,\n    accessToken,\n    callbackUrl,\n  )\n\n  return getTranslationTask(documentId, secrets)\n}\n","import type {Adapter, Secrets} from 'sanity-translations-tab'\n\nimport {authenticate, getHeaders} from './helpers'\n\nexport const getLocales: Adapter['getLocales'] = async (secrets: Secrets | null) => {\n  if (!secrets?.project || !secrets?.secret || !secrets?.proxy) {\n    return []\n  }\n  const {project, proxy} = secrets\n  const url = `https://api.smartling.com/projects-api/v2/projects/${project}`\n  const accessToken = await authenticate(secrets)\n  return fetch(proxy, {\n    method: 'GET',\n    headers: getHeaders(url, accessToken),\n  })\n    .then((res) => res.json())\n    .then((res) => res.response.data.targetLocales)\n}\n","import type {Adapter, Secrets} from 'sanity-translations-tab'\n\nimport {authenticate, getHeaders} from './helpers'\n\nexport const getTranslation: Adapter['getTranslation'] = async (\n  taskId: string,\n  localeId: string,\n  secrets: Secrets | null,\n) => {\n  if (!secrets?.project || !secrets?.secret || !secrets?.proxy) {\n    throw new Error(\n      'The Smartling adapter requires a project ID, a secret key, and a proxy URL. Please check your secrets document in this dataset, per the plugin documentation.',\n    )\n  }\n\n  const {project, proxy} = secrets\n\n  const url = `https://api.smartling.com/files-api/v2/projects/${project}/locales/${localeId}/file?fileUri=${taskId}&retrievalType=pending`\n  const accessToken = await authenticate(secrets)\n  const translatedHTML = await fetch(proxy, {\n    method: 'GET',\n    headers: getHeaders(url, accessToken),\n  })\n    .then((res) => res.json())\n    .then((res) => {\n      if (res.body) {\n        return res.body\n      } else if (res.response.errors) {\n        const errMsg =\n          res.response.errors[0]?.message || 'Error retrieving translation from Smartling'\n        throw new Error(errMsg)\n      }\n      return ''\n    })\n\n  return translatedHTML\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 SmartlingAdapter: Adapter = {\n  getLocales,\n  getTranslationTask,\n  createTask,\n  getTranslation,\n}\n","import {\n  baseDocumentLevelConfig,\n  baseFieldLevelConfig,\n  legacyDocumentLevelConfig as baseLegacyDocumentLevelConfig,\n} from 'sanity-translations-tab'\nimport type {TranslationsTabConfigOptions} from 'sanity-translations-tab'\n\nimport {SmartlingAdapter} from './adapter'\n\nexport {\n  BaseDocumentDeserializer,\n  BaseDocumentMerger,\n  BaseDocumentSerializer,\n  customSerializers,\n  defaultStopTypes,\n  documentLevelPatch,\n  fieldLevelPatch,\n  findLatestDraft,\n  legacyDocumentLevelPatch,\n  TranslationsTab,\n} from 'sanity-translations-tab'\nexport type {\n  TranslationFunctionContext,\n  TranslationsTabConfigOptions,\n} from 'sanity-translations-tab'\n\nconst defaultDocumentLevelConfig: TranslationsTabConfigOptions = {\n  ...baseDocumentLevelConfig,\n  adapter: SmartlingAdapter,\n}\n\nconst legacyDocumentLevelConfig: TranslationsTabConfigOptions = {\n  ...baseLegacyDocumentLevelConfig,\n  adapter: SmartlingAdapter,\n}\n\nconst defaultFieldLevelConfig: TranslationsTabConfigOptions = {\n  ...baseFieldLevelConfig,\n  adapter: SmartlingAdapter,\n}\n\nexport {\n  defaultDocumentLevelConfig,\n  defaultFieldLevelConfig,\n  legacyDocumentLevelConfig,\n  SmartlingAdapter,\n}\n"],"mappings":"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"}
\ No newline at end of file