sanity-plugin-studio-smartling
5.0.175.0.18
dist/index.js.map~
dist/index.js.mapModified+1−1
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","then","res","json","accessToken","response","data","errMsg","errors","message","getHeaders","Record","findExistingJob","documentId","project","items","length","refUrl","JSON","stringify","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","baseDocumentLevelConfig","baseFieldLevelConfig","legacyDocumentLevelConfig","baseLegacyDocumentLevelConfig","TranslationsTabConfigOptions","SmartlingAdapter","BaseDocumentDeserializer","BaseDocumentMerger","BaseDocumentSerializer","customSerializers","defaultStopTypes","documentLevelPatch","fieldLevelPatch","findLatestDraft","legacyDocumentLevelPatch","TranslationsTab","TranslationFunctionContext","defaultDocumentLevelConfig","adapter","defaultFieldLevelConfig"],"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 // `secret` is already a JSON string (e.g. `{\"userIdentifier\":\"…\",\"userSecret\":\"…\"}`),\n // so it is sent as-is. Wrapping it in `JSON.stringify` would double-encode it into a\n // quoted string and break authentication with proxies that forward the body verbatim.\n return fetch(proxy, {\n headers,\n method: 'POST',\n body: secret,\n })\n .then((res) => res.json())\n .then((res) => {\n const accessToken = res?.response?.data?.accessToken\n if (!accessToken) {\n const errMsg =\n res?.response?.errors?.[0]?.message ||\n 'Could not authenticate with Smartling. Please check your secret key and proxy URL, per the plugin documentation.'\n throw new Error(errMsg)\n }\n return accessToken\n })\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 //guard against a 0 totalWordCount (e.g. empty documents) which would\n //otherwise produce NaN/Infinity and surface as an invalid percentage\n if (lastStep && lastStep.wordCount >= 0 && item.progress.totalWordCount > 0) {\n progress = Math.floor((lastStep.wordCount / item.progress.totalWordCount) * 100)\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":[],"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 // `secret` is already a JSON string (e.g. `{\"userIdentifier\":\"…\",\"userSecret\":\"…\"}`),\n // so it is sent as-is. Wrapping it in `JSON.stringify` would double-encode it into a\n // quoted string and break authentication with proxies that forward the body verbatim.\n return fetch(proxy, {\n headers,\n method: 'POST',\n body: secret,\n })\n .then((res) => res.json())\n .then((res) => {\n const accessToken = res?.response?.data?.accessToken\n if (!accessToken) {\n const errMsg =\n res?.response?.errors?.[0]?.message ||\n 'Could not authenticate with Smartling. Please check your secret key and proxy URL, per the plugin documentation.'\n throw new Error(errMsg)\n }\n return accessToken\n })\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 //guard against a 0 totalWordCount (e.g. empty documents) which would\n //otherwise produce NaN/Infinity and surface as an invalid percentage\n if (lastStep && lastStep.wordCount >= 0 && item.progress.totalWordCount > 0) {\n progress = Math.floor((lastStep.wordCount / item.progress.totalWordCount) * 100)\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":";AAEA,MAAa,gBAAgB,YAAsC;CAEjE,IAAM,UAAU;EACd,gBAAgB;EAChB,SAAS;CACX,GACM,EAAC,QAAQ,UAAS;CACxB,IAAI,CAAC,UAAU,CAAC,OACd,MAAU,MACR,gJACF;CAKF,OAAO,MAAM,OAAO;EAClB;EACA,QAAQ;EACR,MAAM;CACR,CAAC,CAAC,CACC,MAAM,QAAQ,IAAI,KAAK,CAAC,CAAC,CACzB,MAAM,QAAQ;EACb,IAAM,cAAc,KAAK,UAAU,MAAM;EACzC,IAAI,CAAC,aAAa;GAChB,IAAM,SACJ,KAAK,UAAU,SAAS,EAAE,EAAE,WAC5B;GACF,MAAU,MAAM,MAAM;EACxB;EACA,OAAO;CACT,CAAC;AACL,GAEa,cAAc,KAAa,iBAAiD;CACvF,eAAiB,UAAU;CAC3B,SAAS;AACX,IAEa,kBAAkB,OAC7B,YACA,SACA,gBACoB;CACpB,IAAM,EAAC,SAAS,UAAS;CACzB,IAAI,CAAC,WAAW,CAAC,OACf,MAAU,MACR,kKACF;CAEF,IAAM,MAAM,kDAAkD,QAAQ,gBAAgB,cAElF,QAAQ,MAAM,MAAM,OAAO,EAC7B,SAAS,WAAW,KAAK,WAAW,EACtC,CAAC,CAAC,CACC,MAAM,QAAQ,IAAI,KAAK,CAAC,CAAC,CACzB,MAAM,QAAQ,KAAK,UAAU,MAAM,KAAK;CAE3C,IAAI,CAAC,SAAS,CAAC,MAAM,QAAQ;EAE3B,IAAM,SAAS,kDAAkD,QAAQ;EACzE,QAAQ,MAAM,MAAM,OAAO;GACzB,SAAS;IACP,GAAG,WAAW,QAAQ,WAAW;IACjC,gBAAgB;GAClB;GACA,QAAQ;GACR,MAAM,KAAK,UAAU,EACnB,UAAU,CAAC,UAAU,EACvB,CAAC;EACH,CAAC,CAAC,CACC,MAAM,QAAQ,IAAI,KAAK,CAAC,CAAC,CACzB,MAAM,QAAQ,KAAK,UAAU,MAAM,KAAK;CAC7C;CAEA,IAAI,OAAO,QAAQ;EAEjB,IAAM,aAAa,MAChB,QAAQ,SAA8B,KAAK,cAAc,SAAS,CAAC,CACnE,MACE,SACE,KAAK,WAAW,KAAK,YAAY,cACjC,KAAK,mBAAmB,KAAK,oBAAoB,UACtD;EAEF,IAAI,YACF,OAAO,WAAW;CAEtB;CACA,OAAO;AACT,GCxEa,qBAAoD,OAC/D,YACA,YACG;CACH,IAAI,CAAC,SAAS,WAAW,CAAC,SAAS,UAAU,CAAC,SAAS,OACrD,OAAO;EACL;EACA,QAAQ;EACR,SAAS,CAAC;CACZ;CAGF,IAAM,EAAC,SAAS,UAAS,SAEnB,cAAc,MAAM,aAAa,OAAO,GACxC,SAAS,MAAM,gBAAgB,YAAY,SAAS,WAAW;CACrE,IAAI,CAAC,QACH,OAAO;EACL;EACA,QAAQ;EACR,SAAS,CAAC;CACZ;CAGF,IAAM,cAAc,kDAAkD,QAAQ,QAAQ,OAAO,YACvF,gBAAgB,MAAM,MAAM,OAAO;EACvC,QAAQ;EACR,SAAS,WAAW,aAAa,WAAW;CAC9C,CAAC,CAAC,CACC,MAAM,QAAQ,IAAI,KAAK,CAAC,CAAC,CACzB,MAAM,QAAQ,IAAI,SAAS,IAAI,GAE9B,UAAU,CAAC;CA6Bf,OA5BI,iBAAiB,cAAc,0BACjC,UAAU,cAAc,sBAAsB,KAAK,SAAgC;EACjF,IAAI,WAAW,KAAK,WAAW,KAAK,SAAS,kBAAkB,GAEzD,eAAe,KAAK,6BAA6B;EACvD,IAAI,gBAAgB,KAAK,YAGrB,aAAa,qCACb,aAAa,kCAAkC,SAAS,GACxD;GAEA,IAAM,WAAW,aAAa,kCAAkC,GAAG,EAAE;GAIrE,AAAI,YAAY,SAAS,aAAa,KAAK,KAAK,SAAS,iBAAiB,MACxE,WAAW,KAAK,MAAO,SAAS,YAAY,KAAK,SAAS,iBAAkB,GAAG;EAEnF;EAEF,OAAO;GACL,UAAU,KAAK;GACf;EACF;CACF,CAAC,IAGI;EACL;EACA;EAEA,QAAQ;EACR,kBAAkB,gDAAgD,QAAQ,gBAAgB,QAAQ,GAAG;CACvG;AACF,GClFM,aACJ,SACA,SACA,WACA,aACA,eACG;CACH,IAAM,EAAC,SAAS,UAAS;CACzB,IAAI,CAAC,WAAW,CAAC,OACf,MAAU,MACR,kKACF;CAGF,IAAM,MAAM,kDAAkD,QAAQ;CACtE,OAAO,MAAM,OAAO;EAClB,QAAQ;EACR,SAAS;GACP,GAAG,WAAW,KAAK,WAAW;GAC9B,gBAAgB;EAClB;EACA,MAAM,KAAK,UAAU;GACnB;GACA,iBAAiB;GACjB,iBAAiB;EACnB,CAAC;CACH,CAAC,CAAC,CACC,MAAM,QAAQ,IAAI,KAAK,CAAC,CAAC,CACzB,MAAM,QAAQ,IAAI,SAAS,KAAK,iBAAiB;AACtD,GAQM,kBACJ,OACA,SACA,YACA,aACA,WACA,gBACG;CACH,IAAM,EAAC,SAAS,UAAS;CACzB,IAAI,CAAC,WAAW,CAAC,OACf,MAAU,MACR,kKACF;CAEF,IAAM,MAAM,yDAAyD,QAAQ,WACvE,UAKF;EACF,WAAW;EACX,mBAAmB;EACnB,UAAU,CAAC,UAAU;CACvB;CASA,OAPI,gBACF,QAAQ,kBAAkB,UAAU,KAAK,OAAO;EAC9C,gBAAgB;EAChB;CACF,EAAE,IAGG,MAAM,OAAO;EAClB,QAAQ;EACR,SAAS;GACP,GAAG,WAAW,KAAK,WAAW;GAC9B,gBAAgB;EAClB;EACA,MAAM,KAAK,UAAU,OAAO;CAC9B,CAAC,CAAC,CACC,MAAM,QAAQ,IAAI,KAAK,CAAC,CAAC,CACzB,MAAM,QAAQ,IAAI,SAAS,KAAK,QAAQ;AAC7C,GAEM,qBACJ,UACA,YACA,UACA,SACA,WACA,aACA,gBACG;CACH,IAAM,EAAC,SAAS,UAAS;CACzB,IAAI,CAAC,WAAW,CAAC,OACf,MAAU,MACR,kKACF;CAEF,IAAM,MAAM,yDAAyD,QAAQ,WAAW,SAAS,QAC3F,WAAW,IAAI,SAAS;CAS9B,OARA,SAAS,OAAO,WAAW,UAAU,GACrC,SAAS,OAAO,YAAY,MAAM,GAClC,SAAS,OAAO,QAAQ,IAAI,KAAK,CAAC,SAAS,OAAO,CAAC,GAAG,GAAG,SAAS,KAAK,MAAM,GAC7E,UAAU,SAAS,aAAa,SAAS,OAAO,0BAA0B,QAAQ,CAAC,GAC/E,eACF,SAAS,OAAO,eAAe,WAAW,GAGrC,MAAM,OAAO;EAClB,QAAQ;EACR,SAAS,WAAW,KAAK,WAAW;EACpC,MAAM;CACR,CAAC,CAAC,CAAC,MAAM,QAAQ,IAAI,KAAK,CAAC;AAC7B,GAEa,aAAoC,OAC/C,YACA,UACA,WACA,SACA,aACA,gBACG;CACH,IAAI,CAAC,SAAS,WAAW,CAAC,SAAS,UAAU,CAAC,SAAS,OACrD,MAAU,MACR,+JACF;CAGF,IAAM,cAAc,MAAM,aAAa,OAAO,GAE1C,SAAS,MAAM,gBAAgB,SAAS,MAAM,SAAS,WAAW;CACtE,AACE,WAAS,MAAM,UAAU,SAAS,MAAM,SAAS,WAAW,aAAa,UAAU;CAGrF,IAAM,WAAW,MAAM,eACrB,QACA,SACA,YACA,aACA,WACA,WACF;CAWA,OAVA,MAAM,kBACJ,UACA,YACA,UACA,SACA,WACA,aACA,WACF,GAEO,mBAAmB,YAAY,OAAO;AAC/C,GC3Ja,aAAoC,OAAO,YAA4B;CAClF,IAAI,CAAC,SAAS,WAAW,CAAC,SAAS,UAAU,CAAC,SAAS,OACrD,OAAO,CAAC;CAEV,IAAM,EAAC,SAAS,UAAS,SACnB,MAAM,sDAAsD,WAC5D,cAAc,MAAM,aAAa,OAAO;CAC9C,OAAO,MAAM,OAAO;EAClB,QAAQ;EACR,SAAS,WAAW,KAAK,WAAW;CACtC,CAAC,CAAC,CACC,MAAM,QAAQ,IAAI,KAAK,CAAC,CAAC,CACzB,MAAM,QAAQ,IAAI,SAAS,KAAK,aAAa;AAClD,GCba,iBAA4C,OACvD,QACA,UACA,YACG;CACH,IAAI,CAAC,SAAS,WAAW,CAAC,SAAS,UAAU,CAAC,SAAS,OACrD,MAAU,MACR,+JACF;CAGF,IAAM,EAAC,SAAS,UAAS,SAEnB,MAAM,mDAAmD,QAAQ,WAAW,SAAS,gBAAgB,OAAO,yBAC5G,cAAc,MAAM,aAAa,OAAO;CAiB9C,OAAO,MAhBsB,MAAM,OAAO;EACxC,QAAQ;EACR,SAAS,WAAW,KAAK,WAAW;CACtC,CAAC,CAAC,CACC,MAAM,QAAQ,IAAI,KAAK,CAAC,CAAC,CACzB,MAAM,QAAQ;EACb,IAAI,IAAI,MACN,OAAO,IAAI;EACN,IAAI,IAAI,UAAU,QAAQ;GAC/B,IAAM,SACJ,IAAI,SAAS,OAAO,EAAE,EAAE,WAAW;GACrC,MAAU,MAAM,MAAM;EACxB;EACA,OAAO;CACT,CAAC;AAGL,GC7Ba,mBAA4B;CACvC;CACA;CACA;CACA;AACF,GCcM,6BAA2D;CAC/D,GAAG;CACH,SAAS;AACX,GAEM,4BAA0D;CAC9D,GAAG;CACH,SAAS;AACX,GAEM,0BAAwD;CAC5D,GAAG;CACH,SAAS;AACX"}
\ No newline at end of file