@sanity/cross-dataset-duplicator

2.1.62.1.7
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":["CrossDatasetDuplicatorContext.Provider","pluginConfig","props.renderDefault(rest)","<CrossDatasetDuplicatorContext.Provider value={pluginConfig}>\n      {props.renderDefault(rest)}\n    </CrossDatasetDuplicatorContext.Provider>","_c","tone = 'caution'","<Text size={1}>{children}</Text>","<Card padding={3} radius={2} shadow={1} tone={tone}>\n      <Text size={1}>{children}</Text>\n    </Card>","_c","() =>\n    payload.length && payload.every((item) => item.include) ? ['ALL'] : []","payload.length","(item) => item.include","function handleSelectButton(action: Action) {\n    if (!payload.length) return\n\n    setPayload((current) =>\n      current.map((item) => ({...item, include: shouldInclude(item, action)})),\n    )\n    setDisabledActions([action])\n  }","length","item","buttons.map((button) =>\n          'action' in button ? (\n            <Button\n              key={button.action}\n              fontSize={1}\n              mode=\"bleed\"\n              padding={2}\n              text={button.label}\n              disabled={disabledActions.includes(button.action)}\n              onClick={() => handleSelectButton(button.action)}\n            />\n          ) : (\n            <Card key={button.divider} borderLeft />\n          ),\n        )","<Card padding={1} radius={3} shadow={1}>\n      <Flex gap={2} wrap=\"wrap\">\n        {buttons.map((button) =>\n          'action' in button ? (\n            <Button\n              key={button.action}\n              fontSize={1}\n              mode=\"bleed\"\n              padding={2}\n              text={button.label}\n              disabled={disabledActions.includes(button.action)}\n              onClick={() => handleSelectButton(button.action)}\n            />\n          ) : (\n            <Card key={button.divider} borderLeft />\n          ),\n        )}\n      </Flex>\n    </Card>","_c","_temp","<Badge padding={2} fontSize={1}>\n        Checking...\n      </Badge>","{maxWidth: 200}","<Box padding={3} style={{maxWidth: 200}}>\n          <Text size={1}>{badgeText}</Text>\n        </Box>","['right', 'left']","<Box marginLeft={2} display={'inline-block'} as=\"span\">\n          <InfoOutlineIcon />\n        </Box>","<Badge padding={3} fontSize={1} tone={badgeTone}>\n        {badgeStatus}\n        <Box marginLeft={2} display={'inline-block'} as=\"span\">\n          <InfoOutlineIcon />\n        </Box>\n      </Badge>","<Tooltip\n      content={\n        <Box padding={3} style={{maxWidth: 200}}>\n          <Text size={1}>{badgeText}</Text>\n        </Box>\n      }\n      fallbackPlacements={['right', 'left']}\n      placement=\"top\"\n      portal\n    >\n      <Badge padding={3} fontSize={1} tone={badgeTone}>\n        {badgeStatus}\n        <Box marginLeft={2} display={'inline-block'} as=\"span\">\n          <InfoOutlineIcon />\n        </Box>\n      </Badge>\n    </Tooltip>","_c","{apiVersion: pluginConfig.apiVersion}","apiVersion","workspace","(space) => !space.disabled","[]","[0, 0]","(acc, doc) => acc + extractWithPath(`.._ref`, doc).length","hasReferences\n    ? {tone: `caution`, text: createInitialMessage(docs.length, initialRefsCount)}\n    : null","length","async function updatePayloadStatuses(payloadActual: PayloadItem[], dest: WorkspaceOption | null) {\n    if (!payloadActual.length || !dest?.name) {\n      return\n    }\n\n    const payloadIds = payloadActual.map(({doc}) => doc._id)\n    const destinationClient = originClient.withConfig({\n      dataset: dest.dataset,\n      projectId: dest.projectId,\n    })\n    const destinationData = await destinationClient.fetch<SanityDocument[]>(\n      `*[_id in $payloadIds]{ _id, _updatedAt }`,\n      {payloadIds},\n    )\n    // Index the destination docs by `_id` so status updates stay O(n) instead\n    // of O(n²) when looking them up for each payload item below.\n    const destinationById = new Map(destinationData.map((doc) => [doc._id, doc]))\n\n    setPayload(\n      payloadActual.map((item) => {\n        const existingDoc = destinationById.get(item.doc._id)\n        let status: keyof MessageTypes = 'CREATE'\n\n        if (existingDoc?._updatedAt && item.doc._updatedAt) {\n          if (existingDoc._updatedAt === item.doc._updatedAt) {\n            // Exact same document exists at destination\n            // We don't compare by _rev because that is updated in a transaction\n            status = `EXISTS`\n          } else {\n            status =\n              new Date(existingDoc._updatedAt) > new Date(item.doc._updatedAt)\n                ? // Document at destination is newer\n                  `OVERWRITE`\n                : // Document at destination is older\n                  `UPDATE`\n          }\n        }\n\n        return {...item, status}\n      }),\n    )\n  }","({doc}) => doc._id","(doc) => [doc._id, doc]","(nextDocs: SanityDocument[]) => {\n    const initialPayload: PayloadItem[] = nextDocs.map((doc) => ({include: true, doc}))\n    updatePayloadStatuses(initialPayload, destination).catch(console.error)\n  }","(doc) => ({include: true, doc})","() => {\n    // oxlint-disable-next-line react/set-state-in-effect\n    initializePayload(docs)\n  }","[docs]","function handleCheckbox(_id: string) {\n    setPayload((current) =>\n      current.map((item) => (item.doc._id === _id ? {...item, include: !item.include} : item)),\n    )\n  }","item","async function handleReferences() {\n    setIsGathering(true)\n\n    try {\n      const docIds = docs.map((doc) => doc._id)\n\n      const payloadDocs = await getDocumentsInArray({\n        fetchIds: docIds,\n        client: originClient,\n        pluginConfig,\n      })\n      const draftDocs = await getDocumentsInArray({\n        fetchIds: docIds.map((id) => `drafts.${id}`),\n        client: originClient,\n        projection: `{_id}`,\n        pluginConfig,\n      })\n      const draftDocsIds = new Set(draftDocs.map(({_id}) => _id))\n\n      // Shape it up\n      const payloadShaped: PayloadItem[] = payloadDocs.map((doc) => ({\n        doc,\n        // Include this in the transaction?\n        include: true,\n        // Does it exist at the destination?\n        status: undefined,\n        // Does it have any drafts?\n        hasDraft: draftDocsIds.has(`drafts.${doc._id}`),\n      }))\n\n      setPayload(payloadShaped)\n      updatePayloadStatuses(payloadShaped, destination).catch(console.error)\n    } catch (err) {\n      console.error(err)\n    }\n\n    setIsGathering(false)\n  }","(doc) => doc._id","(id) => `drafts.${id}`","({_id}) => _id","doc","err","async function handleDuplicate() {\n    if (!destination) {\n      return\n    }\n\n    setIsDuplicating(true)\n\n    const assetsCount = payload.filter(({doc, include}) => include && isAssetId(doc._id)).length\n    let currentProgress = 0\n    setProgress([currentProgress, assetsCount])\n\n    setMessage({text: 'Duplicating...', tone: `transparent`})\n\n    const destinationClient = originClient.withConfig({\n      apiVersion: pluginConfig.apiVersion,\n      dataset: destination.dataset,\n      projectId: destination.projectId,\n    })\n\n    const transactionDocs: SanityDocument[] = []\n    const svgMaps: {old: string; new: string}[] = []\n\n    // Upload assets and then add to transaction\n    async function processDoc(doc: SanityDocument): Promise<void> {\n      if (!isAssetDocument(doc)) {\n        transactionDocs.push(doc)\n\n        return\n      }\n\n      // Download and upload asset\n      // Get the *original* image with this dlRaw param to create the same deterministic _id\n      const typeIsFile = isSanityFileAsset(doc)\n      const downloadUrl = typeIsFile ? doc.url : `${doc.url}?dlRaw=true`\n\n      const res = await fetch(downloadUrl, assetDownloadInit(downloadUrl, token, typeIsFile))\n\n      // Fail fast instead of uploading an error response (e.g. 401/403/404)\n      // body as the asset's binary data.\n      if (!res.ok) {\n        throw new Error(\n          `Failed to download asset \"${doc.originalFilename ?? doc._id}\" (${res.status} ${res.statusText})`,\n        )\n      }\n\n      const assetData = await res.blob()\n\n      const options = {filename: doc.originalFilename}\n      const assetDoc = await destinationClient.assets.upload(\n        typeIsFile ? `file` : `image`,\n        assetData,\n        options,\n      )\n\n      // SVG _id's need remapping before transaction\n      if (doc.extension === 'svg') {\n        svgMaps.push({old: doc._id, new: assetDoc._id})\n      }\n\n      // Merge the original asset document's editorial metadata (e.g. `altText`,\n      // `title`) — which the upload response omits — with the canonical fields of\n      // the freshly uploaded asset (`_id`, `url`, `path`, `assetId`, `sha1hash`,\n      // ...). The uploaded values win, so `url`/`path` no longer reference the\n      // origin dataset. For SVGs the uploaded `_id` differs from the source\n      // (the file is sanitized on upload), so pushing a single merged document at\n      // the new `_id` — and remapping references to it below — avoids leaving an\n      // orphaned asset document behind at the original `_id`.\n      transactionDocs.push({...doc, ...assetDoc})\n\n      currentProgress += 1\n      setMessage({\n        text: `Duplicating ${currentProgress}/${assetsCount} Assets`,\n        tone: 'default',\n      })\n      setProgress([currentProgress, assetsCount])\n    }\n\n    try {\n      const payloadIncludedDocs = payload.filter((item) => item.include).map((item) => item.doc)\n\n      // Promises are limited to three at once\n      await mapWithConcurrency(payloadIncludedDocs, 3, processDoc)\n    } catch (err) {\n      console.error(err)\n      setIsDuplicating(false)\n      setProgress([0, 0])\n      setMessage({\n        tone: 'critical',\n        text: err instanceof Error ? err.message : `Duplication Failed`,\n      })\n\n      return\n    }\n\n    // Remap SVG references to new _id's. SVG assets are sanitized on upload, so\n    // their `_id` changes; references still pointing at the original `_id` must\n    // be updated to the uploaded one.\n    const svgIdRemap = new Map(svgMaps.map(({old, new: next}) => [old, next]))\n    const transactionDocsMapped =\n      svgIdRemap.size === 0\n        ? transactionDocs\n        : transactionDocs.map((doc) => {\n            const references = extractWithPath(`.._ref`, doc)\n\n            if (!references.length) {\n              return doc\n            }\n\n            // Clone lazily before the first mutation: some of these docs are the\n            // same objects held in React state (`payload`), and `dset` mutates in\n            // place — which would corrupt state and trip up the React Compiler.\n            let mappedDoc = doc\n\n            references.forEach((ref) => {\n              const newRefValue =\n                typeof ref.value === 'string' ? svgIdRemap.get(ref.value) : undefined\n\n              if (newRefValue) {\n                if (mappedDoc === doc) {\n                  mappedDoc = structuredClone(doc)\n                }\n\n                dset(mappedDoc, ref.path.join('.'), newRefValue)\n              }\n            })\n\n            return mappedDoc\n          })\n\n    // Create transaction\n    const transaction = destinationClient.transaction()\n\n    transactionDocsMapped.forEach((doc) => {\n      transaction.createOrReplace(doc)\n    })\n\n    const onCommitSuccess = () => {\n      updatePayloadStatuses(payload, destination).catch(console.error)\n    }\n\n    try {\n      await transaction.commit()\n      setMessage({tone: 'positive', text: 'Duplication complete!'})\n\n      onCommitSuccess()\n    } catch (err) {\n      if (isReferenceMutationError(err)) {\n        await handleReferenceError({\n          err,\n          transactionDocs: transactionDocsMapped,\n          originClient,\n          destinationClient,\n          pluginConfig,\n          token,\n          setMessage,\n          onSuccess: onCommitSuccess,\n          excludedIds: new Set(payload.filter((item) => !item.include).map((item) => item.doc._id)),\n          svgMaps,\n        })\n      } else {\n        const description = getErrorDescription(err)\n        setMessage({\n          tone: 'critical',\n          text: description || `Duplication Failed`,\n        })\n      }\n    }\n\n    setIsDuplicating(false)\n    setProgress([0, 0])\n    if (onDuplicated) {\n      try {\n        await onDuplicated()\n      } catch (error) {\n        const text = error instanceof Error ? error.message : String(error)\n        setMessage({tone: 'critical', text: `Error in onDuplicated hook: ${text}`})\n      }\n    }\n  }","pluginConfig.apiVersion","({doc, include}) => include && isAssetId(doc._id)","destinationClient","(item) => item.include","(item) => item.doc","({old, new: next}) => [old, next]","(item) => !item.include","(item) => item.doc._id","error","space","payload.findIndex(({doc}) => doc['extension'] === 'svg')","({doc}) => doc['extension'] === 'svg'","payload.filter(\n    (item) => item.include && !isAssetId(item.doc._id),\n  )","(item) => item.include && !isAssetId(item.doc._id)","payload.filter(\n    (item) => item.include && isAssetId(item.doc._id),\n  )","(item) => item.include && isAssetId(item.doc._id)","(space) => space?.projectId","[selectedTotal, `/`, payloadCount, `Documents and Assets selected`]","projectId","<Feedback tone=\"critical\">\n        <code>sanity.config.ts</code> must contain at least two Workspaces to use this plugin.\n      </Feedback>","<Feedback tone=\"critical\">\n        No allowed Migration destinations are available for this Dataset. Check the{' '}\n        <code>migrationFilters</code> plugin config, or add another Workspace as a valid target.\n      </Feedback>","{flex: 1}","<Label>Duplicate from</Label>","<Box padding={4} paddingTop={5} paddingBottom={0}>\n                  <Text size={3}>\n                    <ArrowRightIcon />\n                  </Text>\n                </Box>","<Label>To Destination</Label>","<Select onChange={handleChange}>\n                    {workspacesOptions.map((space) => (\n                      <option key={space.name} value={space.name} disabled={space.disabled}>\n                        {space.title ?? space.name}\n                        {hasMultipleProjectIds ? ` (${space.projectId})` : ``}\n                        {currentWorkspace?.name === space.name &&\n                        currentWorkspace.projectId === space.projectId\n                          ? ` (Current)`\n                          : ``}\n                      </option>\n                    ))}\n                  </Select>","Select","workspacesOptions.map((space) => (\n                      <option key={space.name} value={space.name} disabled={space.disabled}>\n                        {space.title ?? space.name}\n                        {hasMultipleProjectIds ? ` (${space.projectId})` : ``}\n                        {currentWorkspace?.name === space.name &&\n                        currentWorkspace.projectId === space.projectId\n                          ? ` (Current)`\n                          : ``}\n                      </option>\n                    ))","<Stack style={{flex: 1}} gap={3}>\n                  <Label>To Destination</Label>\n                  <Select onChange={handleChange}>\n                    {workspacesOptions.map((space) => (\n                      <option key={space.name} value={space.name} disabled={space.disabled}>\n                        {space.title ?? space.name}\n                        {hasMultipleProjectIds ? ` (${space.projectId})` : ``}\n                        {currentWorkspace?.name === space.name &&\n                        currentWorkspace.projectId === space.projectId\n                          ? ` (Current)`\n                          : ``}\n                      </option>\n                    ))}\n                  </Select>\n                </Stack>","Stack","3","isDuplicating && (\n                <Card border radius={2}>\n                  <Card\n                    style={{\n                      width: '100%',\n                      // Guard against a 0-asset payload (progress[1] === 0),\n                      // which would make the ratio NaN and produce an invalid transform.\n                      transform: `scaleX(${progress[1] > 0 ? progress[0] / progress[1] : 0})`,\n                      transformOrigin: 'left',\n                      transition: 'transform .2s ease',\n                      boxSizing: 'border-box',\n                    }}\n                    padding={1}\n                    tone=\"positive\"\n                  />\n                </Card>\n              )","progress[1]","payload.length > 0 && (\n                <>\n                  <Label>{headingText}</Label>\n                  <SelectButtons payload={payload} setPayload={setPayload} />\n                </>\n              )","payload.length","displayMessage && (\n                <Card padding={3} radius={2} shadow={1} tone={displayMessage.tone}>\n                  <Text size={1}>{displayMessage.text}</Text>\n                </Card>\n              )","payload.length > 0 ? (\n                <Stack>\n                  {payload.map(({doc, include, status, hasDraft}, index) => {\n                    const schemaType = schema.get(doc._type)\n\n                    return (\n                      <Fragment key={doc._id}>\n                        <Flex align=\"center\">\n                          <Checkbox checked={include} onChange={() => handleCheckbox(doc._id)} />\n                          <Box flex={1} paddingX={3}>\n                            {schemaType ? (\n                              <Preview value={doc} schemaType={schemaType} />\n                            ) : (\n                              <Card tone=\"caution\">Invalid schema type</Card>\n                            )}\n                          </Box>\n                          <Flex align=\"center\" gap={2}>\n                            {hasDraft ? <StatusBadge status=\"UNPUBLISHED\" isAsset={false} /> : null}\n                            <StatusBadge status={status} isAsset={isAssetId(doc._id)} />\n                          </Flex>\n                        </Flex>\n                        {doc['extension'] === 'svg' && index === firstSvgIndex && (\n                          <Card padding={3} radius={2} shadow={1} tone=\"caution\">\n                            <Text size={1}>\n                              Due to how SVGs are sanitized after first uploaded, duplicated SVG\n                              assets may have new <code>_id</code>'s at the destination. The newly\n                              generated <code>_id</code> will be the same in each duplication, but\n                              it will never be the same <code>_id</code> as the first time this\n                              Asset was uploaded. References to the asset will be updated to use the\n                              new <code>_id</code>.\n                            </Text>\n                          </Card>\n                        )}\n                      </Fragment>\n                    )\n                  })}\n                </Stack>\n              ) : (\n                <Flex padding={4} align=\"center\" justify=\"center\">\n                  <Spinner />\n                </Flex>\n              )","{doc, include, status, hasDraft}","include","status","hasReferences && (\n                  <Button\n                    fontSize={2}\n                    padding={4}\n                    tone=\"positive\"\n                    mode=\"ghost\"\n                    icon={SearchIcon}\n                    onClick={() => void handleReferences()}\n                    text=\"Gather References\"\n                    disabled={isDuplicating || !selectedTotal || isGathering}\n                  />\n                )","() => void handleDuplicate()","<Button\n                  fontSize={2}\n                  padding={4}\n                  tone=\"positive\"\n                  icon={LaunchIcon}\n                  onClick={() => void handleDuplicate()}\n                  text={buttonText}\n                  disabled={isDuplicating || !selectedTotal || isGathering}\n                />","isDuplicating || !selectedTotal || isGathering","<Stack gap={2}>\n                {hasReferences && (\n                  <Button\n                    fontSize={2}\n                    padding={4}\n                    tone=\"positive\"\n                    mode=\"ghost\"\n                    icon={SearchIcon}\n                    onClick={() => void handleReferences()}\n                    text=\"Gather References\"\n                    disabled={isDuplicating || !selectedTotal || isGathering}\n                  />\n                )}\n                <Button\n                  fontSize={2}\n                  padding={4}\n                  tone=\"positive\"\n                  icon={LaunchIcon}\n                  onClick={() => void handleDuplicate()}\n                  text={buttonText}\n                  disabled={isDuplicating || !selectedTotal || isGathering}\n                />\n              </Stack>","<Card borderTop padding={4}>\n            <Stack gap={3}>\n              {displayMessage && (\n                <Card padding={3} radius={2} shadow={1} tone={displayMessage.tone}>\n                  <Text size={1}>{displayMessage.text}</Text>\n                </Card>\n              )}\n              {payload.length > 0 ? (\n                <Stack>\n                  {payload.map(({doc, include, status, hasDraft}, index) => {\n                    const schemaType = schema.get(doc._type)\n\n                    return (\n                      <Fragment key={doc._id}>\n                        <Flex align=\"center\">\n                          <Checkbox checked={include} onChange={() => handleCheckbox(doc._id)} />\n                          <Box flex={1} paddingX={3}>\n                            {schemaType ? (\n                              <Preview value={doc} schemaType={schemaType} />\n                            ) : (\n                              <Card tone=\"caution\">Invalid schema type</Card>\n                            )}\n                          </Box>\n                          <Flex align=\"center\" gap={2}>\n                            {hasDraft ? <StatusBadge status=\"UNPUBLISHED\" isAsset={false} /> : null}\n                            <StatusBadge status={status} isAsset={isAssetId(doc._id)} />\n                          </Flex>\n                        </Flex>\n                        {doc['extension'] === 'svg' && index === firstSvgIndex && (\n                          <Card padding={3} radius={2} shadow={1} tone=\"caution\">\n                            <Text size={1}>\n                              Due to how SVGs are sanitized after first uploaded, duplicated SVG\n                              assets may have new <code>_id</code>'s at the destination. The newly\n                              generated <code>_id</code> will be the same in each duplication, but\n                              it will never be the same <code>_id</code> as the first time this\n                              Asset was uploaded. References to the asset will be updated to use the\n                              new <code>_id</code>.\n                            </Text>\n                          </Card>\n                        )}\n                      </Fragment>\n                    )\n                  })}\n                </Stack>\n              ) : (\n                <Flex padding={4} align=\"center\" justify=\"center\">\n                  <Spinner />\n                </Flex>\n              )}\n              <Stack gap={2}>\n                {hasReferences && (\n                  <Button\n                    fontSize={2}\n                    padding={4}\n                    tone=\"positive\"\n                    mode=\"ghost\"\n                    icon={SearchIcon}\n                    onClick={() => void handleReferences()}\n                    text=\"Gather References\"\n                    disabled={isDuplicating || !selectedTotal || isGathering}\n                  />\n                )}\n                <Button\n                  fontSize={2}\n                  padding={4}\n                  tone=\"positive\"\n                  icon={LaunchIcon}\n                  onClick={() => void handleDuplicate()}\n                  text={buttonText}\n                  disabled={isDuplicating || !selectedTotal || isGathering}\n                />\n              </Stack>\n            </Stack>\n          </Card>","stickyStyles(isDarkMode)","{doc}","{old, new: next}","{doc, include}","{_id}","_id","_c","_temp","initialMessage","err","_Fragment","{apiVersion}","schema.getTypeNames()","{\n    docs: [],\n  }","function handleSubmit(e?: SubmitEvent<HTMLFormElement>) {\n    if (e) e.preventDefault()\n    void runQuery()\n  }","(doc) => !doc._id.startsWith(`drafts.`)","err","[0, 0, 0, 5]","[1, 1, 1, 2]","[1, 1, 1, 4]","[2, 2, 2, 0]","<Box>\n                  <Label>Initial Documents Query</Label>\n                </Box>","<Box>\n                  <Text>\n                    Start with a valid GROQ query to load initial documents. The query will need to\n                    return an Array of Objects. Drafts will be removed from the results.\n                  </Text>\n                </Box>","{fontFamily: 'monospace'}","(event) => setValue(event.currentTarget.value)","<Box flex={1} paddingRight={2}>\n                      <TextInput\n                        style={{fontFamily: 'monospace'}}\n                        fontSize={2}\n                        onChange={(event) => setValue(event.currentTarget.value)}\n                        padding={4}\n                        placeholder={`*[_type == \"article\"]`}\n                        value={value ?? ``}\n                      />\n                    </Box>","value ?? ``","() => handleSubmit()","<Button\n                      padding={2}\n                      paddingX={4}\n                      tone=\"primary\"\n                      onClick={() => handleSubmit()}\n                      text=\"Query\"\n                      disabled={!value}\n                    />","!value","<Flex>\n                    <Box flex={1} paddingRight={2}>\n                      <TextInput\n                        style={{fontFamily: 'monospace'}}\n                        fontSize={2}\n                        onChange={(event) => setValue(event.currentTarget.value)}\n                        padding={4}\n                        placeholder={`*[_type == \"article\"]`}\n                        value={value ?? ``}\n                      />\n                    </Box>\n                    <Button\n                      padding={2}\n                      paddingX={4}\n                      tone=\"primary\"\n                      onClick={() => handleSubmit()}\n                      text=\"Query\"\n                      disabled={!value}\n                    />\n                  </Flex>","<Card padding={4} radius={3} border>\n              <Stack gap={4}>\n                <Box>\n                  <Label>Initial Documents Query</Label>\n                </Box>\n                <Box>\n                  <Text>\n                    Start with a valid GROQ query to load initial documents. The query will need to\n                    return an Array of Objects. Drafts will be removed from the results.\n                  </Text>\n                </Box>\n                <form onSubmit={handleSubmit}>\n                  <Flex>\n                    <Box flex={1} paddingRight={2}>\n                      <TextInput\n                        style={{fontFamily: 'monospace'}}\n                        fontSize={2}\n                        onChange={(event) => setValue(event.currentTarget.value)}\n                        padding={4}\n                        placeholder={`*[_type == \"article\"]`}\n                        value={value ?? ``}\n                      />\n                    </Box>\n                    <Button\n                      padding={2}\n                      paddingX={4}\n                      tone=\"primary\"\n                      onClick={() => handleSubmit()}\n                      text=\"Query\"\n                      disabled={!value}\n                    />\n                  </Flex>\n                </form>\n              </Stack>\n            </Card>","preDefinedQueries && preDefinedQueries?.length > 0 && (\n              <Card marginTop={2} padding={4} radius={3} border>\n                <Box>\n                  <Stack gap={4}>\n                    <Box>\n                      <Label>Predefined Queries</Label>\n                    </Box>\n                    <Stack gap={2}>\n                      {preDefinedQueries.map((query) => (\n                        <Button\n                          key={query.label.replace(/\\s+/g, '-')}\n                          padding={2}\n                          paddingX={4}\n                          tone=\"primary\"\n                          onClick={() => setValue(`*[${query.query}]`)}\n                          text={query.label}\n                        />\n                      ))}\n                    </Stack>\n                  </Stack>\n                </Box>\n              </Card>\n            )","<Box padding={[2, 2, 2, 0]}>\n            <Card padding={4} radius={3} border>\n              <Stack gap={4}>\n                <Box>\n                  <Label>Initial Documents Query</Label>\n                </Box>\n                <Box>\n                  <Text>\n                    Start with a valid GROQ query to load initial documents. The query will need to\n                    return an Array of Objects. Drafts will be removed from the results.\n                  </Text>\n                </Box>\n                <form onSubmit={handleSubmit}>\n                  <Flex>\n                    <Box flex={1} paddingRight={2}>\n                      <TextInput\n                        style={{fontFamily: 'monospace'}}\n                        fontSize={2}\n                        onChange={(event) => setValue(event.currentTarget.value)}\n                        padding={4}\n                        placeholder={`*[_type == \"article\"]`}\n                        value={value ?? ``}\n                      />\n                    </Box>\n                    <Button\n                      padding={2}\n                      paddingX={4}\n                      tone=\"primary\"\n                      onClick={() => handleSubmit()}\n                      text=\"Query\"\n                      disabled={!value}\n                    />\n                  </Flex>\n                </form>\n              </Stack>\n            </Card>\n            {preDefinedQueries && preDefinedQueries?.length > 0 && (\n              <Card marginTop={2} padding={4} radius={3} border>\n                <Box>\n                  <Stack gap={4}>\n                    <Box>\n                      <Label>Predefined Queries</Label>\n                    </Box>\n                    <Stack gap={2}>\n                      {preDefinedQueries.map((query) => (\n                        <Button\n                          key={query.label.replace(/\\s+/g, '-')}\n                          padding={2}\n                          paddingX={4}\n                          tone=\"primary\"\n                          onClick={() => setValue(`*[${query.query}]`)}\n                          text={query.label}\n                        />\n                      ))}\n                    </Stack>\n                  </Stack>\n                </Box>\n              </Card>\n            )}\n          </Box>","fetched && initialData.docs.length < 1 && (\n            <Container width={1}>\n              <Card padding={5}>\n                {value ? `No documents match this query` : `Start with a valid GROQ query`}\n              </Card>\n            </Container>\n          )","docs","initialData.docs?.length > 0 && (\n            <Duplicator docs={initialData.docs} token={token} pluginConfig={pluginConfig} />\n          )","<Card padding={[0, 0, 0, 5]}>\n      <Container>\n        <Grid gridTemplateColumns={[1, 1, 1, 2]} gap={[1, 1, 1, 4]}>\n          <Box padding={[2, 2, 2, 0]}>\n            <Card padding={4} radius={3} border>\n              <Stack gap={4}>\n                <Box>\n                  <Label>Initial Documents Query</Label>\n                </Box>\n                <Box>\n                  <Text>\n                    Start with a valid GROQ query to load initial documents. The query will need to\n                    return an Array of Objects. Drafts will be removed from the results.\n                  </Text>\n                </Box>\n                <form onSubmit={handleSubmit}>\n                  <Flex>\n                    <Box flex={1} paddingRight={2}>\n                      <TextInput\n                        style={{fontFamily: 'monospace'}}\n                        fontSize={2}\n                        onChange={(event) => setValue(event.currentTarget.value)}\n                        padding={4}\n                        placeholder={`*[_type == \"article\"]`}\n                        value={value ?? ``}\n                      />\n                    </Box>\n                    <Button\n                      padding={2}\n                      paddingX={4}\n                      tone=\"primary\"\n                      onClick={() => handleSubmit()}\n                      text=\"Query\"\n                      disabled={!value}\n                    />\n                  </Flex>\n                </form>\n              </Stack>\n            </Card>\n            {preDefinedQueries && preDefinedQueries?.length > 0 && (\n              <Card marginTop={2} padding={4} radius={3} border>\n                <Box>\n                  <Stack gap={4}>\n                    <Box>\n                      <Label>Predefined Queries</Label>\n                    </Box>\n                    <Stack gap={2}>\n                      {preDefinedQueries.map((query) => (\n                        <Button\n                          key={query.label.replace(/\\s+/g, '-')}\n                          padding={2}\n                          paddingX={4}\n                          tone=\"primary\"\n                          onClick={() => setValue(`*[${query.query}]`)}\n                          text={query.label}\n                        />\n                      ))}\n                    </Stack>\n                  </Stack>\n                </Box>\n              </Card>\n            )}\n          </Box>\n          {fetched && initialData.docs.length < 1 && (\n            <Container width={1}>\n              <Card padding={5}>\n                {value ? `No documents match this query` : `Start with a valid GROQ query`}\n              </Card>\n            </Container>\n          )}\n          {initialData.docs?.length > 0 && (\n            <Duplicator docs={initialData.docs} token={token} pluginConfig={pluginConfig} />\n          )}\n        </Grid>\n      </Container>\n    </Card>","doc","_c","_temp","err","[]","{apiVersion}","() => {\n    async function fetchInbound() {\n      const firstDocId = docs[0]?._id\n\n      if (!follow.includes(`inbound`) || !firstDocId) {\n        return\n      }\n\n      const inboundReferences = await client.fetch<SanityDocument[]>(`*[references($id)]`, {\n        id: firstDocId,\n      })\n      setInbound([...docs, ...inboundReferences])\n    }\n\n    fetchInbound().catch(console.error)\n  }","[client, docs, follow]","docs[0]?._id","follow.length > 1 && (follow.includes(`inbound`) || follow.includes(`outbound`)) ? (\n        <Card paddingX={4} paddingBottom={4} marginBottom={4} borderBottom>\n          <Grid gridTemplateColumns={2} gap={4}>\n            {follow.includes(`outbound`) ? (\n              <Button\n                mode=\"ghost\"\n                tone=\"primary\"\n                selected={mode === 'outbound'}\n                onClick={() => setMode('outbound')}\n                text=\"Outbound\"\n              />\n            ) : null}\n            {follow.includes(`inbound`) ? (\n              <Button\n                mode=\"ghost\"\n                tone=\"primary\"\n                selected={mode === 'inbound'}\n                onClick={() => setMode('inbound')}\n                disabled={inbound.length === 0}\n                text={inbound.length > 0 ? `Inbound (${inbound.length})` : 'No inbound references'}\n              />\n            ) : null}\n          </Grid>\n        </Card>\n      ) : null","inbound.length","follow.length","<Duplicator\n        docs={mode === 'outbound' ? docs : inbound}\n        token={token}\n        pluginConfig={pluginConfig}\n        onDuplicated={onDuplicated}\n      />","mode === 'outbound' ? docs : inbound","<Container>\n      {follow.length > 1 && (follow.includes(`inbound`) || follow.includes(`outbound`)) ? (\n        <Card paddingX={4} paddingBottom={4} marginBottom={4} borderBottom>\n          <Grid gridTemplateColumns={2} gap={4}>\n            {follow.includes(`outbound`) ? (\n              <Button\n                mode=\"ghost\"\n                tone=\"primary\"\n                selected={mode === 'outbound'}\n                onClick={() => setMode('outbound')}\n                text=\"Outbound\"\n              />\n            ) : null}\n            {follow.includes(`inbound`) ? (\n              <Button\n                mode=\"ghost\"\n                tone=\"primary\"\n                selected={mode === 'inbound'}\n                onClick={() => setMode('inbound')}\n                disabled={inbound.length === 0}\n                text={inbound.length > 0 ? `Inbound (${inbound.length})` : 'No inbound references'}\n              />\n            ) : null}\n          </Grid>\n        </Card>\n      ) : null}\n      <Duplicator\n        docs={mode === 'outbound' ? docs : inbound}\n        token={token}\n        pluginConfig={pluginConfig}\n        onDuplicated={onDuplicated}\n      />\n    </Container>","_c","{apiVersion}: ResetSecretProps","{apiVersion}","() => {\n    client.delete({query: `*[_id == \"secrets.${SECRET_NAMESPACE}\"]`}).catch(console.error)\n  }","useCallback(() => {\n    client.delete({query: `*[_id == \"secrets.${SECRET_NAMESPACE}\"]`}).catch(console.error)\n  }, [client])","[2, 2, 2, 5]","<Flex align=\"center\" justify=\"flex-end\" paddingX={[2, 2, 2, 5]} paddingY={5}>\n      <Button\n        text=\"Reset Secret\"\n        onClick={handleClick}\n        mode=\"ghost\"\n        tone=\"critical\"\n        fontSize={1}\n        padding={2}\n      />\n    </Flex>","_c","<Flex justify=\"center\" align=\"center\">\n        <Box padding={5}>\n          <Spinner />\n        </Box>\n      </Flex>","<SettingsView\n        title=\"Token Required\"\n        namespace={SECRET_NAMESPACE}\n        keys={secretConfigKeys}\n        onClose={() => null}\n      />","() => null","<DuplicatorQuery token={secrets.bearerToken} pluginConfig={pluginConfig} />","bearerToken","<ResetSecret apiVersion={pluginConfig.apiVersion} />","apiVersion","<>\n        <DuplicatorQuery token={secrets.bearerToken} pluginConfig={pluginConfig} />\n        <ResetSecret apiVersion={pluginConfig.apiVersion} />\n      </>","<Feedback>No docs passed into Duplicator Tool</Feedback>","<Feedback>No plugin config</Feedback>","<DuplicatorWrapper\n      docs={docs}\n      token={secrets.bearerToken}\n      pluginConfig={pluginConfig}\n      onDuplicated={onDuplicated}\n    />","_c","_Fragment","<CrossDatasetDuplicator mode=\"action\" docs={docs} onDuplicated={onDuplicated} />","_c","props.tool.options ?? {}","options","docs = []","<CrossDatasetDuplicator mode=\"tool\" docs={docs} />","_c","\"details\"","\"items\"","\"error\"","\"description\"","\"message\"","\"type\"","\"referenceID\"","\"referencedId\"","\"referenceId\"","\"extension\""],"sources":["../src/helpers/constants.ts","../src/context/ConfigProvider.tsx","../src/helpers/index.ts","../src/helpers/getDocumentsInArray.ts","../src/helpers/migrationFilters.ts","../src/components/Feedback.tsx","../src/components/SelectButtons.tsx","../src/components/StatusBadge.tsx","../src/components/Duplicator.tsx","../src/components/DuplicatorQuery.tsx","../src/components/DuplicatorWrapper.tsx","../src/components/ResetSecret.tsx","../src/components/CrossDatasetDuplicator.tsx","../src/components/CrossDatasetDuplicatorAction.tsx","../src/actions/DuplicateToAction.tsx","../src/components/CrossDatasetDuplicatorTool.tsx","../src/tool/index.ts","../src/plugin.tsx"],"sourcesContent":["import type {PluginConfig} from '../types'\n\nexport const SECRET_NAMESPACE = `CrossDatasetDuplicator`\n\nexport const DEFAULT_CONFIG: Required<PluginConfig> = {\n  apiVersion: '2025-02-19',\n  tool: true,\n  types: [],\n  filter: '',\n  follow: ['outbound'],\n  queries: [],\n  migrationFilters: [],\n}\n","import {createContext, useContext} from 'react'\nimport type {LayoutProps} from 'sanity'\n\nimport {DEFAULT_CONFIG} from '../helpers/constants'\nimport type {PluginConfig} from '../types'\n\nconst CrossDatasetDuplicatorContext = createContext(DEFAULT_CONFIG)\n\ntype ConfigProviderProps = LayoutProps & {pluginConfig: Required<PluginConfig>}\n\n/**\n * Plugin config context hook from the Cross Dataset Duplicator plugin\n * @public\n */\nexport function useCrossDatasetDuplicatorConfig() {\n  const pluginConfig = useContext(CrossDatasetDuplicatorContext)\n\n  return pluginConfig\n}\n\nexport function ConfigProvider(props: ConfigProviderProps) {\n  const {pluginConfig, ...rest} = props\n\n  return (\n    <CrossDatasetDuplicatorContext.Provider value={pluginConfig}>\n      {props.renderDefault(rest)}\n    </CrossDatasetDuplicatorContext.Provider>\n  )\n}\n","import type {CSSProperties} from 'react'\n\nexport function createInitialMessage(docCount = 0, refsCount = 0): string {\n  const message = [\n    docCount === 1 ? `This Document contains` : `These ${docCount} Documents contain`,\n    refsCount === 1 ? `1 Reference.` : `${refsCount} References.`,\n    refsCount === 1 ? `That Document` : `Those Documents`,\n    `may have References too. If referenced Documents do not exist at the target Destination, this transaction will fail.`,\n  ]\n\n  return message.join(` `)\n}\n\nexport const stickyStyles = (isDarkMode = true): CSSProperties => ({\n  position: 'sticky',\n  top: 0,\n  zIndex: 100,\n  backgroundColor: isDarkMode ? `rgba(10,10,10,0.95)` : `rgba(255,255,255,0.95)`,\n})\n","import {extractWithPath} from '@sanity/mutator'\nimport type {SanityClient, SanityDocument} from 'sanity'\n\nimport type {PluginConfig} from '../types'\n\ntype OptionsBag = {\n  fetchIds: string[]\n  client: SanityClient\n  pluginConfig: PluginConfig\n  currentIds?: Set<string> | null\n  projection?: string\n}\n\n// Recursively fetch Documents from an array of _id's and their references\n// Heavy use of Set is to avoid recursively querying for id's already in the payload\nexport async function getDocumentsInArray(options: OptionsBag): Promise<SanityDocument[]> {\n  const {fetchIds, client, pluginConfig, currentIds, projection} = options\n  const collection: SanityDocument[] = []\n\n  // Find initial docs\n  const filter = ['_id in $fetchIds', pluginConfig.filter].filter(Boolean).join(' && ')\n  const query = `*[${filter}]${projection ?? ``}`\n  const data = await client.fetch<SanityDocument[]>(query, {\n    fetchIds: fetchIds ?? [],\n  })\n\n  if (!data?.length) {\n    return []\n  }\n\n  const localCurrentIds = currentIds ?? new Set<string>()\n\n  // Find new ids in the returned data\n  // Unless we started with an empty set, get the _ids from the data\n  const newDataIds = new Set<string>(\n    data\n      .map((dataDoc) => dataDoc._id)\n      .filter((id) => (currentIds?.size ? !localCurrentIds.has(id) : Boolean(id))),\n  )\n\n  if (newDataIds.size) {\n    collection.push(...data)\n    for (const id of newDataIds) {\n      localCurrentIds.add(id)\n    }\n\n    // Check new data for more references\n    await Promise.all(\n      data.map(async (doc) => {\n        const expr = `.._ref`\n        const references = extractWithPath(expr, doc).flatMap((ref) =>\n          typeof ref.value === 'string' ? [ref.value] : [],\n        )\n\n        if (references.length) {\n          // Find references not already in the Collection\n          const newReferenceIds = new Set<string>(\n            references.filter((ref) => !localCurrentIds.has(ref)),\n          )\n\n          if (newReferenceIds.size) {\n            // Recursive query for new documents\n            const referenceDocs = await getDocumentsInArray({\n              fetchIds: Array.from(newReferenceIds),\n              currentIds: localCurrentIds,\n              client,\n              pluginConfig,\n            })\n\n            if (referenceDocs?.length) {\n              collection.push(...referenceDocs)\n            }\n          }\n        }\n      }),\n    )\n  }\n\n  // Create a unique array of documents, keeping the first occurrence of each _id\n  const seenIds = new Set<string>()\n  const uniqueCollection: SanityDocument[] = []\n\n  for (const doc of collection) {\n    if (doc && !seenIds.has(doc._id)) {\n      seenIds.add(doc._id)\n      uniqueCollection.push(doc)\n    }\n  }\n\n  return uniqueCollection\n}\n","import type {MigrationFilter} from '../types'\n\ntype IsAllowedMigrationTargetOptions = {\n  migrationFilters: MigrationFilter[] | undefined\n  sourceProjectId: string | undefined\n  sourceDataset: string | undefined\n  targetProjectId: string\n  targetDataset: string\n}\n\n/**\n * Determine whether a Workspace is an allowed Migration destination for the\n * current source Dataset, based on the optional `migrationFilters` config.\n *\n * If no filter is configured for the source Dataset, every target is allowed\n * (the default behaviour). When a filter is configured, only the listed targets\n * are allowed.\n */\nexport function isAllowedMigrationTarget(options: IsAllowedMigrationTargetOptions): boolean {\n  const {migrationFilters, sourceProjectId, sourceDataset, targetProjectId, targetDataset} = options\n\n  const migrationFilter = migrationFilters?.find((filter) => filter.sourceDataset === sourceDataset)\n\n  // If no migrationFilter is configured for this dataset, allow all migration targets.\n  if (!migrationFilter) {\n    return true\n  }\n\n  return migrationFilter.targets.some((target) => {\n    if (target.dataset !== targetDataset) {\n      return false\n    }\n\n    // If a project ID is configured for the target, check that it matches.\n    if (target.projectId) {\n      return target.projectId === targetProjectId\n    }\n\n    // If a project ID is not configured for the target, only allow targets in\n    // the same project as the source.\n    return targetProjectId === sourceProjectId\n  })\n}\n","import {Card, Text} from '@sanity/ui'\nimport type {BadgeTone} from '@sanity/ui'\nimport type {ReactNode} from 'react'\n\ntype FeedbackProps = {\n  children?: ReactNode\n  tone?: BadgeTone\n}\n\nexport default function Feedback(props: FeedbackProps) {\n  const {children, tone = 'caution'} = props\n\n  return (\n    <Card padding={3} radius={2} shadow={1} tone={tone}>\n      <Text size={1}>{children}</Text>\n    </Card>\n  )\n}\n","import {isAssetId} from '@sanity/asset-utils'\nimport {Button, Card, Flex} from '@sanity/ui'\nimport {type Dispatch, type SetStateAction, useState} from 'react'\n\nimport type {PayloadItem} from './Duplicator'\n\ntype Action = 'ALL' | 'NONE' | 'NEW' | 'EXISTING' | 'OLDER' | 'ASSETS' | 'DOCUMENTS'\n\ntype ButtonItem = {label: string; action: Action} | {divider: string}\n\nconst buttons: ButtonItem[] = [\n  {label: 'All', action: 'ALL'},\n  {label: 'None', action: 'NONE'},\n  {divider: 'divider-1'},\n  {label: 'New', action: 'NEW'},\n  {label: 'Existing', action: 'EXISTING'},\n  {label: 'Older', action: 'OLDER'},\n  {divider: 'divider-2'},\n  {label: 'Documents', action: 'DOCUMENTS'},\n  {label: 'Assets', action: 'ASSETS'},\n]\n\nfunction shouldInclude(item: PayloadItem, action: Action): boolean {\n  switch (action) {\n    case 'ALL':\n      return true\n    case 'NONE':\n      return false\n    case 'NEW':\n      return item.status === 'CREATE'\n    case 'EXISTING':\n      return item.status === 'EXISTS'\n    case 'OLDER':\n      return item.status === 'OVERWRITE'\n    case 'ASSETS':\n      return isAssetId(item.doc._id)\n    case 'DOCUMENTS':\n      return !isAssetId(item.doc._id)\n    default:\n      return item.include\n  }\n}\n\ntype SelectButtonsProps = {\n  payload: PayloadItem[]\n  setPayload: Dispatch<SetStateAction<PayloadItem[]>>\n}\n\nexport default function SelectButtons(props: SelectButtonsProps) {\n  const {payload, setPayload} = props\n  const [disabledActions, setDisabledActions] = useState<Action[]>(() =>\n    payload.length && payload.every((item) => item.include) ? ['ALL'] : [],\n  )\n\n  function handleSelectButton(action: Action) {\n    if (!payload.length) return\n\n    setPayload((current) =>\n      current.map((item) => ({...item, include: shouldInclude(item, action)})),\n    )\n    setDisabledActions([action])\n  }\n\n  return (\n    <Card padding={1} radius={3} shadow={1}>\n      <Flex gap={2} wrap=\"wrap\">\n        {buttons.map((button) =>\n          'action' in button ? (\n            <Button\n              key={button.action}\n              fontSize={1}\n              mode=\"bleed\"\n              padding={2}\n              text={button.label}\n              disabled={disabledActions.includes(button.action)}\n              onClick={() => handleSelectButton(button.action)}\n            />\n          ) : (\n            <Card key={button.divider} borderLeft />\n          ),\n        )}\n      </Flex>\n    </Card>\n  )\n}\n","import {InfoOutlineIcon} from '@sanity/icons/InfoOutline'\nimport {Box, Text, Badge} from '@sanity/ui'\nimport type {BadgeTone} from '@sanity/ui'\nimport {Tooltip} from '@sanity/ui/tooltip'\n\ntype StatusTones = {\n  EXISTS: BadgeTone\n  OVERWRITE: BadgeTone\n  UPDATE: BadgeTone\n  CREATE: BadgeTone\n  UNPUBLISHED: BadgeTone\n}\n\nconst documentTones: StatusTones = {\n  EXISTS: `primary`,\n  OVERWRITE: `critical`,\n  UPDATE: `caution`,\n  CREATE: `positive`,\n  UNPUBLISHED: `caution`,\n}\n\nconst assetTones: StatusTones = {\n  EXISTS: `critical`,\n  OVERWRITE: `critical`,\n  UPDATE: `critical`,\n  CREATE: `positive`,\n  UNPUBLISHED: `default`,\n}\n\nexport type MessageTypes = {\n  EXISTS: string\n  OVERWRITE: string\n  UPDATE: string\n  CREATE: string\n  UNPUBLISHED: string\n}\n\nconst documentMessages: MessageTypes = {\n  // Only happens once document is copied the first time, and _updatedAt is the same\n  EXISTS: `This document already exists at the Destination with the same ID and Updated time.`,\n  // Is true immediately after transaction as _updatedAt is updated by API after mutation\n  // Is also true if the document at the destination has been manually modified\n  // Presently, the plugin doesn't actually compare the two documents\n  OVERWRITE: `A newer version of this document exists at the Destination, and it will be overwritten with this version.`,\n  // Document at destination is older\n  UPDATE: `An older version of this document exists at the Destination, and it will be overwritten with this version.`,\n  // Document at destination doesn't exist\n  CREATE: `This document will be created at the destination.`,\n  UNPUBLISHED: `A Draft version of this Document exists in this Dataset, but only the Published version will be duplicated to the destination.`,\n}\n\nconst assetMessages: MessageTypes = {\n  EXISTS: `This Asset already exists at the Destination`,\n  OVERWRITE: `This Asset already exists at the Destination`,\n  UPDATE: `This Asset already exists at the Destination`,\n  CREATE: `This Asset does not yet exist at the Destination`,\n  UNPUBLISHED: ``,\n}\n\nconst assetStatus: MessageTypes = {\n  EXISTS: `RE-UPLOAD`,\n  OVERWRITE: `RE-UPLOAD`,\n  UPDATE: `RE-UPLOAD`,\n  CREATE: `UPLOAD`,\n  UNPUBLISHED: ``,\n}\n\ntype StatusBadgeProps = {\n  isAsset: boolean\n  status?: keyof MessageTypes\n}\n\nexport default function StatusBadge(props: StatusBadgeProps) {\n  const {status, isAsset} = props\n\n  if (!status) {\n    return null\n  }\n\n  const badgeTone = isAsset ? assetTones[status] : documentTones[status]\n\n  if (!badgeTone) {\n    return (\n      <Badge padding={2} fontSize={1}>\n        Checking...\n      </Badge>\n    )\n  }\n\n  const badgeText = isAsset ? assetMessages[status] : documentMessages[status]\n  const badgeStatus = isAsset ? assetStatus[status] : status\n\n  return (\n    <Tooltip\n      content={\n        <Box padding={3} style={{maxWidth: 200}}>\n          <Text size={1}>{badgeText}</Text>\n        </Box>\n      }\n      fallbackPlacements={['right', 'left']}\n      placement=\"top\"\n      portal\n    >\n      <Badge padding={3} fontSize={1} tone={badgeTone}>\n        {badgeStatus}\n        <Box marginLeft={2} display={'inline-block'} as=\"span\">\n          <InfoOutlineIcon />\n        </Box>\n      </Badge>\n    </Tooltip>\n  )\n}\n","import {isAssetId, isSanityFileAsset} from '@sanity/asset-utils'\nimport type {SanityAssetDocument, SanityClient} from '@sanity/client'\nimport {ArrowRightIcon} from '@sanity/icons/ArrowRight'\nimport {LaunchIcon} from '@sanity/icons/Launch'\nimport {SearchIcon} from '@sanity/icons/Search'\nimport {extractWithPath} from '@sanity/mutator'\nimport {\n  Card,\n  Container,\n  Text,\n  Box,\n  Button,\n  Label,\n  Stack,\n  Select,\n  Flex,\n  Checkbox,\n  type CardTone,\n  useTheme,\n  Spinner,\n} from '@sanity/ui'\nimport {getTheme_v2} from '@sanity/ui/theme'\nimport {dset} from 'dset'\nimport {type ChangeEvent, Fragment, useEffect, useEffectEvent, useMemo, useState} from 'react'\nimport {\n  useClient,\n  Preview,\n  useSchema,\n  useWorkspaces,\n  type WorkspaceSummary,\n  type SanityDocument,\n} from 'sanity'\n\nimport {stickyStyles, createInitialMessage} from '../helpers'\nimport {getDocumentsInArray} from '../helpers/getDocumentsInArray'\nimport {isAllowedMigrationTarget} from '../helpers/migrationFilters'\nimport type {PluginConfig} from '../types'\nimport Feedback from './Feedback'\nimport SelectButtons from './SelectButtons'\nimport StatusBadge, {type MessageTypes} from './StatusBadge'\n\nexport type DuplicatorProps = {\n  docs: SanityDocument[]\n  token: string\n  pluginConfig: Required<PluginConfig>\n  onDuplicated?: () => Promise<void>\n}\n\nexport type PayloadItem = {\n  doc: SanityDocument\n  include: boolean\n  status?: keyof MessageTypes\n  hasDraft?: boolean\n}\n\ntype WorkspaceOption = WorkspaceSummary & {\n  disabled: boolean\n}\n\ntype Message = {\n  text: string\n  tone: CardTone\n}\n\nfunction isAssetDocument(doc: SanityDocument): doc is SanityDocument & SanityAssetDocument {\n  return isAssetId(doc._id)\n}\n\n// Run an async function over every item with a maximum concurrency\nasync function mapWithConcurrency<T>(\n  items: T[],\n  limit: number,\n  fn: (item: T) => Promise<void>,\n): Promise<void> {\n  const queue = [...items]\n\n  async function work(): Promise<void> {\n    const item = queue.shift()\n\n    if (item === undefined) {\n      return undefined\n    }\n\n    await fn(item)\n\n    return work()\n  }\n\n  const workers = Array.from({length: Math.min(limit, queue.length)}, () => work())\n\n  await Promise.all(workers)\n}\n\ntype SetMessage = (msg: Message) => void\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n  return typeof value === 'object' && value !== null\n}\n\nfunction isUnknownArray(value: unknown): value is unknown[] {\n  return Array.isArray(value)\n}\n\n// Pull a human-readable description out of a Sanity mutation error.\n// Prefer the richest text available: item-level descriptions (which carry the\n// \"references non-existent document\" phrasing) over a possibly-generic top-level\n// `details.description` like \"Mutation(s) failed with N error(s)\".\nfunction getErrorDescription(err: unknown): string {\n  if (!isRecord(err)) {\n    return ''\n  }\n\n  const details = err['details']\n  const itemDescriptions: string[] = []\n\n  if (isRecord(details) && isUnknownArray(details['items'])) {\n    for (const item of details['items']) {\n      if (isRecord(item) && isRecord(item['error'])) {\n        const itemDescription = item['error']['description']\n\n        if (typeof itemDescription === 'string' && itemDescription) {\n          itemDescriptions.push(itemDescription)\n        }\n      }\n    }\n  }\n\n  if (itemDescriptions.length) {\n    return itemDescriptions.join('\\n')\n  }\n\n  const message = err['message']\n\n  if (typeof message === 'string' && message) {\n    return message\n  }\n\n  if (isRecord(details)) {\n    const description = details['description']\n\n    if (typeof description === 'string') {\n      return description\n    }\n  }\n\n  return ''\n}\n\nfunction isReferenceMutationError(err: unknown): boolean {\n  if (!isRecord(err)) {\n    return false\n  }\n\n  const details = err['details']\n\n  // Most reliable: structured mutation item type from the Content Lake API\n  if (isRecord(details) && isUnknownArray(details['items'])) {\n    for (const item of details['items']) {\n      if (isRecord(item) && isRecord(item['error'])) {\n        if (item['error']['type'] === 'documentReferenceDoesNotExistError') {\n          return true\n        }\n\n        const itemDescription = item['error']['description']\n\n        if (\n          typeof itemDescription === 'string' &&\n          (itemDescription.toLowerCase().includes('references non-existent document') ||\n            itemDescription.toLowerCase().includes('reference non-existent'))\n        ) {\n          return true\n        }\n      }\n    }\n  }\n\n  const description = getErrorDescription(err).toLowerCase()\n\n  return (\n    description.includes('references non-existent document') ||\n    description.includes('reference non-existent')\n  )\n}\n\n// Collect the _id's of referenced documents that are missing at the destination,\n// reading both the structured error payload and the human-readable description\nfunction getMissingReferenceIds(err: unknown, description: string): string[] {\n  const missingIds: string[] = []\n\n  const details = isRecord(err) ? err['details'] : undefined\n  const rawItems = isRecord(details) ? details['items'] : undefined\n  const items = isUnknownArray(rawItems) ? rawItems : []\n\n  for (const item of items) {\n    if (isRecord(item)) {\n      const error = item['error']\n\n      if (isRecord(error)) {\n        // Sanity returns `referenceID`; keep the other spellings as fallbacks\n        const refId = error['referenceID'] ?? error['referencedId'] ?? error['referenceId']\n\n        if (typeof refId === 'string' && !missingIds.includes(refId)) {\n          missingIds.push(refId)\n        }\n      }\n    }\n  }\n\n  const refRegex = /references non-existent document [`'\"]?([^`'\"\\s)]+)[`'\"]?/gi\n  let match = refRegex.exec(description)\n\n  while (match !== null) {\n    const id = match[1]\n\n    if (id && !missingIds.includes(id)) {\n      missingIds.push(id)\n    }\n\n    match = refRegex.exec(description)\n  }\n\n  return missingIds\n}\n\n// Commit documents individually so a single failing document doesn't block the rest.\n// Runs sequentially (concurrency 1) so referenced documents can land before the\n// documents that point at them.\nasync function commitOneByOne(\n  docs: SanityDocument[],\n  client: SanityClient,\n  setMessage: SetMessage,\n  onSuccess: () => void,\n): Promise<void> {\n  let successCount = 0\n  let failCount = 0\n\n  await mapWithConcurrency(docs, 1, async (doc) => {\n    try {\n      const tx = client.transaction()\n      tx.createOrReplace(doc)\n      await tx.commit()\n      successCount += 1\n    } catch (commitErr) {\n      failCount += 1\n      console.error(`Failed to duplicate document \"${doc._id}\"`, commitErr)\n    }\n  })\n\n  if (failCount === 0) {\n    setMessage({tone: 'positive', text: 'Duplication complete!'})\n    onSuccess()\n\n    return\n  }\n\n  setMessage({\n    tone: 'critical',\n    text: `Duplication finished with ${failCount} error(s). ${successCount} document(s) duplicated successfully.`,\n  })\n\n  if (successCount > 0) {\n    onSuccess()\n  }\n}\n\ntype ReferenceErrorOptions = {\n  err: unknown\n  transactionDocs: SanityDocument[]\n  originClient: SanityClient\n  destinationClient: SanityClient\n  pluginConfig: Required<PluginConfig>\n  token: string\n  setMessage: SetMessage\n  onSuccess: () => void\n  /** Caps recursive recovery so a pathological reference loop can't hang forever */\n  depth?: number\n  /** Document ids the user explicitly deselected — never auto-commit these during recovery */\n  excludedIds?: Set<string>\n  /**\n   * SVG _id remaps already applied by the caller. Recovered documents are fetched\n   * fresh from the origin, so they still point at origin SVG _id's that only exist\n   * at the destination under their uploaded _id.\n   */\n  svgMaps?: {old: string; new: string}[]\n}\n\n// Only attach the studio token when downloading from a Sanity host so a crafted\n// asset `url` cannot exfiltrate credentials to an attacker-controlled endpoint.\nfunction assetDownloadInit(url: string, token: string, typeIsFile: boolean): RequestInit {\n  if (typeIsFile) {\n    return {}\n  }\n\n  try {\n    const {hostname} = new URL(url)\n\n    if (hostname === 'cdn.sanity.io' || hostname.endsWith('.sanity.io')) {\n      return {headers: {Authorization: `Bearer ${token}`}}\n    }\n  } catch {\n    // Invalid URL — fetch without credentials\n  }\n\n  return {}\n}\n\n// Upload a recovered asset to the destination, rewriting url/path for the new dataset\nasync function uploadAssetForRecovery(\n  doc: SanityDocument & SanityAssetDocument,\n  destinationClient: SanityClient,\n  token: string,\n): Promise<{docs: SanityDocument[]; svgMap?: {old: string; new: string}}> {\n  const typeIsFile = isSanityFileAsset(doc)\n  const downloadUrl = typeIsFile ? doc.url : `${doc.url}?dlRaw=true`\n\n  const res = await fetch(downloadUrl, assetDownloadInit(downloadUrl, token, typeIsFile))\n\n  if (!res.ok) {\n    throw new Error(\n      `Failed to download asset \"${doc._id}\" from origin (${res.status} ${res.statusText})`,\n    )\n  }\n\n  const assetData = await res.blob()\n  const assetDoc = await destinationClient.assets.upload(typeIsFile ? `file` : `image`, assetData, {\n    filename: doc.originalFilename,\n  })\n\n  // Merge the original asset document's editorial metadata (e.g. `altText`) with\n  // the uploaded asset's canonical fields, matching the main duplication path.\n  // Keeping this to a single document at the uploaded `_id` avoids leaving an\n  // orphaned asset behind when an SVG's `_id` changes on upload; references are\n  // repointed via `svgMap`.\n  return {\n    docs: [{...doc, ...assetDoc}],\n    svgMap: doc.extension === 'svg' ? {old: doc._id, new: assetDoc._id} : undefined,\n  }\n}\n\n// Rewrite _ref values that point at remapped SVG asset ids.\n// Clones each doc so caller-held / payload objects are not mutated.\nfunction remapSvgRefs(\n  docs: SanityDocument[],\n  svgMaps: {old: string; new: string}[],\n): SanityDocument[] {\n  if (!svgMaps.length) {\n    return docs\n  }\n\n  return docs.map((original) => {\n    const references = extractWithPath(`.._ref`, original)\n\n    if (!references.length) {\n      return original\n    }\n\n    const doc = structuredClone(original)\n\n    references.forEach((ref) => {\n      const newRefValue = svgMaps.find((asset) => asset.old === ref.value)?.new\n\n      if (newRefValue) {\n        dset(doc, ref.path.join('.'), newRefValue)\n      }\n    })\n\n    return doc\n  })\n}\n\n// Order docs so referenced documents come before the documents that point at\n// them. Used by the sequential one-by-one fallback where commit order matters.\nfunction orderDocsDependenciesFirst(docs: SanityDocument[]): SanityDocument[] {\n  const byId = new Map(docs.map((doc) => [doc._id, doc]))\n  const visiting = new Set<string>()\n  const visited = new Set<string>()\n  const ordered: SanityDocument[] = []\n\n  function visit(id: string): void {\n    if (visited.has(id) || visiting.has(id)) {\n      return\n    }\n\n    const doc = byId.get(id)\n\n    if (!doc) {\n      return\n    }\n\n    visiting.add(id)\n\n    for (const ref of extractWithPath(`.._ref`, doc)) {\n      if (typeof ref.value === 'string') {\n        visit(ref.value)\n      }\n    }\n\n    visiting.delete(id)\n    visited.add(id)\n    ordered.push(doc)\n  }\n\n  for (const doc of docs) {\n    visit(doc._id)\n  }\n\n  return ordered\n}\n\n// When a transaction fails because of missing references, fetch the referenced\n// documents (and their transitive refs) from the origin — respecting\n// pluginConfig.filter — upload any assets, then retry. Falls back to one-by-one\n// commits if the retry still fails.\nasync function handleReferenceError(options: ReferenceErrorOptions): Promise<void> {\n  const {\n    err,\n    transactionDocs,\n    originClient,\n    destinationClient,\n    pluginConfig,\n    token,\n    setMessage,\n    onSuccess,\n    depth = 0,\n    excludedIds = new Set(),\n    svgMaps: inheritedSvgMaps = [],\n  } = options\n  const description = getErrorDescription(err)\n  const missingIds = getMissingReferenceIds(err, description)\n\n  // If the only missing refs are ones the user deselected, surface that instead of\n  // silently re-committing them\n  const autoFetchIds = missingIds.filter((id) => !excludedIds.has(id))\n  const blockedIds = missingIds.filter((id) => excludedIds.has(id))\n\n  if (blockedIds.length && !autoFetchIds.length) {\n    setMessage({\n      tone: 'critical',\n      text: `Duplication failed because deselected document(s) are still referenced: ${blockedIds.join(', ')}. Re-select them or remove the references.`,\n    })\n\n    return\n  }\n\n  if (!missingIds.length || depth >= 5) {\n    // Couldn't parse the missing _id's (or we hit the recursion cap) — retry each document on its own\n    setMessage({tone: 'default', text: 'Retrying documents one by one...'})\n    await commitOneByOne(\n      orderDocsDependenciesFirst(transactionDocs),\n      destinationClient,\n      setMessage,\n      onSuccess,\n    )\n\n    return\n  }\n\n  setMessage({\n    tone: 'default',\n    text: `Fetching ${autoFetchIds.length} missing referenced document(s) and retrying...`,\n  })\n\n  let missingDocs: SanityDocument[] = []\n\n  try {\n    // Recursively gather referenced docs (and apply pluginConfig.filter), same\n    // as the \"Gather References\" path — so nested refs aren't left behind\n    missingDocs = await getDocumentsInArray({\n      fetchIds: autoFetchIds,\n      client: originClient,\n      pluginConfig,\n    })\n  } catch (fetchErr) {\n    setMessage({\n      tone: 'critical',\n      text:\n        (fetchErr instanceof Error ? fetchErr.message : '') || description || 'Duplication Failed',\n    })\n\n    return\n  }\n\n  if (!missingDocs.length) {\n    setMessage({tone: 'default', text: 'Retrying documents one by one...'})\n    await commitOneByOne(\n      orderDocsDependenciesFirst(transactionDocs),\n      destinationClient,\n      setMessage,\n      onSuccess,\n    )\n\n    return\n  }\n\n  // Don't re-commit documents already in the failed transaction, or ones the\n  // user explicitly deselected (including transitive refs of those)\n  const existingIds = new Set(transactionDocs.map((doc) => doc._id))\n  // Reverse so transitive refs (appended last by getDocumentsInArray) are processed first\n  const newMissingDocs = [...missingDocs]\n    .reverse()\n    .filter((doc) => !existingIds.has(doc._id) && !excludedIds.has(doc._id))\n\n  // Nothing new to add — retrying the same transaction would just loop until the depth cap\n  if (!newMissingDocs.length) {\n    setMessage({tone: 'default', text: 'Retrying documents one by one...'})\n    await commitOneByOne(\n      orderDocsDependenciesFirst(transactionDocs),\n      destinationClient,\n      setMessage,\n      onSuccess,\n    )\n\n    return\n  }\n\n  setMessage({tone: 'default', text: `Duplicating ${newMissingDocs.length} missing document(s)...`})\n\n  // Seed with the caller's remaps so recovered documents referencing an SVG that\n  // was uploaded earlier are repointed at its destination _id, even when that\n  // asset isn't re-fetched here (e.g. `pluginConfig.filter` excludes assets)\n  const svgMaps: {old: string; new: string}[] = [...inheritedSvgMaps]\n\n  // Process with the same concurrency limit as the main duplication path, while\n  // writing into index slots so dependency-first order is preserved\n  const recoveredChunks: SanityDocument[][] = Array.from({length: newMissingDocs.length}, () => [])\n\n  try {\n    await mapWithConcurrency(\n      newMissingDocs.map((doc, index) => ({doc, index})),\n      3,\n      async ({doc, index}) => {\n        if (!isAssetDocument(doc)) {\n          recoveredChunks[index] = [doc]\n\n          return\n        }\n\n        const {docs, svgMap} = await uploadAssetForRecovery(doc, destinationClient, token)\n        recoveredChunks[index] = docs\n\n        if (svgMap) {\n          svgMaps.push(svgMap)\n        }\n      },\n    )\n  } catch (uploadErr) {\n    setMessage({\n      tone: 'critical',\n      text:\n        (uploadErr instanceof Error ? uploadErr.message : '') ||\n        description ||\n        'Duplication Failed',\n    })\n\n    return\n  }\n\n  const recoveredDocs = recoveredChunks.flat()\n\n  // Remap SVG _ref's in both recovered and original transaction docs\n  const remappedRecoveredDocs = remapSvgRefs(recoveredDocs, svgMaps)\n  const remappedTransactionDocs = remapSvgRefs(transactionDocs, svgMaps)\n\n  // Put recovered (referenced) docs first so sequential commits land\n  // dependencies before the documents that point at them\n  const allDocs = orderDocsDependenciesFirst([...remappedRecoveredDocs, ...remappedTransactionDocs])\n\n  const retryTransaction = destinationClient.transaction()\n  allDocs.forEach((doc) => retryTransaction.createOrReplace(doc))\n\n  try {\n    await retryTransaction.commit()\n    setMessage({tone: 'positive', text: 'Duplication complete!'})\n    onSuccess()\n  } catch (retryErr) {\n    if (isReferenceMutationError(retryErr)) {\n      // Another layer of missing refs — recurse with the expanded set\n      await handleReferenceError({\n        ...options,\n        err: retryErr,\n        transactionDocs: allDocs,\n        depth: depth + 1,\n        svgMaps,\n      })\n\n      return\n    }\n\n    setMessage({tone: 'default', text: 'Retrying documents one by one...'})\n    await commitOneByOne(allDocs, destinationClient, setMessage, onSuccess)\n  }\n}\n\nexport default function Duplicator(props: DuplicatorProps) {\n  const {docs, token, pluginConfig, onDuplicated} = props\n  const theme = useTheme()\n  const isDarkMode = getTheme_v2({sanity: theme.sanity}).color._dark\n\n  // Prepare origin (this Studio) client\n  const originClient = useClient({apiVersion: pluginConfig.apiVersion})\n\n  const schema = useSchema()\n\n  // Create list of dataset options\n  // and set initial value of dropdown\n  const workspaces = useWorkspaces()\n  const {projectId: sourceProjectId, dataset: sourceDataset} = originClient.config()\n  const workspacesOptions: WorkspaceOption[] = workspaces.map((workspace) => {\n    const isSourceWorkspace =\n      workspace.projectId === sourceProjectId && workspace.dataset === sourceDataset\n    const isAllowedMigration = isAllowedMigrationTarget({\n      migrationFilters: pluginConfig.migrationFilters,\n      sourceProjectId,\n      sourceDataset,\n      targetProjectId: workspace.projectId,\n      targetDataset: workspace.dataset,\n    })\n\n    return {\n      ...workspace,\n      disabled: isSourceWorkspace || !isAllowedMigration,\n    }\n  })\n\n  const currentWorkspace = workspacesOptions.find(\n    (workspace) => workspace.projectId === sourceProjectId && workspace.dataset === sourceDataset,\n  )\n\n  const [destination, setDestination] = useState<WorkspaceOption | null>(\n    workspaces.length ? (workspacesOptions.find((space) => !space.disabled) ?? null) : null,\n  )\n  const [message, setMessage] = useState<Message | null>(null)\n  const [payload, setPayload] = useState<PayloadItem[]>([])\n\n  const [isDuplicating, setIsDuplicating] = useState(false)\n  const [isGathering, setIsGathering] = useState(false)\n  const [progress, setProgress] = useState<[number, number]>([0, 0])\n\n  // References found in the initial docs\n  const initialRefsCount = useMemo(\n    () => docs.reduce((acc, doc) => acc + extractWithPath(`.._ref`, doc).length, 0),\n    [docs],\n  )\n  const hasReferences = initialRefsCount > 0\n  const initialMessage: Message | null = hasReferences\n    ? {tone: `caution`, text: createInitialMessage(docs.length, initialRefsCount)}\n    : null\n  const displayMessage = message ?? initialMessage\n\n  // Check if payload documents exist at destination\n  async function updatePayloadStatuses(payloadActual: PayloadItem[], dest: WorkspaceOption | null) {\n    if (!payloadActual.length || !dest?.name) {\n      return\n    }\n\n    const payloadIds = payloadActual.map(({doc}) => doc._id)\n    const destinationClient = originClient.withConfig({\n      dataset: dest.dataset,\n      projectId: dest.projectId,\n    })\n    const destinationData = await destinationClient.fetch<SanityDocument[]>(\n      `*[_id in $payloadIds]{ _id, _updatedAt }`,\n      {payloadIds},\n    )\n    // Index the destination docs by `_id` so status updates stay O(n) instead\n    // of O(n²) when looking them up for each payload item below.\n    const destinationById = new Map(destinationData.map((doc) => [doc._id, doc]))\n\n    setPayload(\n      payloadActual.map((item) => {\n        const existingDoc = destinationById.get(item.doc._id)\n        let status: keyof MessageTypes = 'CREATE'\n\n        if (existingDoc?._updatedAt && item.doc._updatedAt) {\n          if (existingDoc._updatedAt === item.doc._updatedAt) {\n            // Exact same document exists at destination\n            // We don't compare by _rev because that is updated in a transaction\n            status = `EXISTS`\n          } else {\n            status =\n              new Date(existingDoc._updatedAt) > new Date(item.doc._updatedAt)\n                ? // Document at destination is newer\n                  `OVERWRITE`\n                : // Document at destination is older\n                  `UPDATE`\n          }\n        }\n\n        return {...item, status}\n      }),\n    )\n  }\n\n  // Build the initial payload and check statuses at the current destination\n  const initializePayload = useEffectEvent((nextDocs: SanityDocument[]) => {\n    const initialPayload: PayloadItem[] = nextDocs.map((doc) => ({include: true, doc}))\n    updatePayloadStatuses(initialPayload, destination).catch(console.error)\n  })\n\n  // Sync the payload with the docs prop and the destination dataset.\n  // setPayload only runs after fetching document statuses from the\n  // destination resolves, not synchronously within the effect.\n  // See: https://github.com/facebook/react/issues/34743\n  useEffect(() => {\n    // oxlint-disable-next-line react/set-state-in-effect\n    initializePayload(docs)\n  }, [docs])\n\n  function handleCheckbox(_id: string) {\n    setPayload((current) =>\n      current.map((item) => (item.doc._id === _id ? {...item, include: !item.include} : item)),\n    )\n  }\n\n  // Find and recursively follow references beginning with this document\n  async function handleReferences() {\n    setIsGathering(true)\n\n    try {\n      const docIds = docs.map((doc) => doc._id)\n\n      const payloadDocs = await getDocumentsInArray({\n        fetchIds: docIds,\n        client: originClient,\n        pluginConfig,\n      })\n      const draftDocs = await getDocumentsInArray({\n        fetchIds: docIds.map((id) => `drafts.${id}`),\n        client: originClient,\n        projection: `{_id}`,\n        pluginConfig,\n      })\n      const draftDocsIds = new Set(draftDocs.map(({_id}) => _id))\n\n      // Shape it up\n      const payloadShaped: PayloadItem[] = payloadDocs.map((doc) => ({\n        doc,\n        // Include this in the transaction?\n        include: true,\n        // Does it exist at the destination?\n        status: undefined,\n        // Does it have any drafts?\n        hasDraft: draftDocsIds.has(`drafts.${doc._id}`),\n      }))\n\n      setPayload(payloadShaped)\n      updatePayloadStatuses(payloadShaped, destination).catch(console.error)\n    } catch (err) {\n      console.error(err)\n    }\n\n    setIsGathering(false)\n  }\n\n  // Duplicate payload to destination dataset\n  async function handleDuplicate() {\n    if (!destination) {\n      return\n    }\n\n    setIsDuplicating(true)\n\n    const assetsCount = payload.filter(({doc, include}) => include && isAssetId(doc._id)).length\n    let currentProgress = 0\n    setProgress([currentProgress, assetsCount])\n\n    setMessage({text: 'Duplicating...', tone: `transparent`})\n\n    const destinationClient = originClient.withConfig({\n      apiVersion: pluginConfig.apiVersion,\n      dataset: destination.dataset,\n      projectId: destination.projectId,\n    })\n\n    const transactionDocs: SanityDocument[] = []\n    const svgMaps: {old: string; new: string}[] = []\n\n    // Upload assets and then add to transaction\n    async function processDoc(doc: SanityDocument): Promise<void> {\n      if (!isAssetDocument(doc)) {\n        transactionDocs.push(doc)\n\n        return\n      }\n\n      // Download and upload asset\n      // Get the *original* image with this dlRaw param to create the same deterministic _id\n      const typeIsFile = isSanityFileAsset(doc)\n      const downloadUrl = typeIsFile ? doc.url : `${doc.url}?dlRaw=true`\n\n      const res = await fetch(downloadUrl, assetDownloadInit(downloadUrl, token, typeIsFile))\n\n      // Fail fast instead of uploading an error response (e.g. 401/403/404)\n      // body as the asset's binary data.\n      if (!res.ok) {\n        throw new Error(\n          `Failed to download asset \"${doc.originalFilename ?? doc._id}\" (${res.status} ${res.statusText})`,\n        )\n      }\n\n      const assetData = await res.blob()\n\n      const options = {filename: doc.originalFilename}\n      const assetDoc = await destinationClient.assets.upload(\n        typeIsFile ? `file` : `image`,\n        assetData,\n        options,\n      )\n\n      // SVG _id's need remapping before transaction\n      if (doc.extension === 'svg') {\n        svgMaps.push({old: doc._id, new: assetDoc._id})\n      }\n\n      // Merge the original asset document's editorial metadata (e.g. `altText`,\n      // `title`) — which the upload response omits — with the canonical fields of\n      // the freshly uploaded asset (`_id`, `url`, `path`, `assetId`, `sha1hash`,\n      // ...). The uploaded values win, so `url`/`path` no longer reference the\n      // origin dataset. For SVGs the uploaded `_id` differs from the source\n      // (the file is sanitized on upload), so pushing a single merged document at\n      // the new `_id` — and remapping references to it below — avoids leaving an\n      // orphaned asset document behind at the original `_id`.\n      transactionDocs.push({...doc, ...assetDoc})\n\n      currentProgress += 1\n      setMessage({\n        text: `Duplicating ${currentProgress}/${assetsCount} Assets`,\n        tone: 'default',\n      })\n      setProgress([currentProgress, assetsCount])\n    }\n\n    try {\n      const payloadIncludedDocs = payload.filter((item) => item.include).map((item) => item.doc)\n\n      // Promises are limited to three at once\n      await mapWithConcurrency(payloadIncludedDocs, 3, processDoc)\n    } catch (err) {\n      console.error(err)\n      setIsDuplicating(false)\n      setProgress([0, 0])\n      setMessage({\n        tone: 'critical',\n        text: err instanceof Error ? err.message : `Duplication Failed`,\n      })\n\n      return\n    }\n\n    // Remap SVG references to new _id's. SVG assets are sanitized on upload, so\n    // their `_id` changes; references still pointing at the original `_id` must\n    // be updated to the uploaded one.\n    const svgIdRemap = new Map(svgMaps.map(({old, new: next}) => [old, next]))\n    const transactionDocsMapped =\n      svgIdRemap.size === 0\n        ? transactionDocs\n        : transactionDocs.map((doc) => {\n            const references = extractWithPath(`.._ref`, doc)\n\n            if (!references.length) {\n              return doc\n            }\n\n            // Clone lazily before the first mutation: some of these docs are the\n            // same objects held in React state (`payload`), and `dset` mutates in\n            // place — which would corrupt state and trip up the React Compiler.\n            let mappedDoc = doc\n\n            references.forEach((ref) => {\n              const newRefValue =\n                typeof ref.value === 'string' ? svgIdRemap.get(ref.value) : undefined\n\n              if (newRefValue) {\n                if (mappedDoc === doc) {\n                  mappedDoc = structuredClone(doc)\n                }\n\n                dset(mappedDoc, ref.path.join('.'), newRefValue)\n              }\n            })\n\n            return mappedDoc\n          })\n\n    // Create transaction\n    const transaction = destinationClient.transaction()\n\n    transactionDocsMapped.forEach((doc) => {\n      transaction.createOrReplace(doc)\n    })\n\n    const onCommitSuccess = () => {\n      updatePayloadStatuses(payload, destination).catch(console.error)\n    }\n\n    try {\n      await transaction.commit()\n      setMessage({tone: 'positive', text: 'Duplication complete!'})\n\n      onCommitSuccess()\n    } catch (err) {\n      if (isReferenceMutationError(err)) {\n        await handleReferenceError({\n          err,\n          transactionDocs: transactionDocsMapped,\n          originClient,\n          destinationClient,\n          pluginConfig,\n          token,\n          setMessage,\n          onSuccess: onCommitSuccess,\n          excludedIds: new Set(payload.filter((item) => !item.include).map((item) => item.doc._id)),\n          svgMaps,\n        })\n      } else {\n        const description = getErrorDescription(err)\n        setMessage({\n          tone: 'critical',\n          text: description || `Duplication Failed`,\n        })\n      }\n    }\n\n    setIsDuplicating(false)\n    setProgress([0, 0])\n    if (onDuplicated) {\n      try {\n        await onDuplicated()\n      } catch (error) {\n        const text = error instanceof Error ? error.message : String(error)\n        setMessage({tone: 'critical', text: `Error in onDuplicated hook: ${text}`})\n      }\n    }\n  }\n\n  function handleChange(e: ChangeEvent<HTMLSelectElement>) {\n    if (!workspacesOptions.length) {\n      return\n    }\n\n    const targeted = workspacesOptions.find((space) => space.name === e.currentTarget.value)\n\n    if (targeted) {\n      setDestination(targeted)\n      updatePayloadStatuses(payload, targeted).catch(console.error)\n    }\n  }\n\n  const payloadCount = payload.length\n  const firstSvgIndex = payload.findIndex(({doc}) => doc['extension'] === 'svg')\n  const selectedDocumentsCount = payload.filter(\n    (item) => item.include && !isAssetId(item.doc._id),\n  ).length\n  const selectedAssetsCount = payload.filter(\n    (item) => item.include && isAssetId(item.doc._id),\n  ).length\n  const selectedTotal = selectedDocumentsCount + selectedAssetsCount\n  const destinationTitle = destination?.title ?? destination?.name\n  const hasMultipleProjectIds =\n    new Set(workspacesOptions.map((space) => space?.projectId).filter(Boolean)).size > 1\n\n  const headingText = [selectedTotal, `/`, payloadCount, `Documents and Assets selected`].join(` `)\n\n  const buttonTextParts = [`Duplicate`]\n\n  if (selectedDocumentsCount > 0) {\n    buttonTextParts.push(\n      String(selectedDocumentsCount),\n      selectedDocumentsCount === 1 ? `Document` : `Documents`,\n    )\n  }\n\n  if (selectedAssetsCount > 0) {\n    // Only join with \"and\" when documents are also part of the selection.\n    if (selectedDocumentsCount > 0) {\n      buttonTextParts.push(`and`)\n    }\n\n    buttonTextParts.push(\n      String(selectedAssetsCount),\n      selectedAssetsCount === 1 ? `Asset` : `Assets`,\n    )\n  }\n\n  if (originClient.config().projectId !== destination?.projectId) {\n    buttonTextParts.push(`between Projects`)\n  }\n\n  buttonTextParts.push(`to`, String(destinationTitle))\n\n  const buttonText = buttonTextParts.join(` `)\n\n  if (workspacesOptions.length < 2) {\n    return (\n      <Feedback tone=\"critical\">\n        <code>sanity.config.ts</code> must contain at least two Workspaces to use this plugin.\n      </Feedback>\n    )\n  }\n\n  if (!destination) {\n    return (\n      <Feedback tone=\"critical\">\n        No allowed Migration destinations are available for this Dataset. Check the{' '}\n        <code>migrationFilters</code> plugin config, or add another Workspace as a valid target.\n      </Feedback>\n    )\n  }\n\n  return (\n    <Container width={1}>\n      <Card border>\n        <Stack>\n          <Card padding={4} style={stickyStyles(isDarkMode)}>\n            <Stack gap={4}>\n              <Flex gap={3}>\n                <Stack style={{flex: 1}} gap={3}>\n                  <Label>Duplicate from</Label>\n                  <Select readOnly value={currentWorkspace?.name}>\n                    {currentWorkspace ? (\n                      <option value={currentWorkspace.name}>\n                        {currentWorkspace.title ?? currentWorkspace.name}\n                        {hasMultipleProjectIds ? ` (${currentWorkspace.projectId})` : ``}\n                      </option>\n                    ) : null}\n                  </Select>\n                </Stack>\n                <Box padding={4} paddingTop={5} paddingBottom={0}>\n                  <Text size={3}>\n                    <ArrowRightIcon />\n                  </Text>\n                </Box>\n                <Stack style={{flex: 1}} gap={3}>\n                  <Label>To Destination</Label>\n                  <Select onChange={handleChange}>\n                    {workspacesOptions.map((space) => (\n                      <option key={space.name} value={space.name} disabled={space.disabled}>\n                        {space.title ?? space.name}\n                        {hasMultipleProjectIds ? ` (${space.projectId})` : ``}\n                        {currentWorkspace?.name === space.name &&\n                        currentWorkspace.projectId === space.projectId\n                          ? ` (Current)`\n                          : ``}\n                      </option>\n                    ))}\n                  </Select>\n                </Stack>\n              </Flex>\n\n              {isDuplicating && (\n                <Card border radius={2}>\n                  <Card\n                    style={{\n                      width: '100%',\n                      // Guard against a 0-asset payload (progress[1] === 0),\n                      // which would make the ratio NaN and produce an invalid transform.\n                      transform: `scaleX(${progress[1] > 0 ? progress[0] / progress[1] : 0})`,\n                      transformOrigin: 'left',\n                      transition: 'transform .2s ease',\n                      boxSizing: 'border-box',\n                    }}\n                    padding={1}\n                    tone=\"positive\"\n                  />\n                </Card>\n              )}\n              {payload.length > 0 && (\n                <>\n                  <Label>{headingText}</Label>\n                  <SelectButtons payload={payload} setPayload={setPayload} />\n                </>\n              )}\n            </Stack>\n          </Card>\n          <Card borderTop padding={4}>\n            <Stack gap={3}>\n              {displayMessage && (\n                <Card padding={3} radius={2} shadow={1} tone={displayMessage.tone}>\n                  <Text size={1}>{displayMessage.text}</Text>\n                </Card>\n              )}\n              {payload.length > 0 ? (\n                <Stack>\n                  {payload.map(({doc, include, status, hasDraft}, index) => {\n                    const schemaType = schema.get(doc._type)\n\n                    return (\n                      <Fragment key={doc._id}>\n                        <Flex align=\"center\">\n                          <Checkbox checked={include} onChange={() => handleCheckbox(doc._id)} />\n                          <Box flex={1} paddingX={3}>\n                            {schemaType ? (\n                              <Preview value={doc} schemaType={schemaType} />\n                            ) : (\n                              <Card tone=\"caution\">Invalid schema type</Card>\n                            )}\n                          </Box>\n                          <Flex align=\"center\" gap={2}>\n                            {hasDraft ? <StatusBadge status=\"UNPUBLISHED\" isAsset={false} /> : null}\n                            <StatusBadge status={status} isAsset={isAssetId(doc._id)} />\n                          </Flex>\n                        </Flex>\n                        {doc['extension'] === 'svg' && index === firstSvgIndex && (\n                          <Card padding={3} radius={2} shadow={1} tone=\"caution\">\n                            <Text size={1}>\n                              Due to how SVGs are sanitized after first uploaded, duplicated SVG\n                              assets may have new <code>_id</code>'s at the destination. The newly\n                              generated <code>_id</code> will be the same in each duplication, but\n                              it will never be the same <code>_id</code> as the first time this\n                              Asset was uploaded. References to the asset will be updated to use the\n                              new <code>_id</code>.\n                            </Text>\n                          </Card>\n                        )}\n                      </Fragment>\n                    )\n                  })}\n                </Stack>\n              ) : (\n                <Flex padding={4} align=\"center\" justify=\"center\">\n                  <Spinner />\n                </Flex>\n              )}\n              <Stack gap={2}>\n                {hasReferences && (\n                  <Button\n                    fontSize={2}\n                    padding={4}\n                    tone=\"positive\"\n                    mode=\"ghost\"\n                    icon={SearchIcon}\n                    onClick={() => void handleReferences()}\n                    text=\"Gather References\"\n                    disabled={isDuplicating || !selectedTotal || isGathering}\n                  />\n                )}\n                <Button\n                  fontSize={2}\n                  padding={4}\n                  tone=\"positive\"\n                  icon={LaunchIcon}\n                  onClick={() => void handleDuplicate()}\n                  text={buttonText}\n                  disabled={isDuplicating || !selectedTotal || isGathering}\n                />\n              </Stack>\n            </Stack>\n          </Card>\n        </Stack>\n      </Card>\n    </Container>\n  )\n}\n","import {Button, Stack, Box, Label, Text, Card, Flex, Grid, Container, TextInput} from '@sanity/ui'\nimport {type SubmitEvent, useState} from 'react'\nimport {useSchema, useClient, type SanityDocument} from 'sanity'\n\nimport type {PluginConfig} from '../types'\nimport Duplicator from './Duplicator'\n\ntype DuplicatorQueryProps = {\n  token: string\n  pluginConfig: Required<PluginConfig>\n}\n\ntype InitialData = {\n  docs: SanityDocument[]\n}\n\nexport default function DuplicatorQuery(props: DuplicatorQueryProps) {\n  const {token, pluginConfig} = props\n\n  const {queries: preDefinedQueries, apiVersion} = pluginConfig\n  const originClient = useClient({apiVersion})\n\n  const schema = useSchema()\n  const schemaTypes = schema.getTypeNames()\n\n  const [value, setValue] = useState(``)\n  const [fetched, setFetched] = useState(false)\n  const [initialData, setInitialData] = useState<InitialData>({\n    docs: [],\n  })\n\n  async function runQuery() {\n    try {\n      const res = await originClient.fetch<SanityDocument[]>(value)\n\n      // Ensure queried docs are registered to the schema\n      const registeredAndPublishedDocs = res.length\n        ? res\n            .filter((doc) => schemaTypes.includes(doc._type))\n            .filter((doc) => !doc._id.startsWith(`drafts.`))\n        : []\n\n      setInitialData({\n        docs: registeredAndPublishedDocs,\n      })\n      setFetched(true)\n    } catch (err) {\n      console.error(err)\n    }\n  }\n\n  function handleSubmit(e?: SubmitEvent<HTMLFormElement>) {\n    if (e) e.preventDefault()\n    void runQuery()\n  }\n\n  return (\n    <Card padding={[0, 0, 0, 5]}>\n      <Container>\n        <Grid gridTemplateColumns={[1, 1, 1, 2]} gap={[1, 1, 1, 4]}>\n          <Box padding={[2, 2, 2, 0]}>\n            <Card padding={4} radius={3} border>\n              <Stack gap={4}>\n                <Box>\n                  <Label>Initial Documents Query</Label>\n                </Box>\n                <Box>\n                  <Text>\n                    Start with a valid GROQ query to load initial documents. The query will need to\n                    return an Array of Objects. Drafts will be removed from the results.\n                  </Text>\n                </Box>\n                <form onSubmit={handleSubmit}>\n                  <Flex>\n                    <Box flex={1} paddingRight={2}>\n                      <TextInput\n                        style={{fontFamily: 'monospace'}}\n                        fontSize={2}\n                        onChange={(event) => setValue(event.currentTarget.value)}\n                        padding={4}\n                        placeholder={`*[_type == \"article\"]`}\n                        value={value ?? ``}\n                      />\n                    </Box>\n                    <Button\n                      padding={2}\n                      paddingX={4}\n                      tone=\"primary\"\n                      onClick={() => handleSubmit()}\n                      text=\"Query\"\n                      disabled={!value}\n                    />\n                  </Flex>\n                </form>\n              </Stack>\n            </Card>\n            {preDefinedQueries && preDefinedQueries?.length > 0 && (\n              <Card marginTop={2} padding={4} radius={3} border>\n                <Box>\n                  <Stack gap={4}>\n                    <Box>\n                      <Label>Predefined Queries</Label>\n                    </Box>\n                    <Stack gap={2}>\n                      {preDefinedQueries.map((query) => (\n                        <Button\n                          key={query.label.replace(/\\s+/g, '-')}\n                          padding={2}\n                          paddingX={4}\n                          tone=\"primary\"\n                          onClick={() => setValue(`*[${query.query}]`)}\n                          text={query.label}\n                        />\n                      ))}\n                    </Stack>\n                  </Stack>\n                </Box>\n              </Card>\n            )}\n          </Box>\n          {fetched && initialData.docs.length < 1 && (\n            <Container width={1}>\n              <Card padding={5}>\n                {value ? `No documents match this query` : `Start with a valid GROQ query`}\n              </Card>\n            </Container>\n          )}\n          {initialData.docs?.length > 0 && (\n            <Duplicator docs={initialData.docs} token={token} pluginConfig={pluginConfig} />\n          )}\n        </Grid>\n      </Container>\n    </Card>\n  )\n}\n","import {Grid, Card, Container, Button} from '@sanity/ui'\nimport {useState, useEffect} from 'react'\nimport {type SanityDocument, useClient} from 'sanity'\n\nimport type {DuplicatorProps} from './Duplicator'\nimport Duplicator from './Duplicator'\n\nexport default function DuplicatorWrapper(props: DuplicatorProps) {\n  const {docs, token, pluginConfig, onDuplicated} = props\n  const [inbound, setInbound] = useState<SanityDocument[]>([])\n  const {follow, apiVersion} = pluginConfig\n\n  // Make the first mode the default if there's only one\n  const [mode, setMode] = useState<'inbound' | 'outbound'>(\n    follow.length === 1 ? (follow[0] ?? 'outbound') : 'outbound',\n  )\n  const client = useClient({apiVersion})\n\n  // \"Inbound\" will start with all documents that reference the first one\n  // And then you can gather \"Outbound\" references thereafter\n  useEffect(() => {\n    async function fetchInbound() {\n      const firstDocId = docs[0]?._id\n\n      if (!follow.includes(`inbound`) || !firstDocId) {\n        return\n      }\n\n      const inboundReferences = await client.fetch<SanityDocument[]>(`*[references($id)]`, {\n        id: firstDocId,\n      })\n      setInbound([...docs, ...inboundReferences])\n    }\n\n    fetchInbound().catch(console.error)\n  }, [client, docs, follow])\n\n  return (\n    <Container>\n      {follow.length > 1 && (follow.includes(`inbound`) || follow.includes(`outbound`)) ? (\n        <Card paddingX={4} paddingBottom={4} marginBottom={4} borderBottom>\n          <Grid gridTemplateColumns={2} gap={4}>\n            {follow.includes(`outbound`) ? (\n              <Button\n                mode=\"ghost\"\n                tone=\"primary\"\n                selected={mode === 'outbound'}\n                onClick={() => setMode('outbound')}\n                text=\"Outbound\"\n              />\n            ) : null}\n            {follow.includes(`inbound`) ? (\n              <Button\n                mode=\"ghost\"\n                tone=\"primary\"\n                selected={mode === 'inbound'}\n                onClick={() => setMode('inbound')}\n                disabled={inbound.length === 0}\n                text={inbound.length > 0 ? `Inbound (${inbound.length})` : 'No inbound references'}\n              />\n            ) : null}\n          </Grid>\n        </Card>\n      ) : null}\n      <Duplicator\n        docs={mode === 'outbound' ? docs : inbound}\n        token={token}\n        pluginConfig={pluginConfig}\n        onDuplicated={onDuplicated}\n      />\n    </Container>\n  )\n}\n","import {Button, Flex} from '@sanity/ui'\nimport {useCallback} from 'react'\nimport {useClient} from 'sanity'\n\nimport {SECRET_NAMESPACE} from '../helpers/constants'\n\ntype ResetSecretProps = {\n  apiVersion: string\n}\n\nexport default function ResetSecret({apiVersion}: ResetSecretProps) {\n  const client = useClient({apiVersion})\n\n  const handleClick = useCallback(() => {\n    client.delete({query: `*[_id == \"secrets.${SECRET_NAMESPACE}\"]`}).catch(console.error)\n  }, [client])\n\n  return (\n    <Flex align=\"center\" justify=\"flex-end\" paddingX={[2, 2, 2, 5]} paddingY={5}>\n      <Button\n        text=\"Reset Secret\"\n        onClick={handleClick}\n        mode=\"ghost\"\n        tone=\"critical\"\n        fontSize={1}\n        padding={2}\n      />\n    </Flex>\n  )\n}\n","import {useSecrets, SettingsView} from '@sanity/studio-secrets'\nimport {Flex, Box, Spinner} from '@sanity/ui'\nimport type {SanityDocument} from 'sanity'\n\nimport {useCrossDatasetDuplicatorConfig} from '../context/ConfigProvider'\nimport {SECRET_NAMESPACE} from '../helpers/constants'\nimport DuplicatorQuery from './DuplicatorQuery'\nimport DuplicatorWrapper from './DuplicatorWrapper'\nimport Feedback from './Feedback'\nimport ResetSecret from './ResetSecret'\n\n// Check for auth secret (required for asset uploads)\nconst secretConfigKeys = [\n  {\n    key: 'bearerToken',\n    title:\n      'An API token with Viewer permissions is required to duplicate the original files of assets, and will be used for all Duplications. Create one at sanity.io/manage',\n    description: '',\n  },\n]\n\ntype Secrets = {\n  bearerToken?: string\n}\n\ntype CrossDatasetDuplicatorProps = {\n  mode: 'tool' | 'action'\n  docs: SanityDocument[]\n  onDuplicated?: () => Promise<void>\n}\n\nexport default function CrossDatasetDuplicator(props: CrossDatasetDuplicatorProps) {\n  const {mode, docs, onDuplicated} = props\n  const pluginConfig = useCrossDatasetDuplicatorConfig()\n\n  const {loading, secrets} = useSecrets<Secrets>(SECRET_NAMESPACE)\n\n  if (loading) {\n    return (\n      <Flex justify=\"center\" align=\"center\">\n        <Box padding={5}>\n          <Spinner />\n        </Box>\n      </Flex>\n    )\n  }\n\n  // A bearer token is required to duplicate assets, so the prompt cannot be\n  // dismissed until one is saved\n  if (!secrets?.bearerToken) {\n    return (\n      <SettingsView\n        title=\"Token Required\"\n        namespace={SECRET_NAMESPACE}\n        keys={secretConfigKeys}\n        onClose={() => null}\n      />\n    )\n  }\n\n  if (mode === 'tool' && pluginConfig) {\n    return (\n      <>\n        <DuplicatorQuery token={secrets.bearerToken} pluginConfig={pluginConfig} />\n        <ResetSecret apiVersion={pluginConfig.apiVersion} />\n      </>\n    )\n  }\n\n  if (!docs?.length) {\n    return <Feedback>No docs passed into Duplicator Tool</Feedback>\n  }\n\n  if (!pluginConfig) {\n    return <Feedback>No plugin config</Feedback>\n  }\n\n  return (\n    <DuplicatorWrapper\n      docs={docs}\n      token={secrets.bearerToken}\n      pluginConfig={pluginConfig}\n      onDuplicated={onDuplicated}\n    />\n  )\n}\n","import type {CrossDatasetDuplicatorActionProps} from '../types'\nimport CrossDatasetDuplicator from './CrossDatasetDuplicator'\n\n/**\n * Component to perform a migration from the Cross Dataset Duplicator plugin\n * @public\n */\nexport function CrossDatasetDuplicatorAction(props: CrossDatasetDuplicatorActionProps) {\n  const {docs, onDuplicated} = props\n\n  return <CrossDatasetDuplicator mode=\"action\" docs={docs} onDuplicated={onDuplicated} />\n}\n","import {LaunchIcon} from '@sanity/icons/Launch'\nimport {useState} from 'react'\nimport type {DocumentActionProps} from 'sanity'\n\nimport {CrossDatasetDuplicatorAction} from '../components/CrossDatasetDuplicatorAction'\n\n/**\n * Document action from the Cross Dataset Duplicator plugin\n * @public\n */\nexport const DuplicateToAction = (props: DocumentActionProps) => {\n  const {draft, published} = props\n  const [dialogOpen, setDialogOpen] = useState(false)\n\n  return {\n    disabled: Boolean(draft),\n    title: draft ? `Document must be Published to begin` : null,\n    label: 'Duplicate to...',\n    dialog: dialogOpen &&\n      published && {\n        type: 'modal',\n        title: 'Cross Dataset Duplicator',\n        content: <CrossDatasetDuplicatorAction docs={[published]} />,\n        onClose: () => setDialogOpen(false),\n      },\n    onHandle: () => setDialogOpen(true),\n    icon: LaunchIcon,\n  }\n}\n\nDuplicateToAction.action = 'duplicateTo'\n","import type {SanityDocument, Tool} from 'sanity'\n\nimport CrossDatasetDuplicator from './CrossDatasetDuplicator'\n\nexport type MultiToolConfig = {\n  docs: SanityDocument[]\n}\n\ntype CrossDatasetDuplicatorProps = {\n  tool: Tool<MultiToolConfig>\n}\n\nexport function CrossDatasetDuplicatorTool(props: CrossDatasetDuplicatorProps) {\n  const {docs = []} = props.tool.options ?? {}\n\n  return <CrossDatasetDuplicator mode=\"tool\" docs={docs} />\n}\n","import {LaunchIcon} from '@sanity/icons/Launch'\nimport type {Tool} from 'sanity'\n\nimport {\n  CrossDatasetDuplicatorTool,\n  type MultiToolConfig,\n} from '../components/CrossDatasetDuplicatorTool'\n\nexport const crossDatasetDuplicatorTool = (): Tool<MultiToolConfig> => ({\n  title: 'Duplicator',\n  name: 'duplicator',\n  icon: LaunchIcon,\n  component: CrossDatasetDuplicatorTool,\n  options: {\n    docs: [],\n  },\n})\n","import {definePlugin} from 'sanity'\n\nimport {DuplicateToAction} from './actions/DuplicateToAction'\nimport {ConfigProvider} from './context/ConfigProvider'\nimport {DEFAULT_CONFIG} from './helpers/constants'\nimport {crossDatasetDuplicatorTool} from './tool'\nimport type {PluginConfig} from './types'\n\n/**\n * Plugin: Cross Dataset Duplicator\n * @public\n */\nexport const crossDatasetDuplicator = definePlugin<Partial<PluginConfig> | void>((config = {}) => {\n  const pluginConfig = {...DEFAULT_CONFIG, ...config}\n  const {types} = pluginConfig\n\n  return {\n    name: '@sanity/cross-dataset-duplicator',\n    tools: (prev) => (pluginConfig.tool ? [...prev, crossDatasetDuplicatorTool()] : prev),\n    studio: {\n      components: {\n        layout: (props) => <ConfigProvider {...props} pluginConfig={pluginConfig} />,\n      },\n    },\n    document: {\n      actions: (prev, {schemaType}) => {\n        return types && types.includes(schemaType) ? [...prev, DuplicateToAction] : prev\n      },\n    },\n  }\n})\n"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"index.js","names":["CrossDatasetDuplicatorContext.Provider","pluginConfig","props.renderDefault(rest)","<CrossDatasetDuplicatorContext.Provider value={pluginConfig}>\n      {props.renderDefault(rest)}\n    </CrossDatasetDuplicatorContext.Provider>","_c","tone = 'caution'","<Text size={1}>{children}</Text>","<Card padding={3} radius={2} shadow={1} tone={tone}>\n      <Text size={1}>{children}</Text>\n    </Card>","_c","() =>\n    payload.length && payload.every((item) => item.include) ? ['ALL'] : []","payload.length","(item) => item.include","function handleSelectButton(action: Action) {\n    if (!payload.length) return\n\n    setPayload((current) =>\n      current.map((item) => ({...item, include: shouldInclude(item, action)})),\n    )\n    setDisabledActions([action])\n  }","length","item","buttons.map((button) =>\n          'action' in button ? (\n            <Button\n              key={button.action}\n              fontSize={1}\n              mode=\"bleed\"\n              padding={2}\n              text={button.label}\n              disabled={disabledActions.includes(button.action)}\n              onClick={() => handleSelectButton(button.action)}\n            />\n          ) : (\n            <Card key={button.divider} borderLeft />\n          ),\n        )","<Card padding={1} radius={3} shadow={1}>\n      <Flex gap={2} wrap=\"wrap\">\n        {buttons.map((button) =>\n          'action' in button ? (\n            <Button\n              key={button.action}\n              fontSize={1}\n              mode=\"bleed\"\n              padding={2}\n              text={button.label}\n              disabled={disabledActions.includes(button.action)}\n              onClick={() => handleSelectButton(button.action)}\n            />\n          ) : (\n            <Card key={button.divider} borderLeft />\n          ),\n        )}\n      </Flex>\n    </Card>","_c","_temp","<Badge padding={2} fontSize={1}>\n        Checking...\n      </Badge>","{maxWidth: 200}","<Box padding={3} style={{maxWidth: 200}}>\n          <Text size={1}>{badgeText}</Text>\n        </Box>","['right', 'left']","<Box marginLeft={2} display={'inline-block'} as=\"span\">\n          <InfoOutlineIcon />\n        </Box>","<Badge padding={3} fontSize={1} tone={badgeTone}>\n        {badgeStatus}\n        <Box marginLeft={2} display={'inline-block'} as=\"span\">\n          <InfoOutlineIcon />\n        </Box>\n      </Badge>","<Tooltip\n      content={\n        <Box padding={3} style={{maxWidth: 200}}>\n          <Text size={1}>{badgeText}</Text>\n        </Box>\n      }\n      fallbackPlacements={['right', 'left']}\n      placement=\"top\"\n      portal\n    >\n      <Badge padding={3} fontSize={1} tone={badgeTone}>\n        {badgeStatus}\n        <Box marginLeft={2} display={'inline-block'} as=\"span\">\n          <InfoOutlineIcon />\n        </Box>\n      </Badge>\n    </Tooltip>","_c","{apiVersion: pluginConfig.apiVersion}","apiVersion","workspace","(space) => !space.disabled","[]","[0, 0]","(acc, doc) => acc + extractWithPath(`.._ref`, doc).length","hasReferences\n    ? {tone: `caution`, text: createInitialMessage(docs.length, initialRefsCount)}\n    : null","length","async function updatePayloadStatuses(payloadActual: PayloadItem[], dest: WorkspaceOption | null) {\n    if (!payloadActual.length || !dest?.name) {\n      return\n    }\n\n    const payloadIds = payloadActual.map(({doc}) => doc._id)\n    const destinationClient = originClient.withConfig({\n      dataset: dest.dataset,\n      projectId: dest.projectId,\n    })\n    const destinationData = await destinationClient.fetch<SanityDocument[]>(\n      `*[_id in $payloadIds]{ _id, _updatedAt }`,\n      {payloadIds},\n    )\n    // Index the destination docs by `_id` so status updates stay O(n) instead\n    // of O(n²) when looking them up for each payload item below.\n    const destinationById = new Map(destinationData.map((doc) => [doc._id, doc]))\n\n    setPayload(\n      payloadActual.map((item) => {\n        const existingDoc = destinationById.get(item.doc._id)\n        let status: keyof MessageTypes = 'CREATE'\n\n        if (existingDoc?._updatedAt && item.doc._updatedAt) {\n          if (existingDoc._updatedAt === item.doc._updatedAt) {\n            // Exact same document exists at destination\n            // We don't compare by _rev because that is updated in a transaction\n            status = `EXISTS`\n          } else {\n            status =\n              new Date(existingDoc._updatedAt) > new Date(item.doc._updatedAt)\n                ? // Document at destination is newer\n                  `OVERWRITE`\n                : // Document at destination is older\n                  `UPDATE`\n          }\n        }\n\n        return {...item, status}\n      }),\n    )\n  }","({doc}) => doc._id","(doc) => [doc._id, doc]","(nextDocs: SanityDocument[]) => {\n    const initialPayload: PayloadItem[] = nextDocs.map((doc) => ({include: true, doc}))\n    updatePayloadStatuses(initialPayload, destination).catch(console.error)\n  }","(doc) => ({include: true, doc})","() => {\n    // oxlint-disable-next-line react/set-state-in-effect\n    initializePayload(docs)\n  }","[docs]","function handleCheckbox(_id: string) {\n    setPayload((current) =>\n      current.map((item) => (item.doc._id === _id ? {...item, include: !item.include} : item)),\n    )\n  }","item","async function handleReferences() {\n    setIsGathering(true)\n\n    try {\n      const docIds = docs.map((doc) => doc._id)\n\n      const payloadDocs = await getDocumentsInArray({\n        fetchIds: docIds,\n        client: originClient,\n        pluginConfig,\n      })\n      const draftDocs = await getDocumentsInArray({\n        fetchIds: docIds.map((id) => `drafts.${id}`),\n        client: originClient,\n        projection: `{_id}`,\n        pluginConfig,\n      })\n      const draftDocsIds = new Set(draftDocs.map(({_id}) => _id))\n\n      // Shape it up\n      const payloadShaped: PayloadItem[] = payloadDocs.map((doc) => ({\n        doc,\n        // Include this in the transaction?\n        include: true,\n        // Does it exist at the destination?\n        status: undefined,\n        // Does it have any drafts?\n        hasDraft: draftDocsIds.has(`drafts.${doc._id}`),\n      }))\n\n      setPayload(payloadShaped)\n      updatePayloadStatuses(payloadShaped, destination).catch(console.error)\n    } catch (err) {\n      console.error(err)\n    }\n\n    setIsGathering(false)\n  }","(doc) => doc._id","(id) => `drafts.${id}`","({_id}) => _id","doc","err","async function handleDuplicate() {\n    if (!destination) {\n      return\n    }\n\n    setIsDuplicating(true)\n\n    const assetsCount = payload.filter(({doc, include}) => include && isAssetId(doc._id)).length\n    let currentProgress = 0\n    setProgress([currentProgress, assetsCount])\n\n    setMessage({text: 'Duplicating...', tone: `transparent`})\n\n    const destinationClient = originClient.withConfig({\n      apiVersion: pluginConfig.apiVersion,\n      dataset: destination.dataset,\n      projectId: destination.projectId,\n    })\n\n    const transactionDocs: SanityDocument[] = []\n    const svgMaps: {old: string; new: string}[] = []\n\n    // Upload assets and then add to transaction\n    async function processDoc(doc: SanityDocument): Promise<void> {\n      if (!isAssetDocument(doc)) {\n        transactionDocs.push(doc)\n\n        return\n      }\n\n      // Download and upload asset\n      // Get the *original* image with this dlRaw param to create the same deterministic _id\n      const typeIsFile = isSanityFileAsset(doc)\n      const downloadUrl = typeIsFile ? doc.url : `${doc.url}?dlRaw=true`\n\n      const res = await fetch(downloadUrl, assetDownloadInit(downloadUrl, token, typeIsFile))\n\n      // Fail fast instead of uploading an error response (e.g. 401/403/404)\n      // body as the asset's binary data.\n      if (!res.ok) {\n        throw new Error(\n          `Failed to download asset \"${doc.originalFilename ?? doc._id}\" (${res.status} ${res.statusText})`,\n        )\n      }\n\n      const assetData = await res.blob()\n\n      const options = {filename: doc.originalFilename}\n      const assetDoc = await destinationClient.assets.upload(\n        typeIsFile ? `file` : `image`,\n        assetData,\n        options,\n      )\n\n      // SVG _id's need remapping before transaction\n      if (doc.extension === 'svg') {\n        svgMaps.push({old: doc._id, new: assetDoc._id})\n      }\n\n      // Merge the original asset document's editorial metadata (e.g. `altText`,\n      // `title`) — which the upload response omits — with the canonical fields of\n      // the freshly uploaded asset (`_id`, `url`, `path`, `assetId`, `sha1hash`,\n      // ...). The uploaded values win, so `url`/`path` no longer reference the\n      // origin dataset. For SVGs the uploaded `_id` differs from the source\n      // (the file is sanitized on upload), so pushing a single merged document at\n      // the new `_id` — and remapping references to it below — avoids leaving an\n      // orphaned asset document behind at the original `_id`.\n      transactionDocs.push({...doc, ...assetDoc})\n\n      currentProgress += 1\n      setMessage({\n        text: `Duplicating ${currentProgress}/${assetsCount} Assets`,\n        tone: 'default',\n      })\n      setProgress([currentProgress, assetsCount])\n    }\n\n    try {\n      const payloadIncludedDocs = payload.filter((item) => item.include).map((item) => item.doc)\n\n      // Promises are limited to three at once\n      await mapWithConcurrency(payloadIncludedDocs, 3, processDoc)\n    } catch (err) {\n      console.error(err)\n      setIsDuplicating(false)\n      setProgress([0, 0])\n      setMessage({\n        tone: 'critical',\n        text: err instanceof Error ? err.message : `Duplication Failed`,\n      })\n\n      return\n    }\n\n    // Remap SVG references to new _id's. SVG assets are sanitized on upload, so\n    // their `_id` changes; references still pointing at the original `_id` must\n    // be updated to the uploaded one.\n    const svgIdRemap = new Map(svgMaps.map(({old, new: next}) => [old, next]))\n    const transactionDocsMapped =\n      svgIdRemap.size === 0\n        ? transactionDocs\n        : transactionDocs.map((doc) => {\n            const references = extractWithPath(`.._ref`, doc)\n\n            if (!references.length) {\n              return doc\n            }\n\n            // Clone lazily before the first mutation: some of these docs are the\n            // same objects held in React state (`payload`), and `dset` mutates in\n            // place — which would corrupt state and trip up the React Compiler.\n            let mappedDoc = doc\n\n            references.forEach((ref) => {\n              const newRefValue =\n                typeof ref.value === 'string' ? svgIdRemap.get(ref.value) : undefined\n\n              if (newRefValue) {\n                if (mappedDoc === doc) {\n                  mappedDoc = structuredClone(doc)\n                }\n\n                dset(mappedDoc, ref.path.join('.'), newRefValue)\n              }\n            })\n\n            return mappedDoc\n          })\n\n    // Create transaction\n    const transaction = destinationClient.transaction()\n\n    transactionDocsMapped.forEach((doc) => {\n      transaction.createOrReplace(doc)\n    })\n\n    const onCommitSuccess = () => {\n      updatePayloadStatuses(payload, destination).catch(console.error)\n    }\n\n    try {\n      await transaction.commit()\n      setMessage({tone: 'positive', text: 'Duplication complete!'})\n\n      onCommitSuccess()\n    } catch (err) {\n      if (isReferenceMutationError(err)) {\n        await handleReferenceError({\n          err,\n          transactionDocs: transactionDocsMapped,\n          originClient,\n          destinationClient,\n          pluginConfig,\n          token,\n          setMessage,\n          onSuccess: onCommitSuccess,\n          excludedIds: new Set(payload.filter((item) => !item.include).map((item) => item.doc._id)),\n          svgMaps,\n        })\n      } else {\n        const description = getErrorDescription(err)\n        setMessage({\n          tone: 'critical',\n          text: description || `Duplication Failed`,\n        })\n      }\n    }\n\n    setIsDuplicating(false)\n    setProgress([0, 0])\n    if (onDuplicated) {\n      try {\n        await onDuplicated()\n      } catch (error) {\n        const text = error instanceof Error ? error.message : String(error)\n        setMessage({tone: 'critical', text: `Error in onDuplicated hook: ${text}`})\n      }\n    }\n  }","pluginConfig.apiVersion","({doc, include}) => include && isAssetId(doc._id)","destinationClient","(item) => item.include","(item) => item.doc","({old, new: next}) => [old, next]","(item) => !item.include","(item) => item.doc._id","error","space","payload.findIndex(({doc}) => doc['extension'] === 'svg')","({doc}) => doc['extension'] === 'svg'","payload.filter(\n    (item) => item.include && !isAssetId(item.doc._id),\n  )","(item) => item.include && !isAssetId(item.doc._id)","payload.filter(\n    (item) => item.include && isAssetId(item.doc._id),\n  )","(item) => item.include && isAssetId(item.doc._id)","(space) => space?.projectId","[selectedTotal, `/`, payloadCount, `Documents and Assets selected`]","projectId","<Feedback tone=\"critical\">\n        <code>sanity.config.ts</code> must contain at least two Workspaces to use this plugin.\n      </Feedback>","<Feedback tone=\"critical\">\n        No allowed Migration destinations are available for this Dataset. Check the{' '}\n        <code>migrationFilters</code> plugin config, or add another Workspace as a valid target.\n      </Feedback>","{flex: 1}","<Label>Duplicate from</Label>","<Box padding={4} paddingTop={5} paddingBottom={0}>\n                  <Text size={3}>\n                    <ArrowRightIcon />\n                  </Text>\n                </Box>","<Label>To Destination</Label>","<Select onChange={handleChange}>\n                    {workspacesOptions.map((space) => (\n                      <option key={space.name} value={space.name} disabled={space.disabled}>\n                        {space.title ?? space.name}\n                        {hasMultipleProjectIds ? ` (${space.projectId})` : ``}\n                        {currentWorkspace?.name === space.name &&\n                        currentWorkspace.projectId === space.projectId\n                          ? ` (Current)`\n                          : ``}\n                      </option>\n                    ))}\n                  </Select>","Select","workspacesOptions.map((space) => (\n                      <option key={space.name} value={space.name} disabled={space.disabled}>\n                        {space.title ?? space.name}\n                        {hasMultipleProjectIds ? ` (${space.projectId})` : ``}\n                        {currentWorkspace?.name === space.name &&\n                        currentWorkspace.projectId === space.projectId\n                          ? ` (Current)`\n                          : ``}\n                      </option>\n                    ))","<Stack style={{flex: 1}} gap={3}>\n                  <Label>To Destination</Label>\n                  <Select onChange={handleChange}>\n                    {workspacesOptions.map((space) => (\n                      <option key={space.name} value={space.name} disabled={space.disabled}>\n                        {space.title ?? space.name}\n                        {hasMultipleProjectIds ? ` (${space.projectId})` : ``}\n                        {currentWorkspace?.name === space.name &&\n                        currentWorkspace.projectId === space.projectId\n                          ? ` (Current)`\n                          : ``}\n                      </option>\n                    ))}\n                  </Select>\n                </Stack>","Stack","3","isDuplicating && (\n                <Card border radius={2}>\n                  <Card\n                    style={{\n                      width: '100%',\n                      // Guard against a 0-asset payload (progress[1] === 0),\n                      // which would make the ratio NaN and produce an invalid transform.\n                      transform: `scaleX(${progress[1] > 0 ? progress[0] / progress[1] : 0})`,\n                      transformOrigin: 'left',\n                      transition: 'transform .2s ease',\n                      boxSizing: 'border-box',\n                    }}\n                    padding={1}\n                    tone=\"positive\"\n                  />\n                </Card>\n              )","progress[1]","payload.length > 0 && (\n                <>\n                  <Label>{headingText}</Label>\n                  <SelectButtons payload={payload} setPayload={setPayload} />\n                </>\n              )","payload.length","displayMessage && (\n                <Card padding={3} radius={2} shadow={1} tone={displayMessage.tone}>\n                  <Text size={1}>{displayMessage.text}</Text>\n                </Card>\n              )","payload.length > 0 ? (\n                <Stack>\n                  {payload.map(({doc, include, status, hasDraft}, index) => {\n                    const schemaType = schema.get(doc._type)\n\n                    return (\n                      <Fragment key={doc._id}>\n                        <Flex align=\"center\">\n                          <Checkbox checked={include} onChange={() => handleCheckbox(doc._id)} />\n                          <Box flex={1} paddingX={3}>\n                            {schemaType ? (\n                              <Preview value={doc} schemaType={schemaType} />\n                            ) : (\n                              <Card tone=\"caution\">Invalid schema type</Card>\n                            )}\n                          </Box>\n                          <Flex align=\"center\" gap={2}>\n                            {hasDraft ? <StatusBadge status=\"UNPUBLISHED\" isAsset={false} /> : null}\n                            <StatusBadge status={status} isAsset={isAssetId(doc._id)} />\n                          </Flex>\n                        </Flex>\n                        {doc['extension'] === 'svg' && index === firstSvgIndex && (\n                          <Card padding={3} radius={2} shadow={1} tone=\"caution\">\n                            <Text size={1}>\n                              Due to how SVGs are sanitized after first uploaded, duplicated SVG\n                              assets may have new <code>_id</code>'s at the destination. The newly\n                              generated <code>_id</code> will be the same in each duplication, but\n                              it will never be the same <code>_id</code> as the first time this\n                              Asset was uploaded. References to the asset will be updated to use the\n                              new <code>_id</code>.\n                            </Text>\n                          </Card>\n                        )}\n                      </Fragment>\n                    )\n                  })}\n                </Stack>\n              ) : (\n                <Flex padding={4} align=\"center\" justify=\"center\">\n                  <Spinner />\n                </Flex>\n              )","{doc, include, status, hasDraft}","include","status","hasReferences && (\n                  <Button\n                    fontSize={2}\n                    padding={4}\n                    tone=\"positive\"\n                    mode=\"ghost\"\n                    icon={SearchIcon}\n                    onClick={() => void handleReferences()}\n                    text=\"Gather References\"\n                    disabled={isDuplicating || !selectedTotal || isGathering}\n                  />\n                )","() => void handleDuplicate()","<Button\n                  fontSize={2}\n                  padding={4}\n                  tone=\"positive\"\n                  icon={LaunchIcon}\n                  onClick={() => void handleDuplicate()}\n                  text={buttonText}\n                  disabled={isDuplicating || !selectedTotal || isGathering}\n                />","isDuplicating || !selectedTotal || isGathering","<Stack gap={2}>\n                {hasReferences && (\n                  <Button\n                    fontSize={2}\n                    padding={4}\n                    tone=\"positive\"\n                    mode=\"ghost\"\n                    icon={SearchIcon}\n                    onClick={() => void handleReferences()}\n                    text=\"Gather References\"\n                    disabled={isDuplicating || !selectedTotal || isGathering}\n                  />\n                )}\n                <Button\n                  fontSize={2}\n                  padding={4}\n                  tone=\"positive\"\n                  icon={LaunchIcon}\n                  onClick={() => void handleDuplicate()}\n                  text={buttonText}\n                  disabled={isDuplicating || !selectedTotal || isGathering}\n                />\n              </Stack>","<Card borderTop padding={4}>\n            <Stack gap={3}>\n              {displayMessage && (\n                <Card padding={3} radius={2} shadow={1} tone={displayMessage.tone}>\n                  <Text size={1}>{displayMessage.text}</Text>\n                </Card>\n              )}\n              {payload.length > 0 ? (\n                <Stack>\n                  {payload.map(({doc, include, status, hasDraft}, index) => {\n                    const schemaType = schema.get(doc._type)\n\n                    return (\n                      <Fragment key={doc._id}>\n                        <Flex align=\"center\">\n                          <Checkbox checked={include} onChange={() => handleCheckbox(doc._id)} />\n                          <Box flex={1} paddingX={3}>\n                            {schemaType ? (\n                              <Preview value={doc} schemaType={schemaType} />\n                            ) : (\n                              <Card tone=\"caution\">Invalid schema type</Card>\n                            )}\n                          </Box>\n                          <Flex align=\"center\" gap={2}>\n                            {hasDraft ? <StatusBadge status=\"UNPUBLISHED\" isAsset={false} /> : null}\n                            <StatusBadge status={status} isAsset={isAssetId(doc._id)} />\n                          </Flex>\n                        </Flex>\n                        {doc['extension'] === 'svg' && index === firstSvgIndex && (\n                          <Card padding={3} radius={2} shadow={1} tone=\"caution\">\n                            <Text size={1}>\n                              Due to how SVGs are sanitized after first uploaded, duplicated SVG\n                              assets may have new <code>_id</code>'s at the destination. The newly\n                              generated <code>_id</code> will be the same in each duplication, but\n                              it will never be the same <code>_id</code> as the first time this\n                              Asset was uploaded. References to the asset will be updated to use the\n                              new <code>_id</code>.\n                            </Text>\n                          </Card>\n                        )}\n                      </Fragment>\n                    )\n                  })}\n                </Stack>\n              ) : (\n                <Flex padding={4} align=\"center\" justify=\"center\">\n                  <Spinner />\n                </Flex>\n              )}\n              <Stack gap={2}>\n                {hasReferences && (\n                  <Button\n                    fontSize={2}\n                    padding={4}\n                    tone=\"positive\"\n                    mode=\"ghost\"\n                    icon={SearchIcon}\n                    onClick={() => void handleReferences()}\n                    text=\"Gather References\"\n                    disabled={isDuplicating || !selectedTotal || isGathering}\n                  />\n                )}\n                <Button\n                  fontSize={2}\n                  padding={4}\n                  tone=\"positive\"\n                  icon={LaunchIcon}\n                  onClick={() => void handleDuplicate()}\n                  text={buttonText}\n                  disabled={isDuplicating || !selectedTotal || isGathering}\n                />\n              </Stack>\n            </Stack>\n          </Card>","stickyStyles(isDarkMode)","{doc}","{old, new: next}","{doc, include}","{_id}","_id","_c","_temp","initialMessage","err","_Fragment","{apiVersion}","schema.getTypeNames()","{\n    docs: [],\n  }","function handleSubmit(e?: SubmitEvent<HTMLFormElement>) {\n    if (e) e.preventDefault()\n    void runQuery()\n  }","(doc) => !doc._id.startsWith(`drafts.`)","err","[0, 0, 0, 5]","[1, 1, 1, 2]","[1, 1, 1, 4]","[2, 2, 2, 0]","<Box>\n                  <Label>Initial Documents Query</Label>\n                </Box>","<Box>\n                  <Text>\n                    Start with a valid GROQ query to load initial documents. The query will need to\n                    return an Array of Objects. Drafts will be removed from the results.\n                  </Text>\n                </Box>","{fontFamily: 'monospace'}","(event) => setValue(event.currentTarget.value)","<Box flex={1} paddingRight={2}>\n                      <TextInput\n                        style={{fontFamily: 'monospace'}}\n                        fontSize={2}\n                        onChange={(event) => setValue(event.currentTarget.value)}\n                        padding={4}\n                        placeholder={`*[_type == \"article\"]`}\n                        value={value ?? ``}\n                      />\n                    </Box>","value ?? ``","() => handleSubmit()","<Button\n                      padding={2}\n                      paddingX={4}\n                      tone=\"primary\"\n                      onClick={() => handleSubmit()}\n                      text=\"Query\"\n                      disabled={!value}\n                    />","!value","<Flex>\n                    <Box flex={1} paddingRight={2}>\n                      <TextInput\n                        style={{fontFamily: 'monospace'}}\n                        fontSize={2}\n                        onChange={(event) => setValue(event.currentTarget.value)}\n                        padding={4}\n                        placeholder={`*[_type == \"article\"]`}\n                        value={value ?? ``}\n                      />\n                    </Box>\n                    <Button\n                      padding={2}\n                      paddingX={4}\n                      tone=\"primary\"\n                      onClick={() => handleSubmit()}\n                      text=\"Query\"\n                      disabled={!value}\n                    />\n                  </Flex>","<Card padding={4} radius={3} border>\n              <Stack gap={4}>\n                <Box>\n                  <Label>Initial Documents Query</Label>\n                </Box>\n                <Box>\n                  <Text>\n                    Start with a valid GROQ query to load initial documents. The query will need to\n                    return an Array of Objects. Drafts will be removed from the results.\n                  </Text>\n                </Box>\n                <form onSubmit={handleSubmit}>\n                  <Flex>\n                    <Box flex={1} paddingRight={2}>\n                      <TextInput\n                        style={{fontFamily: 'monospace'}}\n                        fontSize={2}\n                        onChange={(event) => setValue(event.currentTarget.value)}\n                        padding={4}\n                        placeholder={`*[_type == \"article\"]`}\n                        value={value ?? ``}\n                      />\n                    </Box>\n                    <Button\n                      padding={2}\n                      paddingX={4}\n                      tone=\"primary\"\n                      onClick={() => handleSubmit()}\n                      text=\"Query\"\n                      disabled={!value}\n                    />\n                  </Flex>\n                </form>\n              </Stack>\n            </Card>","preDefinedQueries && preDefinedQueries?.length > 0 && (\n              <Card marginTop={2} padding={4} radius={3} border>\n                <Box>\n                  <Stack gap={4}>\n                    <Box>\n                      <Label>Predefined Queries</Label>\n                    </Box>\n                    <Stack gap={2}>\n                      {preDefinedQueries.map((query) => (\n                        <Button\n                          key={query.label.replace(/\\s+/g, '-')}\n                          padding={2}\n                          paddingX={4}\n                          tone=\"primary\"\n                          onClick={() => setValue(`*[${query.query}]`)}\n                          text={query.label}\n                        />\n                      ))}\n                    </Stack>\n                  </Stack>\n                </Box>\n              </Card>\n            )","<Box padding={[2, 2, 2, 0]}>\n            <Card padding={4} radius={3} border>\n              <Stack gap={4}>\n                <Box>\n                  <Label>Initial Documents Query</Label>\n                </Box>\n                <Box>\n                  <Text>\n                    Start with a valid GROQ query to load initial documents. The query will need to\n                    return an Array of Objects. Drafts will be removed from the results.\n                  </Text>\n                </Box>\n                <form onSubmit={handleSubmit}>\n                  <Flex>\n                    <Box flex={1} paddingRight={2}>\n                      <TextInput\n                        style={{fontFamily: 'monospace'}}\n                        fontSize={2}\n                        onChange={(event) => setValue(event.currentTarget.value)}\n                        padding={4}\n                        placeholder={`*[_type == \"article\"]`}\n                        value={value ?? ``}\n                      />\n                    </Box>\n                    <Button\n                      padding={2}\n                      paddingX={4}\n                      tone=\"primary\"\n                      onClick={() => handleSubmit()}\n                      text=\"Query\"\n                      disabled={!value}\n                    />\n                  </Flex>\n                </form>\n              </Stack>\n            </Card>\n            {preDefinedQueries && preDefinedQueries?.length > 0 && (\n              <Card marginTop={2} padding={4} radius={3} border>\n                <Box>\n                  <Stack gap={4}>\n                    <Box>\n                      <Label>Predefined Queries</Label>\n                    </Box>\n                    <Stack gap={2}>\n                      {preDefinedQueries.map((query) => (\n                        <Button\n                          key={query.label.replace(/\\s+/g, '-')}\n                          padding={2}\n                          paddingX={4}\n                          tone=\"primary\"\n                          onClick={() => setValue(`*[${query.query}]`)}\n                          text={query.label}\n                        />\n                      ))}\n                    </Stack>\n                  </Stack>\n                </Box>\n              </Card>\n            )}\n          </Box>","fetched && initialData.docs.length < 1 && (\n            <Container width={1}>\n              <Card padding={5}>\n                {value ? `No documents match this query` : `Start with a valid GROQ query`}\n              </Card>\n            </Container>\n          )","docs","initialData.docs?.length > 0 && (\n            <Duplicator docs={initialData.docs} token={token} pluginConfig={pluginConfig} />\n          )","<Card padding={[0, 0, 0, 5]}>\n      <Container>\n        <Grid gridTemplateColumns={[1, 1, 1, 2]} gap={[1, 1, 1, 4]}>\n          <Box padding={[2, 2, 2, 0]}>\n            <Card padding={4} radius={3} border>\n              <Stack gap={4}>\n                <Box>\n                  <Label>Initial Documents Query</Label>\n                </Box>\n                <Box>\n                  <Text>\n                    Start with a valid GROQ query to load initial documents. The query will need to\n                    return an Array of Objects. Drafts will be removed from the results.\n                  </Text>\n                </Box>\n                <form onSubmit={handleSubmit}>\n                  <Flex>\n                    <Box flex={1} paddingRight={2}>\n                      <TextInput\n                        style={{fontFamily: 'monospace'}}\n                        fontSize={2}\n                        onChange={(event) => setValue(event.currentTarget.value)}\n                        padding={4}\n                        placeholder={`*[_type == \"article\"]`}\n                        value={value ?? ``}\n                      />\n                    </Box>\n                    <Button\n                      padding={2}\n                      paddingX={4}\n                      tone=\"primary\"\n                      onClick={() => handleSubmit()}\n                      text=\"Query\"\n                      disabled={!value}\n                    />\n                  </Flex>\n                </form>\n              </Stack>\n            </Card>\n            {preDefinedQueries && preDefinedQueries?.length > 0 && (\n              <Card marginTop={2} padding={4} radius={3} border>\n                <Box>\n                  <Stack gap={4}>\n                    <Box>\n                      <Label>Predefined Queries</Label>\n                    </Box>\n                    <Stack gap={2}>\n                      {preDefinedQueries.map((query) => (\n                        <Button\n                          key={query.label.replace(/\\s+/g, '-')}\n                          padding={2}\n                          paddingX={4}\n                          tone=\"primary\"\n                          onClick={() => setValue(`*[${query.query}]`)}\n                          text={query.label}\n                        />\n                      ))}\n                    </Stack>\n                  </Stack>\n                </Box>\n              </Card>\n            )}\n          </Box>\n          {fetched && initialData.docs.length < 1 && (\n            <Container width={1}>\n              <Card padding={5}>\n                {value ? `No documents match this query` : `Start with a valid GROQ query`}\n              </Card>\n            </Container>\n          )}\n          {initialData.docs?.length > 0 && (\n            <Duplicator docs={initialData.docs} token={token} pluginConfig={pluginConfig} />\n          )}\n        </Grid>\n      </Container>\n    </Card>","doc","_c","_temp","err","[]","{apiVersion}","() => {\n    async function fetchInbound() {\n      const firstDocId = docs[0]?._id\n\n      if (!follow.includes(`inbound`) || !firstDocId) {\n        return\n      }\n\n      const inboundReferences = await client.fetch<SanityDocument[]>(`*[references($id)]`, {\n        id: firstDocId,\n      })\n      setInbound([...docs, ...inboundReferences])\n    }\n\n    fetchInbound().catch(console.error)\n  }","[client, docs, follow]","docs[0]?._id","follow.length > 1 && (follow.includes(`inbound`) || follow.includes(`outbound`)) ? (\n        <Card paddingX={4} paddingBottom={4} marginBottom={4} borderBottom>\n          <Grid gridTemplateColumns={2} gap={4}>\n            {follow.includes(`outbound`) ? (\n              <Button\n                mode=\"ghost\"\n                tone=\"primary\"\n                selected={mode === 'outbound'}\n                onClick={() => setMode('outbound')}\n                text=\"Outbound\"\n              />\n            ) : null}\n            {follow.includes(`inbound`) ? (\n              <Button\n                mode=\"ghost\"\n                tone=\"primary\"\n                selected={mode === 'inbound'}\n                onClick={() => setMode('inbound')}\n                disabled={inbound.length === 0}\n                text={inbound.length > 0 ? `Inbound (${inbound.length})` : 'No inbound references'}\n              />\n            ) : null}\n          </Grid>\n        </Card>\n      ) : null","inbound.length","follow.length","<Duplicator\n        docs={mode === 'outbound' ? docs : inbound}\n        token={token}\n        pluginConfig={pluginConfig}\n        onDuplicated={onDuplicated}\n      />","mode === 'outbound' ? docs : inbound","<Container>\n      {follow.length > 1 && (follow.includes(`inbound`) || follow.includes(`outbound`)) ? (\n        <Card paddingX={4} paddingBottom={4} marginBottom={4} borderBottom>\n          <Grid gridTemplateColumns={2} gap={4}>\n            {follow.includes(`outbound`) ? (\n              <Button\n                mode=\"ghost\"\n                tone=\"primary\"\n                selected={mode === 'outbound'}\n                onClick={() => setMode('outbound')}\n                text=\"Outbound\"\n              />\n            ) : null}\n            {follow.includes(`inbound`) ? (\n              <Button\n                mode=\"ghost\"\n                tone=\"primary\"\n                selected={mode === 'inbound'}\n                onClick={() => setMode('inbound')}\n                disabled={inbound.length === 0}\n                text={inbound.length > 0 ? `Inbound (${inbound.length})` : 'No inbound references'}\n              />\n            ) : null}\n          </Grid>\n        </Card>\n      ) : null}\n      <Duplicator\n        docs={mode === 'outbound' ? docs : inbound}\n        token={token}\n        pluginConfig={pluginConfig}\n        onDuplicated={onDuplicated}\n      />\n    </Container>","_c","{apiVersion}: ResetSecretProps","{apiVersion}","() => {\n    client.delete({query: `*[_id == \"secrets.${SECRET_NAMESPACE}\"]`}).catch(console.error)\n  }","useCallback(() => {\n    client.delete({query: `*[_id == \"secrets.${SECRET_NAMESPACE}\"]`}).catch(console.error)\n  }, [client])","[2, 2, 2, 5]","<Flex align=\"center\" justify=\"flex-end\" paddingX={[2, 2, 2, 5]} paddingY={5}>\n      <Button\n        text=\"Reset Secret\"\n        onClick={handleClick}\n        mode=\"ghost\"\n        tone=\"critical\"\n        fontSize={1}\n        padding={2}\n      />\n    </Flex>","_c","<Flex justify=\"center\" align=\"center\">\n        <Box padding={5}>\n          <Spinner />\n        </Box>\n      </Flex>","<SettingsView\n        title=\"Token Required\"\n        namespace={SECRET_NAMESPACE}\n        keys={secretConfigKeys}\n        onClose={() => null}\n      />","() => null","<DuplicatorQuery token={secrets.bearerToken} pluginConfig={pluginConfig} />","bearerToken","<ResetSecret apiVersion={pluginConfig.apiVersion} />","apiVersion","<>\n        <DuplicatorQuery token={secrets.bearerToken} pluginConfig={pluginConfig} />\n        <ResetSecret apiVersion={pluginConfig.apiVersion} />\n      </>","<Feedback>No docs passed into Duplicator Tool</Feedback>","<Feedback>No plugin config</Feedback>","<DuplicatorWrapper\n      docs={docs}\n      token={secrets.bearerToken}\n      pluginConfig={pluginConfig}\n      onDuplicated={onDuplicated}\n    />","_c","_Fragment","<CrossDatasetDuplicator mode=\"action\" docs={docs} onDuplicated={onDuplicated} />","_c","props.tool.options ?? {}","options","docs = []","<CrossDatasetDuplicator mode=\"tool\" docs={docs} />","_c","\"details\"","\"items\"","\"error\"","\"description\"","\"message\"","\"type\"","\"referenceID\"","\"referencedId\"","\"referenceId\"","\"extension\""],"sources":["../src/helpers/constants.ts","../src/context/ConfigProvider.tsx","../src/helpers/index.ts","../src/helpers/getDocumentsInArray.ts","../src/helpers/migrationFilters.ts","../src/components/Feedback.tsx","../src/components/SelectButtons.tsx","../src/components/StatusBadge.tsx","../src/components/Duplicator.tsx","../src/components/DuplicatorQuery.tsx","../src/components/DuplicatorWrapper.tsx","../src/components/ResetSecret.tsx","../src/components/CrossDatasetDuplicator.tsx","../src/components/CrossDatasetDuplicatorAction.tsx","../src/actions/DuplicateToAction.tsx","../src/components/CrossDatasetDuplicatorTool.tsx","../src/tool/index.ts","../src/plugin.tsx"],"sourcesContent":["import type {PluginConfig} from '../types'\n\nexport const SECRET_NAMESPACE = `CrossDatasetDuplicator`\n\nexport const DEFAULT_CONFIG: Required<PluginConfig> = {\n  apiVersion: '2025-02-19',\n  tool: true,\n  types: [],\n  filter: '',\n  follow: ['outbound'],\n  queries: [],\n  migrationFilters: [],\n}\n","import {createContext, useContext} from 'react'\nimport type {LayoutProps} from 'sanity'\n\nimport {DEFAULT_CONFIG} from '../helpers/constants'\nimport type {PluginConfig} from '../types'\n\nconst CrossDatasetDuplicatorContext = createContext(DEFAULT_CONFIG)\n\ntype ConfigProviderProps = LayoutProps & {pluginConfig: Required<PluginConfig>}\n\n/**\n * Plugin config context hook from the Cross Dataset Duplicator plugin\n * @public\n */\nexport function useCrossDatasetDuplicatorConfig() {\n  const pluginConfig = useContext(CrossDatasetDuplicatorContext)\n\n  return pluginConfig\n}\n\nexport function ConfigProvider(props: ConfigProviderProps) {\n  const {pluginConfig, ...rest} = props\n\n  return (\n    <CrossDatasetDuplicatorContext.Provider value={pluginConfig}>\n      {props.renderDefault(rest)}\n    </CrossDatasetDuplicatorContext.Provider>\n  )\n}\n","import type {CSSProperties} from 'react'\n\nexport function createInitialMessage(docCount = 0, refsCount = 0): string {\n  const message = [\n    docCount === 1 ? `This Document contains` : `These ${docCount} Documents contain`,\n    refsCount === 1 ? `1 Reference.` : `${refsCount} References.`,\n    refsCount === 1 ? `That Document` : `Those Documents`,\n    `may have References too. If referenced Documents do not exist at the target Destination, this transaction will fail.`,\n  ]\n\n  return message.join(` `)\n}\n\nexport const stickyStyles = (isDarkMode = true): CSSProperties => ({\n  position: 'sticky',\n  top: 0,\n  zIndex: 100,\n  backgroundColor: isDarkMode ? `rgba(10,10,10,0.95)` : `rgba(255,255,255,0.95)`,\n})\n","import {extractWithPath} from '@sanity/mutator'\nimport type {SanityClient, SanityDocument} from 'sanity'\n\nimport type {PluginConfig} from '../types'\n\ntype OptionsBag = {\n  fetchIds: string[]\n  client: SanityClient\n  pluginConfig: PluginConfig\n  currentIds?: Set<string> | null\n  projection?: string\n}\n\n// Recursively fetch Documents from an array of _id's and their references\n// Heavy use of Set is to avoid recursively querying for id's already in the payload\nexport async function getDocumentsInArray(options: OptionsBag): Promise<SanityDocument[]> {\n  const {fetchIds, client, pluginConfig, currentIds, projection} = options\n  const collection: SanityDocument[] = []\n\n  // Find initial docs\n  const filter = ['_id in $fetchIds', pluginConfig.filter].filter(Boolean).join(' && ')\n  const query = `*[${filter}]${projection ?? ``}`\n  const data = await client.fetch<SanityDocument[]>(query, {\n    fetchIds: fetchIds ?? [],\n  })\n\n  if (!data?.length) {\n    return []\n  }\n\n  const localCurrentIds = currentIds ?? new Set<string>()\n\n  // Find new ids in the returned data\n  // Unless we started with an empty set, get the _ids from the data\n  const newDataIds = new Set<string>(\n    data\n      .map((dataDoc) => dataDoc._id)\n      .filter((id) => (currentIds?.size ? !localCurrentIds.has(id) : Boolean(id))),\n  )\n\n  if (newDataIds.size) {\n    collection.push(...data)\n    for (const id of newDataIds) {\n      localCurrentIds.add(id)\n    }\n\n    // Check new data for more references\n    await Promise.all(\n      data.map(async (doc) => {\n        const expr = `.._ref`\n        const references = extractWithPath(expr, doc).flatMap((ref) =>\n          typeof ref.value === 'string' ? [ref.value] : [],\n        )\n\n        if (references.length) {\n          // Find references not already in the Collection\n          const newReferenceIds = new Set<string>(\n            references.filter((ref) => !localCurrentIds.has(ref)),\n          )\n\n          if (newReferenceIds.size) {\n            // Recursive query for new documents\n            const referenceDocs = await getDocumentsInArray({\n              fetchIds: Array.from(newReferenceIds),\n              currentIds: localCurrentIds,\n              client,\n              pluginConfig,\n            })\n\n            if (referenceDocs?.length) {\n              collection.push(...referenceDocs)\n            }\n          }\n        }\n      }),\n    )\n  }\n\n  // Create a unique array of documents, keeping the first occurrence of each _id\n  const seenIds = new Set<string>()\n  const uniqueCollection: SanityDocument[] = []\n\n  for (const doc of collection) {\n    if (doc && !seenIds.has(doc._id)) {\n      seenIds.add(doc._id)\n      uniqueCollection.push(doc)\n    }\n  }\n\n  return uniqueCollection\n}\n","import type {MigrationFilter} from '../types'\n\ntype IsAllowedMigrationTargetOptions = {\n  migrationFilters: MigrationFilter[] | undefined\n  sourceProjectId: string | undefined\n  sourceDataset: string | undefined\n  targetProjectId: string\n  targetDataset: string\n}\n\n/**\n * Determine whether a Workspace is an allowed Migration destination for the\n * current source Dataset, based on the optional `migrationFilters` config.\n *\n * If no filter is configured for the source Dataset, every target is allowed\n * (the default behaviour). When a filter is configured, only the listed targets\n * are allowed.\n */\nexport function isAllowedMigrationTarget(options: IsAllowedMigrationTargetOptions): boolean {\n  const {migrationFilters, sourceProjectId, sourceDataset, targetProjectId, targetDataset} = options\n\n  const migrationFilter = migrationFilters?.find((filter) => filter.sourceDataset === sourceDataset)\n\n  // If no migrationFilter is configured for this dataset, allow all migration targets.\n  if (!migrationFilter) {\n    return true\n  }\n\n  return migrationFilter.targets.some((target) => {\n    if (target.dataset !== targetDataset) {\n      return false\n    }\n\n    // If a project ID is configured for the target, check that it matches.\n    if (target.projectId) {\n      return target.projectId === targetProjectId\n    }\n\n    // If a project ID is not configured for the target, only allow targets in\n    // the same project as the source.\n    return targetProjectId === sourceProjectId\n  })\n}\n","import {Card, Text} from '@sanity/ui'\nimport type {BadgeTone} from '@sanity/ui'\nimport type {ReactNode} from 'react'\n\ntype FeedbackProps = {\n  children?: ReactNode\n  tone?: BadgeTone\n}\n\nexport default function Feedback(props: FeedbackProps) {\n  const {children, tone = 'caution'} = props\n\n  return (\n    <Card padding={3} radius={2} shadow={1} tone={tone}>\n      <Text size={1}>{children}</Text>\n    </Card>\n  )\n}\n","import {isAssetId} from '@sanity/asset-utils'\nimport {Button, Card, Flex} from '@sanity/ui'\nimport {type Dispatch, type SetStateAction, useState} from 'react'\n\nimport type {PayloadItem} from './Duplicator'\n\ntype Action = 'ALL' | 'NONE' | 'NEW' | 'EXISTING' | 'OLDER' | 'ASSETS' | 'DOCUMENTS'\n\ntype ButtonItem = {label: string; action: Action} | {divider: string}\n\nconst buttons: ButtonItem[] = [\n  {label: 'All', action: 'ALL'},\n  {label: 'None', action: 'NONE'},\n  {divider: 'divider-1'},\n  {label: 'New', action: 'NEW'},\n  {label: 'Existing', action: 'EXISTING'},\n  {label: 'Older', action: 'OLDER'},\n  {divider: 'divider-2'},\n  {label: 'Documents', action: 'DOCUMENTS'},\n  {label: 'Assets', action: 'ASSETS'},\n]\n\nfunction shouldInclude(item: PayloadItem, action: Action): boolean {\n  switch (action) {\n    case 'ALL':\n      return true\n    case 'NONE':\n      return false\n    case 'NEW':\n      return item.status === 'CREATE'\n    case 'EXISTING':\n      return item.status === 'EXISTS'\n    case 'OLDER':\n      return item.status === 'OVERWRITE'\n    case 'ASSETS':\n      return isAssetId(item.doc._id)\n    case 'DOCUMENTS':\n      return !isAssetId(item.doc._id)\n    default:\n      return item.include\n  }\n}\n\ntype SelectButtonsProps = {\n  payload: PayloadItem[]\n  setPayload: Dispatch<SetStateAction<PayloadItem[]>>\n}\n\nexport default function SelectButtons(props: SelectButtonsProps) {\n  const {payload, setPayload} = props\n  const [disabledActions, setDisabledActions] = useState<Action[]>(() =>\n    payload.length && payload.every((item) => item.include) ? ['ALL'] : [],\n  )\n\n  function handleSelectButton(action: Action) {\n    if (!payload.length) return\n\n    setPayload((current) =>\n      current.map((item) => ({...item, include: shouldInclude(item, action)})),\n    )\n    setDisabledActions([action])\n  }\n\n  return (\n    <Card padding={1} radius={3} shadow={1}>\n      <Flex gap={2} wrap=\"wrap\">\n        {buttons.map((button) =>\n          'action' in button ? (\n            <Button\n              key={button.action}\n              fontSize={1}\n              mode=\"bleed\"\n              padding={2}\n              text={button.label}\n              disabled={disabledActions.includes(button.action)}\n              onClick={() => handleSelectButton(button.action)}\n            />\n          ) : (\n            <Card key={button.divider} borderLeft />\n          ),\n        )}\n      </Flex>\n    </Card>\n  )\n}\n","import {InfoOutlineIcon} from '@sanity/icons/InfoOutline'\nimport {Box, Text, Badge} from '@sanity/ui'\nimport type {BadgeTone} from '@sanity/ui'\nimport {Tooltip} from '@sanity/ui/tooltip'\n\ntype StatusTones = {\n  EXISTS: BadgeTone\n  OVERWRITE: BadgeTone\n  UPDATE: BadgeTone\n  CREATE: BadgeTone\n  UNPUBLISHED: BadgeTone\n}\n\nconst documentTones: StatusTones = {\n  EXISTS: `primary`,\n  OVERWRITE: `critical`,\n  UPDATE: `caution`,\n  CREATE: `positive`,\n  UNPUBLISHED: `caution`,\n}\n\nconst assetTones: StatusTones = {\n  EXISTS: `critical`,\n  OVERWRITE: `critical`,\n  UPDATE: `critical`,\n  CREATE: `positive`,\n  UNPUBLISHED: `default`,\n}\n\nexport type MessageTypes = {\n  EXISTS: string\n  OVERWRITE: string\n  UPDATE: string\n  CREATE: string\n  UNPUBLISHED: string\n}\n\nconst documentMessages: MessageTypes = {\n  // Only happens once document is copied the first time, and _updatedAt is the same\n  EXISTS: `This document already exists at the Destination with the same ID and Updated time.`,\n  // Is true immediately after transaction as _updatedAt is updated by API after mutation\n  // Is also true if the document at the destination has been manually modified\n  // Presently, the plugin doesn't actually compare the two documents\n  OVERWRITE: `A newer version of this document exists at the Destination, and it will be overwritten with this version.`,\n  // Document at destination is older\n  UPDATE: `An older version of this document exists at the Destination, and it will be overwritten with this version.`,\n  // Document at destination doesn't exist\n  CREATE: `This document will be created at the destination.`,\n  UNPUBLISHED: `A Draft version of this Document exists in this Dataset, but only the Published version will be duplicated to the destination.`,\n}\n\nconst assetMessages: MessageTypes = {\n  EXISTS: `This Asset already exists at the Destination`,\n  OVERWRITE: `This Asset already exists at the Destination`,\n  UPDATE: `This Asset already exists at the Destination`,\n  CREATE: `This Asset does not yet exist at the Destination`,\n  UNPUBLISHED: ``,\n}\n\nconst assetStatus: MessageTypes = {\n  EXISTS: `RE-UPLOAD`,\n  OVERWRITE: `RE-UPLOAD`,\n  UPDATE: `RE-UPLOAD`,\n  CREATE: `UPLOAD`,\n  UNPUBLISHED: ``,\n}\n\ntype StatusBadgeProps = {\n  isAsset: boolean\n  status?: keyof MessageTypes\n}\n\nexport default function StatusBadge(props: StatusBadgeProps) {\n  const {status, isAsset} = props\n\n  if (!status) {\n    return null\n  }\n\n  const badgeTone = isAsset ? assetTones[status] : documentTones[status]\n\n  if (!badgeTone) {\n    return (\n      <Badge padding={2} fontSize={1}>\n        Checking...\n      </Badge>\n    )\n  }\n\n  const badgeText = isAsset ? assetMessages[status] : documentMessages[status]\n  const badgeStatus = isAsset ? assetStatus[status] : status\n\n  return (\n    <Tooltip\n      content={\n        <Box padding={3} style={{maxWidth: 200}}>\n          <Text size={1}>{badgeText}</Text>\n        </Box>\n      }\n      fallbackPlacements={['right', 'left']}\n      placement=\"top\"\n      portal\n    >\n      <Badge padding={3} fontSize={1} tone={badgeTone}>\n        {badgeStatus}\n        <Box marginLeft={2} display={'inline-block'} as=\"span\">\n          <InfoOutlineIcon />\n        </Box>\n      </Badge>\n    </Tooltip>\n  )\n}\n","import {isAssetId, isSanityFileAsset} from '@sanity/asset-utils'\nimport type {SanityAssetDocument, SanityClient} from '@sanity/client'\nimport {ArrowRightIcon} from '@sanity/icons/ArrowRight'\nimport {LaunchIcon} from '@sanity/icons/Launch'\nimport {SearchIcon} from '@sanity/icons/Search'\nimport {extractWithPath} from '@sanity/mutator'\nimport {\n  Card,\n  Container,\n  Text,\n  Box,\n  Button,\n  Label,\n  Stack,\n  Select,\n  Flex,\n  Checkbox,\n  type CardTone,\n  useTheme,\n  Spinner,\n} from '@sanity/ui'\nimport {getTheme_v2} from '@sanity/ui/theme'\nimport {dset} from 'dset'\nimport {type ChangeEvent, Fragment, useEffect, useEffectEvent, useMemo, useState} from 'react'\nimport {\n  useClient,\n  Preview,\n  useSchema,\n  useWorkspaces,\n  type WorkspaceSummary,\n  type SanityDocument,\n} from 'sanity'\n\nimport {stickyStyles, createInitialMessage} from '../helpers'\nimport {getDocumentsInArray} from '../helpers/getDocumentsInArray'\nimport {isAllowedMigrationTarget} from '../helpers/migrationFilters'\nimport type {PluginConfig} from '../types'\nimport Feedback from './Feedback'\nimport SelectButtons from './SelectButtons'\nimport StatusBadge, {type MessageTypes} from './StatusBadge'\n\nexport type DuplicatorProps = {\n  docs: SanityDocument[]\n  token: string\n  pluginConfig: Required<PluginConfig>\n  onDuplicated?: () => Promise<void>\n}\n\nexport type PayloadItem = {\n  doc: SanityDocument\n  include: boolean\n  status?: keyof MessageTypes\n  hasDraft?: boolean\n}\n\ntype WorkspaceOption = WorkspaceSummary & {\n  disabled: boolean\n}\n\ntype Message = {\n  text: string\n  tone: CardTone\n}\n\nfunction isAssetDocument(doc: SanityDocument): doc is SanityDocument & SanityAssetDocument {\n  return isAssetId(doc._id)\n}\n\n// Run an async function over every item with a maximum concurrency\nasync function mapWithConcurrency<T>(\n  items: T[],\n  limit: number,\n  fn: (item: T) => Promise<void>,\n): Promise<void> {\n  const queue = [...items]\n\n  async function work(): Promise<void> {\n    const item = queue.shift()\n\n    if (item === undefined) {\n      return undefined\n    }\n\n    await fn(item)\n\n    return work()\n  }\n\n  const workers = Array.from({length: Math.min(limit, queue.length)}, () => work())\n\n  await Promise.all(workers)\n}\n\ntype SetMessage = (msg: Message) => void\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n  return typeof value === 'object' && value !== null\n}\n\nfunction isUnknownArray(value: unknown): value is unknown[] {\n  return Array.isArray(value)\n}\n\n// Pull a human-readable description out of a Sanity mutation error.\n// Prefer the richest text available: item-level descriptions (which carry the\n// \"references non-existent document\" phrasing) over a possibly-generic top-level\n// `details.description` like \"Mutation(s) failed with N error(s)\".\nfunction getErrorDescription(err: unknown): string {\n  if (!isRecord(err)) {\n    return ''\n  }\n\n  const details = err['details']\n  const itemDescriptions: string[] = []\n\n  if (isRecord(details) && isUnknownArray(details['items'])) {\n    for (const item of details['items']) {\n      if (isRecord(item) && isRecord(item['error'])) {\n        const itemDescription = item['error']['description']\n\n        if (typeof itemDescription === 'string' && itemDescription) {\n          itemDescriptions.push(itemDescription)\n        }\n      }\n    }\n  }\n\n  if (itemDescriptions.length) {\n    return itemDescriptions.join('\\n')\n  }\n\n  const message = err['message']\n\n  if (typeof message === 'string' && message) {\n    return message\n  }\n\n  if (isRecord(details)) {\n    const description = details['description']\n\n    if (typeof description === 'string') {\n      return description\n    }\n  }\n\n  return ''\n}\n\nfunction isReferenceMutationError(err: unknown): boolean {\n  if (!isRecord(err)) {\n    return false\n  }\n\n  const details = err['details']\n\n  // Most reliable: structured mutation item type from the Content Lake API\n  if (isRecord(details) && isUnknownArray(details['items'])) {\n    for (const item of details['items']) {\n      if (isRecord(item) && isRecord(item['error'])) {\n        if (item['error']['type'] === 'documentReferenceDoesNotExistError') {\n          return true\n        }\n\n        const itemDescription = item['error']['description']\n\n        if (\n          typeof itemDescription === 'string' &&\n          (itemDescription.toLowerCase().includes('references non-existent document') ||\n            itemDescription.toLowerCase().includes('reference non-existent'))\n        ) {\n          return true\n        }\n      }\n    }\n  }\n\n  const description = getErrorDescription(err).toLowerCase()\n\n  return (\n    description.includes('references non-existent document') ||\n    description.includes('reference non-existent')\n  )\n}\n\n// Collect the _id's of referenced documents that are missing at the destination,\n// reading both the structured error payload and the human-readable description\nfunction getMissingReferenceIds(err: unknown, description: string): string[] {\n  const missingIds: string[] = []\n\n  const details = isRecord(err) ? err['details'] : undefined\n  const rawItems = isRecord(details) ? details['items'] : undefined\n  const items = isUnknownArray(rawItems) ? rawItems : []\n\n  for (const item of items) {\n    if (isRecord(item)) {\n      const error = item['error']\n\n      if (isRecord(error)) {\n        // Sanity returns `referenceID`; keep the other spellings as fallbacks\n        const refId = error['referenceID'] ?? error['referencedId'] ?? error['referenceId']\n\n        if (typeof refId === 'string' && !missingIds.includes(refId)) {\n          missingIds.push(refId)\n        }\n      }\n    }\n  }\n\n  const refRegex = /references non-existent document [`'\"]?([^`'\"\\s)]+)[`'\"]?/gi\n  let match = refRegex.exec(description)\n\n  while (match !== null) {\n    const id = match[1]\n\n    if (id && !missingIds.includes(id)) {\n      missingIds.push(id)\n    }\n\n    match = refRegex.exec(description)\n  }\n\n  return missingIds\n}\n\n// Commit documents individually so a single failing document doesn't block the rest.\n// Runs sequentially (concurrency 1) so referenced documents can land before the\n// documents that point at them.\nasync function commitOneByOne(\n  docs: SanityDocument[],\n  client: SanityClient,\n  setMessage: SetMessage,\n  onSuccess: () => void,\n): Promise<void> {\n  let successCount = 0\n  let failCount = 0\n\n  await mapWithConcurrency(docs, 1, async (doc) => {\n    try {\n      const tx = client.transaction()\n      tx.createOrReplace(doc)\n      await tx.commit()\n      successCount += 1\n    } catch (commitErr) {\n      failCount += 1\n      console.error(`Failed to duplicate document \"${doc._id}\"`, commitErr)\n    }\n  })\n\n  if (failCount === 0) {\n    setMessage({tone: 'positive', text: 'Duplication complete!'})\n    onSuccess()\n\n    return\n  }\n\n  setMessage({\n    tone: 'critical',\n    text: `Duplication finished with ${failCount} error(s). ${successCount} document(s) duplicated successfully.`,\n  })\n\n  if (successCount > 0) {\n    onSuccess()\n  }\n}\n\ntype ReferenceErrorOptions = {\n  err: unknown\n  transactionDocs: SanityDocument[]\n  originClient: SanityClient\n  destinationClient: SanityClient\n  pluginConfig: Required<PluginConfig>\n  token: string\n  setMessage: SetMessage\n  onSuccess: () => void\n  /** Caps recursive recovery so a pathological reference loop can't hang forever */\n  depth?: number\n  /** Document ids the user explicitly deselected — never auto-commit these during recovery */\n  excludedIds?: Set<string>\n  /**\n   * SVG _id remaps already applied by the caller. Recovered documents are fetched\n   * fresh from the origin, so they still point at origin SVG _id's that only exist\n   * at the destination under their uploaded _id.\n   */\n  svgMaps?: {old: string; new: string}[]\n}\n\n// Only attach the studio token when downloading from a Sanity host so a crafted\n// asset `url` cannot exfiltrate credentials to an attacker-controlled endpoint.\nfunction assetDownloadInit(url: string, token: string, typeIsFile: boolean): RequestInit {\n  if (typeIsFile) {\n    return {}\n  }\n\n  try {\n    const {hostname} = new URL(url)\n\n    if (hostname === 'cdn.sanity.io' || hostname.endsWith('.sanity.io')) {\n      return {headers: {Authorization: `Bearer ${token}`}}\n    }\n  } catch {\n    // Invalid URL — fetch without credentials\n  }\n\n  return {}\n}\n\n// Upload a recovered asset to the destination, rewriting url/path for the new dataset\nasync function uploadAssetForRecovery(\n  doc: SanityDocument & SanityAssetDocument,\n  destinationClient: SanityClient,\n  token: string,\n): Promise<{docs: SanityDocument[]; svgMap?: {old: string; new: string}}> {\n  const typeIsFile = isSanityFileAsset(doc)\n  const downloadUrl = typeIsFile ? doc.url : `${doc.url}?dlRaw=true`\n\n  const res = await fetch(downloadUrl, assetDownloadInit(downloadUrl, token, typeIsFile))\n\n  if (!res.ok) {\n    throw new Error(\n      `Failed to download asset \"${doc._id}\" from origin (${res.status} ${res.statusText})`,\n    )\n  }\n\n  const assetData = await res.blob()\n  const assetDoc = await destinationClient.assets.upload(typeIsFile ? `file` : `image`, assetData, {\n    filename: doc.originalFilename,\n  })\n\n  // Merge the original asset document's editorial metadata (e.g. `altText`) with\n  // the uploaded asset's canonical fields, matching the main duplication path.\n  // Keeping this to a single document at the uploaded `_id` avoids leaving an\n  // orphaned asset behind when an SVG's `_id` changes on upload; references are\n  // repointed via `svgMap`.\n  return {\n    docs: [{...doc, ...assetDoc}],\n    svgMap: doc.extension === 'svg' ? {old: doc._id, new: assetDoc._id} : undefined,\n  }\n}\n\n// Rewrite _ref values that point at remapped SVG asset ids.\n// Clones each doc so caller-held / payload objects are not mutated.\nfunction remapSvgRefs(\n  docs: SanityDocument[],\n  svgMaps: {old: string; new: string}[],\n): SanityDocument[] {\n  if (!svgMaps.length) {\n    return docs\n  }\n\n  return docs.map((original) => {\n    const references = extractWithPath(`.._ref`, original)\n\n    if (!references.length) {\n      return original\n    }\n\n    const doc = structuredClone(original)\n\n    references.forEach((ref) => {\n      const newRefValue = svgMaps.find((asset) => asset.old === ref.value)?.new\n\n      if (newRefValue) {\n        dset(doc, ref.path.join('.'), newRefValue)\n      }\n    })\n\n    return doc\n  })\n}\n\n// Order docs so referenced documents come before the documents that point at\n// them. Used by the sequential one-by-one fallback where commit order matters.\nfunction orderDocsDependenciesFirst(docs: SanityDocument[]): SanityDocument[] {\n  const byId = new Map(docs.map((doc) => [doc._id, doc]))\n  const visiting = new Set<string>()\n  const visited = new Set<string>()\n  const ordered: SanityDocument[] = []\n\n  function visit(id: string): void {\n    if (visited.has(id) || visiting.has(id)) {\n      return\n    }\n\n    const doc = byId.get(id)\n\n    if (!doc) {\n      return\n    }\n\n    visiting.add(id)\n\n    for (const ref of extractWithPath(`.._ref`, doc)) {\n      if (typeof ref.value === 'string') {\n        visit(ref.value)\n      }\n    }\n\n    visiting.delete(id)\n    visited.add(id)\n    ordered.push(doc)\n  }\n\n  for (const doc of docs) {\n    visit(doc._id)\n  }\n\n  return ordered\n}\n\n// When a transaction fails because of missing references, fetch the referenced\n// documents (and their transitive refs) from the origin — respecting\n// pluginConfig.filter — upload any assets, then retry. Falls back to one-by-one\n// commits if the retry still fails.\nasync function handleReferenceError(options: ReferenceErrorOptions): Promise<void> {\n  const {\n    err,\n    transactionDocs,\n    originClient,\n    destinationClient,\n    pluginConfig,\n    token,\n    setMessage,\n    onSuccess,\n    depth = 0,\n    excludedIds = new Set(),\n    svgMaps: inheritedSvgMaps = [],\n  } = options\n  const description = getErrorDescription(err)\n  const missingIds = getMissingReferenceIds(err, description)\n\n  // If the only missing refs are ones the user deselected, surface that instead of\n  // silently re-committing them\n  const autoFetchIds = missingIds.filter((id) => !excludedIds.has(id))\n  const blockedIds = missingIds.filter((id) => excludedIds.has(id))\n\n  if (blockedIds.length && !autoFetchIds.length) {\n    setMessage({\n      tone: 'critical',\n      text: `Duplication failed because deselected document(s) are still referenced: ${blockedIds.join(', ')}. Re-select them or remove the references.`,\n    })\n\n    return\n  }\n\n  if (!missingIds.length || depth >= 5) {\n    // Couldn't parse the missing _id's (or we hit the recursion cap) — retry each document on its own\n    setMessage({tone: 'default', text: 'Retrying documents one by one...'})\n    await commitOneByOne(\n      orderDocsDependenciesFirst(transactionDocs),\n      destinationClient,\n      setMessage,\n      onSuccess,\n    )\n\n    return\n  }\n\n  setMessage({\n    tone: 'default',\n    text: `Fetching ${autoFetchIds.length} missing referenced document(s) and retrying...`,\n  })\n\n  let missingDocs: SanityDocument[] = []\n\n  try {\n    // Recursively gather referenced docs (and apply pluginConfig.filter), same\n    // as the \"Gather References\" path — so nested refs aren't left behind\n    missingDocs = await getDocumentsInArray({\n      fetchIds: autoFetchIds,\n      client: originClient,\n      pluginConfig,\n    })\n  } catch (fetchErr) {\n    setMessage({\n      tone: 'critical',\n      text:\n        (fetchErr instanceof Error ? fetchErr.message : '') || description || 'Duplication Failed',\n    })\n\n    return\n  }\n\n  if (!missingDocs.length) {\n    setMessage({tone: 'default', text: 'Retrying documents one by one...'})\n    await commitOneByOne(\n      orderDocsDependenciesFirst(transactionDocs),\n      destinationClient,\n      setMessage,\n      onSuccess,\n    )\n\n    return\n  }\n\n  // Don't re-commit documents already in the failed transaction, or ones the\n  // user explicitly deselected (including transitive refs of those)\n  const existingIds = new Set(transactionDocs.map((doc) => doc._id))\n  // Reverse so transitive refs (appended last by getDocumentsInArray) are processed first\n  const newMissingDocs = [...missingDocs]\n    .reverse()\n    .filter((doc) => !existingIds.has(doc._id) && !excludedIds.has(doc._id))\n\n  // Nothing new to add — retrying the same transaction would just loop until the depth cap\n  if (!newMissingDocs.length) {\n    setMessage({tone: 'default', text: 'Retrying documents one by one...'})\n    await commitOneByOne(\n      orderDocsDependenciesFirst(transactionDocs),\n      destinationClient,\n      setMessage,\n      onSuccess,\n    )\n\n    return\n  }\n\n  setMessage({tone: 'default', text: `Duplicating ${newMissingDocs.length} missing document(s)...`})\n\n  // Seed with the caller's remaps so recovered documents referencing an SVG that\n  // was uploaded earlier are repointed at its destination _id, even when that\n  // asset isn't re-fetched here (e.g. `pluginConfig.filter` excludes assets)\n  const svgMaps: {old: string; new: string}[] = [...inheritedSvgMaps]\n\n  // Process with the same concurrency limit as the main duplication path, while\n  // writing into index slots so dependency-first order is preserved\n  const recoveredChunks: SanityDocument[][] = Array.from({length: newMissingDocs.length}, () => [])\n\n  try {\n    await mapWithConcurrency(\n      newMissingDocs.map((doc, index) => ({doc, index})),\n      3,\n      async ({doc, index}) => {\n        if (!isAssetDocument(doc)) {\n          recoveredChunks[index] = [doc]\n\n          return\n        }\n\n        const {docs, svgMap} = await uploadAssetForRecovery(doc, destinationClient, token)\n        recoveredChunks[index] = docs\n\n        if (svgMap) {\n          svgMaps.push(svgMap)\n        }\n      },\n    )\n  } catch (uploadErr) {\n    setMessage({\n      tone: 'critical',\n      text:\n        (uploadErr instanceof Error ? uploadErr.message : '') ||\n        description ||\n        'Duplication Failed',\n    })\n\n    return\n  }\n\n  const recoveredDocs = recoveredChunks.flat()\n\n  // Remap SVG _ref's in both recovered and original transaction docs\n  const remappedRecoveredDocs = remapSvgRefs(recoveredDocs, svgMaps)\n  const remappedTransactionDocs = remapSvgRefs(transactionDocs, svgMaps)\n\n  // Put recovered (referenced) docs first so sequential commits land\n  // dependencies before the documents that point at them\n  const allDocs = orderDocsDependenciesFirst([...remappedRecoveredDocs, ...remappedTransactionDocs])\n\n  const retryTransaction = destinationClient.transaction()\n  allDocs.forEach((doc) => retryTransaction.createOrReplace(doc))\n\n  try {\n    await retryTransaction.commit()\n    setMessage({tone: 'positive', text: 'Duplication complete!'})\n    onSuccess()\n  } catch (retryErr) {\n    if (isReferenceMutationError(retryErr)) {\n      // Another layer of missing refs — recurse with the expanded set\n      await handleReferenceError({\n        ...options,\n        err: retryErr,\n        transactionDocs: allDocs,\n        depth: depth + 1,\n        svgMaps,\n      })\n\n      return\n    }\n\n    setMessage({tone: 'default', text: 'Retrying documents one by one...'})\n    await commitOneByOne(allDocs, destinationClient, setMessage, onSuccess)\n  }\n}\n\nexport default function Duplicator(props: DuplicatorProps) {\n  const {docs, token, pluginConfig, onDuplicated} = props\n  const theme = useTheme()\n  const isDarkMode = getTheme_v2({sanity: theme.sanity}).color._dark\n\n  // Prepare origin (this Studio) client\n  const originClient = useClient({apiVersion: pluginConfig.apiVersion})\n\n  const schema = useSchema()\n\n  // Create list of dataset options\n  // and set initial value of dropdown\n  const workspaces = useWorkspaces()\n  const {projectId: sourceProjectId, dataset: sourceDataset} = originClient.config()\n  const workspacesOptions: WorkspaceOption[] = workspaces.map((workspace) => {\n    const isSourceWorkspace =\n      workspace.projectId === sourceProjectId && workspace.dataset === sourceDataset\n    const isAllowedMigration = isAllowedMigrationTarget({\n      migrationFilters: pluginConfig.migrationFilters,\n      sourceProjectId,\n      sourceDataset,\n      targetProjectId: workspace.projectId,\n      targetDataset: workspace.dataset,\n    })\n\n    return {\n      ...workspace,\n      disabled: isSourceWorkspace || !isAllowedMigration,\n    }\n  })\n\n  const currentWorkspace = workspacesOptions.find(\n    (workspace) => workspace.projectId === sourceProjectId && workspace.dataset === sourceDataset,\n  )\n\n  const [destination, setDestination] = useState<WorkspaceOption | null>(\n    workspaces.length ? (workspacesOptions.find((space) => !space.disabled) ?? null) : null,\n  )\n  const [message, setMessage] = useState<Message | null>(null)\n  const [payload, setPayload] = useState<PayloadItem[]>([])\n\n  const [isDuplicating, setIsDuplicating] = useState(false)\n  const [isGathering, setIsGathering] = useState(false)\n  const [progress, setProgress] = useState<[number, number]>([0, 0])\n\n  // References found in the initial docs\n  const initialRefsCount = useMemo(\n    () => docs.reduce((acc, doc) => acc + extractWithPath(`.._ref`, doc).length, 0),\n    [docs],\n  )\n  const hasReferences = initialRefsCount > 0\n  const initialMessage: Message | null = hasReferences\n    ? {tone: `caution`, text: createInitialMessage(docs.length, initialRefsCount)}\n    : null\n  const displayMessage = message ?? initialMessage\n\n  // Check if payload documents exist at destination\n  async function updatePayloadStatuses(payloadActual: PayloadItem[], dest: WorkspaceOption | null) {\n    if (!payloadActual.length || !dest?.name) {\n      return\n    }\n\n    const payloadIds = payloadActual.map(({doc}) => doc._id)\n    const destinationClient = originClient.withConfig({\n      dataset: dest.dataset,\n      projectId: dest.projectId,\n    })\n    const destinationData = await destinationClient.fetch<SanityDocument[]>(\n      `*[_id in $payloadIds]{ _id, _updatedAt }`,\n      {payloadIds},\n    )\n    // Index the destination docs by `_id` so status updates stay O(n) instead\n    // of O(n²) when looking them up for each payload item below.\n    const destinationById = new Map(destinationData.map((doc) => [doc._id, doc]))\n\n    setPayload(\n      payloadActual.map((item) => {\n        const existingDoc = destinationById.get(item.doc._id)\n        let status: keyof MessageTypes = 'CREATE'\n\n        if (existingDoc?._updatedAt && item.doc._updatedAt) {\n          if (existingDoc._updatedAt === item.doc._updatedAt) {\n            // Exact same document exists at destination\n            // We don't compare by _rev because that is updated in a transaction\n            status = `EXISTS`\n          } else {\n            status =\n              new Date(existingDoc._updatedAt) > new Date(item.doc._updatedAt)\n                ? // Document at destination is newer\n                  `OVERWRITE`\n                : // Document at destination is older\n                  `UPDATE`\n          }\n        }\n\n        return {...item, status}\n      }),\n    )\n  }\n\n  // Build the initial payload and check statuses at the current destination\n  const initializePayload = useEffectEvent((nextDocs: SanityDocument[]) => {\n    const initialPayload: PayloadItem[] = nextDocs.map((doc) => ({include: true, doc}))\n    updatePayloadStatuses(initialPayload, destination).catch(console.error)\n  })\n\n  // Sync the payload with the docs prop and the destination dataset.\n  // setPayload only runs after fetching document statuses from the\n  // destination resolves, not synchronously within the effect.\n  // See: https://github.com/facebook/react/issues/34743\n  useEffect(() => {\n    // oxlint-disable-next-line react/set-state-in-effect\n    initializePayload(docs)\n  }, [docs])\n\n  function handleCheckbox(_id: string) {\n    setPayload((current) =>\n      current.map((item) => (item.doc._id === _id ? {...item, include: !item.include} : item)),\n    )\n  }\n\n  // Find and recursively follow references beginning with this document\n  async function handleReferences() {\n    setIsGathering(true)\n\n    try {\n      const docIds = docs.map((doc) => doc._id)\n\n      const payloadDocs = await getDocumentsInArray({\n        fetchIds: docIds,\n        client: originClient,\n        pluginConfig,\n      })\n      const draftDocs = await getDocumentsInArray({\n        fetchIds: docIds.map((id) => `drafts.${id}`),\n        client: originClient,\n        projection: `{_id}`,\n        pluginConfig,\n      })\n      const draftDocsIds = new Set(draftDocs.map(({_id}) => _id))\n\n      // Shape it up\n      const payloadShaped: PayloadItem[] = payloadDocs.map((doc) => ({\n        doc,\n        // Include this in the transaction?\n        include: true,\n        // Does it exist at the destination?\n        status: undefined,\n        // Does it have any drafts?\n        hasDraft: draftDocsIds.has(`drafts.${doc._id}`),\n      }))\n\n      setPayload(payloadShaped)\n      updatePayloadStatuses(payloadShaped, destination).catch(console.error)\n    } catch (err) {\n      console.error(err)\n    }\n\n    setIsGathering(false)\n  }\n\n  // Duplicate payload to destination dataset\n  async function handleDuplicate() {\n    if (!destination) {\n      return\n    }\n\n    setIsDuplicating(true)\n\n    const assetsCount = payload.filter(({doc, include}) => include && isAssetId(doc._id)).length\n    let currentProgress = 0\n    setProgress([currentProgress, assetsCount])\n\n    setMessage({text: 'Duplicating...', tone: `transparent`})\n\n    const destinationClient = originClient.withConfig({\n      apiVersion: pluginConfig.apiVersion,\n      dataset: destination.dataset,\n      projectId: destination.projectId,\n    })\n\n    const transactionDocs: SanityDocument[] = []\n    const svgMaps: {old: string; new: string}[] = []\n\n    // Upload assets and then add to transaction\n    async function processDoc(doc: SanityDocument): Promise<void> {\n      if (!isAssetDocument(doc)) {\n        transactionDocs.push(doc)\n\n        return\n      }\n\n      // Download and upload asset\n      // Get the *original* image with this dlRaw param to create the same deterministic _id\n      const typeIsFile = isSanityFileAsset(doc)\n      const downloadUrl = typeIsFile ? doc.url : `${doc.url}?dlRaw=true`\n\n      const res = await fetch(downloadUrl, assetDownloadInit(downloadUrl, token, typeIsFile))\n\n      // Fail fast instead of uploading an error response (e.g. 401/403/404)\n      // body as the asset's binary data.\n      if (!res.ok) {\n        throw new Error(\n          `Failed to download asset \"${doc.originalFilename ?? doc._id}\" (${res.status} ${res.statusText})`,\n        )\n      }\n\n      const assetData = await res.blob()\n\n      const options = {filename: doc.originalFilename}\n      const assetDoc = await destinationClient.assets.upload(\n        typeIsFile ? `file` : `image`,\n        assetData,\n        options,\n      )\n\n      // SVG _id's need remapping before transaction\n      if (doc.extension === 'svg') {\n        svgMaps.push({old: doc._id, new: assetDoc._id})\n      }\n\n      // Merge the original asset document's editorial metadata (e.g. `altText`,\n      // `title`) — which the upload response omits — with the canonical fields of\n      // the freshly uploaded asset (`_id`, `url`, `path`, `assetId`, `sha1hash`,\n      // ...). The uploaded values win, so `url`/`path` no longer reference the\n      // origin dataset. For SVGs the uploaded `_id` differs from the source\n      // (the file is sanitized on upload), so pushing a single merged document at\n      // the new `_id` — and remapping references to it below — avoids leaving an\n      // orphaned asset document behind at the original `_id`.\n      transactionDocs.push({...doc, ...assetDoc})\n\n      currentProgress += 1\n      setMessage({\n        text: `Duplicating ${currentProgress}/${assetsCount} Assets`,\n        tone: 'default',\n      })\n      setProgress([currentProgress, assetsCount])\n    }\n\n    try {\n      const payloadIncludedDocs = payload.filter((item) => item.include).map((item) => item.doc)\n\n      // Promises are limited to three at once\n      await mapWithConcurrency(payloadIncludedDocs, 3, processDoc)\n    } catch (err) {\n      console.error(err)\n      setIsDuplicating(false)\n      setProgress([0, 0])\n      setMessage({\n        tone: 'critical',\n        text: err instanceof Error ? err.message : `Duplication Failed`,\n      })\n\n      return\n    }\n\n    // Remap SVG references to new _id's. SVG assets are sanitized on upload, so\n    // their `_id` changes; references still pointing at the original `_id` must\n    // be updated to the uploaded one.\n    const svgIdRemap = new Map(svgMaps.map(({old, new: next}) => [old, next]))\n    const transactionDocsMapped =\n      svgIdRemap.size === 0\n        ? transactionDocs\n        : transactionDocs.map((doc) => {\n            const references = extractWithPath(`.._ref`, doc)\n\n            if (!references.length) {\n              return doc\n            }\n\n            // Clone lazily before the first mutation: some of these docs are the\n            // same objects held in React state (`payload`), and `dset` mutates in\n            // place — which would corrupt state and trip up the React Compiler.\n            let mappedDoc = doc\n\n            references.forEach((ref) => {\n              const newRefValue =\n                typeof ref.value === 'string' ? svgIdRemap.get(ref.value) : undefined\n\n              if (newRefValue) {\n                if (mappedDoc === doc) {\n                  mappedDoc = structuredClone(doc)\n                }\n\n                dset(mappedDoc, ref.path.join('.'), newRefValue)\n              }\n            })\n\n            return mappedDoc\n          })\n\n    // Create transaction\n    const transaction = destinationClient.transaction()\n\n    transactionDocsMapped.forEach((doc) => {\n      transaction.createOrReplace(doc)\n    })\n\n    const onCommitSuccess = () => {\n      updatePayloadStatuses(payload, destination).catch(console.error)\n    }\n\n    try {\n      await transaction.commit()\n      setMessage({tone: 'positive', text: 'Duplication complete!'})\n\n      onCommitSuccess()\n    } catch (err) {\n      if (isReferenceMutationError(err)) {\n        await handleReferenceError({\n          err,\n          transactionDocs: transactionDocsMapped,\n          originClient,\n          destinationClient,\n          pluginConfig,\n          token,\n          setMessage,\n          onSuccess: onCommitSuccess,\n          excludedIds: new Set(payload.filter((item) => !item.include).map((item) => item.doc._id)),\n          svgMaps,\n        })\n      } else {\n        const description = getErrorDescription(err)\n        setMessage({\n          tone: 'critical',\n          text: description || `Duplication Failed`,\n        })\n      }\n    }\n\n    setIsDuplicating(false)\n    setProgress([0, 0])\n    if (onDuplicated) {\n      try {\n        await onDuplicated()\n      } catch (error) {\n        const text = error instanceof Error ? error.message : String(error)\n        setMessage({tone: 'critical', text: `Error in onDuplicated hook: ${text}`})\n      }\n    }\n  }\n\n  function handleChange(e: ChangeEvent<HTMLSelectElement>) {\n    if (!workspacesOptions.length) {\n      return\n    }\n\n    const targeted = workspacesOptions.find((space) => space.name === e.currentTarget.value)\n\n    if (targeted) {\n      setDestination(targeted)\n      updatePayloadStatuses(payload, targeted).catch(console.error)\n    }\n  }\n\n  const payloadCount = payload.length\n  const firstSvgIndex = payload.findIndex(({doc}) => doc['extension'] === 'svg')\n  const selectedDocumentsCount = payload.filter(\n    (item) => item.include && !isAssetId(item.doc._id),\n  ).length\n  const selectedAssetsCount = payload.filter(\n    (item) => item.include && isAssetId(item.doc._id),\n  ).length\n  const selectedTotal = selectedDocumentsCount + selectedAssetsCount\n  const destinationTitle = destination?.title ?? destination?.name\n  const hasMultipleProjectIds =\n    new Set(workspacesOptions.map((space) => space?.projectId).filter(Boolean)).size > 1\n\n  const headingText = [selectedTotal, `/`, payloadCount, `Documents and Assets selected`].join(` `)\n\n  const buttonTextParts = [`Duplicate`]\n\n  if (selectedDocumentsCount > 0) {\n    buttonTextParts.push(\n      String(selectedDocumentsCount),\n      selectedDocumentsCount === 1 ? `Document` : `Documents`,\n    )\n  }\n\n  if (selectedAssetsCount > 0) {\n    // Only join with \"and\" when documents are also part of the selection.\n    if (selectedDocumentsCount > 0) {\n      buttonTextParts.push(`and`)\n    }\n\n    buttonTextParts.push(\n      String(selectedAssetsCount),\n      selectedAssetsCount === 1 ? `Asset` : `Assets`,\n    )\n  }\n\n  if (originClient.config().projectId !== destination?.projectId) {\n    buttonTextParts.push(`between Projects`)\n  }\n\n  buttonTextParts.push(`to`, String(destinationTitle))\n\n  const buttonText = buttonTextParts.join(` `)\n\n  if (workspacesOptions.length < 2) {\n    return (\n      <Feedback tone=\"critical\">\n        <code>sanity.config.ts</code> must contain at least two Workspaces to use this plugin.\n      </Feedback>\n    )\n  }\n\n  if (!destination) {\n    return (\n      <Feedback tone=\"critical\">\n        No allowed Migration destinations are available for this Dataset. Check the{' '}\n        <code>migrationFilters</code> plugin config, or add another Workspace as a valid target.\n      </Feedback>\n    )\n  }\n\n  return (\n    <Container width={1}>\n      <Card border>\n        <Stack>\n          <Card padding={4} style={stickyStyles(isDarkMode)}>\n            <Stack gap={4}>\n              <Flex gap={3}>\n                <Stack style={{flex: 1}} gap={3}>\n                  <Label>Duplicate from</Label>\n                  <Select readOnly value={currentWorkspace?.name}>\n                    {currentWorkspace ? (\n                      <option value={currentWorkspace.name}>\n                        {currentWorkspace.title ?? currentWorkspace.name}\n                        {hasMultipleProjectIds ? ` (${currentWorkspace.projectId})` : ``}\n                      </option>\n                    ) : null}\n                  </Select>\n                </Stack>\n                <Box padding={4} paddingTop={5} paddingBottom={0}>\n                  <Text size={3}>\n                    <ArrowRightIcon />\n                  </Text>\n                </Box>\n                <Stack style={{flex: 1}} gap={3}>\n                  <Label>To Destination</Label>\n                  <Select onChange={handleChange}>\n                    {workspacesOptions.map((space) => (\n                      <option key={space.name} value={space.name} disabled={space.disabled}>\n                        {space.title ?? space.name}\n                        {hasMultipleProjectIds ? ` (${space.projectId})` : ``}\n                        {currentWorkspace?.name === space.name &&\n                        currentWorkspace.projectId === space.projectId\n                          ? ` (Current)`\n                          : ``}\n                      </option>\n                    ))}\n                  </Select>\n                </Stack>\n              </Flex>\n\n              {isDuplicating && (\n                <Card border radius={2}>\n                  <Card\n                    style={{\n                      width: '100%',\n                      // Guard against a 0-asset payload (progress[1] === 0),\n                      // which would make the ratio NaN and produce an invalid transform.\n                      transform: `scaleX(${progress[1] > 0 ? progress[0] / progress[1] : 0})`,\n                      transformOrigin: 'left',\n                      transition: 'transform .2s ease',\n                      boxSizing: 'border-box',\n                    }}\n                    padding={1}\n                    tone=\"positive\"\n                  />\n                </Card>\n              )}\n              {payload.length > 0 && (\n                <>\n                  <Label>{headingText}</Label>\n                  <SelectButtons payload={payload} setPayload={setPayload} />\n                </>\n              )}\n            </Stack>\n          </Card>\n          <Card borderTop padding={4}>\n            <Stack gap={3}>\n              {displayMessage && (\n                <Card padding={3} radius={2} shadow={1} tone={displayMessage.tone}>\n                  <Text size={1}>{displayMessage.text}</Text>\n                </Card>\n              )}\n              {payload.length > 0 ? (\n                <Stack>\n                  {payload.map(({doc, include, status, hasDraft}, index) => {\n                    const schemaType = schema.get(doc._type)\n\n                    return (\n                      <Fragment key={doc._id}>\n                        <Flex align=\"center\">\n                          <Checkbox checked={include} onChange={() => handleCheckbox(doc._id)} />\n                          <Box flex={1} paddingX={3}>\n                            {schemaType ? (\n                              <Preview value={doc} schemaType={schemaType} />\n                            ) : (\n                              <Card tone=\"caution\">Invalid schema type</Card>\n                            )}\n                          </Box>\n                          <Flex align=\"center\" gap={2}>\n                            {hasDraft ? <StatusBadge status=\"UNPUBLISHED\" isAsset={false} /> : null}\n                            <StatusBadge status={status} isAsset={isAssetId(doc._id)} />\n                          </Flex>\n                        </Flex>\n                        {doc['extension'] === 'svg' && index === firstSvgIndex && (\n                          <Card padding={3} radius={2} shadow={1} tone=\"caution\">\n                            <Text size={1}>\n                              Due to how SVGs are sanitized after first uploaded, duplicated SVG\n                              assets may have new <code>_id</code>'s at the destination. The newly\n                              generated <code>_id</code> will be the same in each duplication, but\n                              it will never be the same <code>_id</code> as the first time this\n                              Asset was uploaded. References to the asset will be updated to use the\n                              new <code>_id</code>.\n                            </Text>\n                          </Card>\n                        )}\n                      </Fragment>\n                    )\n                  })}\n                </Stack>\n              ) : (\n                <Flex padding={4} align=\"center\" justify=\"center\">\n                  <Spinner />\n                </Flex>\n              )}\n              <Stack gap={2}>\n                {hasReferences && (\n                  <Button\n                    fontSize={2}\n                    padding={4}\n                    tone=\"positive\"\n                    mode=\"ghost\"\n                    icon={SearchIcon}\n                    onClick={() => void handleReferences()}\n                    text=\"Gather References\"\n                    disabled={isDuplicating || !selectedTotal || isGathering}\n                  />\n                )}\n                <Button\n                  fontSize={2}\n                  padding={4}\n                  tone=\"positive\"\n                  icon={LaunchIcon}\n                  onClick={() => void handleDuplicate()}\n                  text={buttonText}\n                  disabled={isDuplicating || !selectedTotal || isGathering}\n                />\n              </Stack>\n            </Stack>\n          </Card>\n        </Stack>\n      </Card>\n    </Container>\n  )\n}\n","import {Button, Stack, Box, Label, Text, Card, Flex, Grid, Container, TextInput} from '@sanity/ui'\nimport {type SubmitEvent, useState} from 'react'\nimport {useSchema, useClient, type SanityDocument} from 'sanity'\n\nimport type {PluginConfig} from '../types'\nimport Duplicator from './Duplicator'\n\ntype DuplicatorQueryProps = {\n  token: string\n  pluginConfig: Required<PluginConfig>\n}\n\ntype InitialData = {\n  docs: SanityDocument[]\n}\n\nexport default function DuplicatorQuery(props: DuplicatorQueryProps) {\n  const {token, pluginConfig} = props\n\n  const {queries: preDefinedQueries, apiVersion} = pluginConfig\n  const originClient = useClient({apiVersion})\n\n  const schema = useSchema()\n  const schemaTypes = schema.getTypeNames()\n\n  const [value, setValue] = useState(``)\n  const [fetched, setFetched] = useState(false)\n  const [initialData, setInitialData] = useState<InitialData>({\n    docs: [],\n  })\n\n  async function runQuery() {\n    try {\n      const res = await originClient.fetch<SanityDocument[]>(value)\n\n      // Ensure queried docs are registered to the schema\n      const registeredAndPublishedDocs = res.length\n        ? res\n            .filter((doc) => schemaTypes.includes(doc._type))\n            .filter((doc) => !doc._id.startsWith(`drafts.`))\n        : []\n\n      setInitialData({\n        docs: registeredAndPublishedDocs,\n      })\n      setFetched(true)\n    } catch (err) {\n      console.error(err)\n    }\n  }\n\n  function handleSubmit(e?: SubmitEvent<HTMLFormElement>) {\n    if (e) e.preventDefault()\n    void runQuery()\n  }\n\n  return (\n    <Card padding={[0, 0, 0, 5]}>\n      <Container>\n        <Grid gridTemplateColumns={[1, 1, 1, 2]} gap={[1, 1, 1, 4]}>\n          <Box padding={[2, 2, 2, 0]}>\n            <Card padding={4} radius={3} border>\n              <Stack gap={4}>\n                <Box>\n                  <Label>Initial Documents Query</Label>\n                </Box>\n                <Box>\n                  <Text>\n                    Start with a valid GROQ query to load initial documents. The query will need to\n                    return an Array of Objects. Drafts will be removed from the results.\n                  </Text>\n                </Box>\n                <form onSubmit={handleSubmit}>\n                  <Flex>\n                    <Box flex={1} paddingRight={2}>\n                      <TextInput\n                        style={{fontFamily: 'monospace'}}\n                        fontSize={2}\n                        onChange={(event) => setValue(event.currentTarget.value)}\n                        padding={4}\n                        placeholder={`*[_type == \"article\"]`}\n                        value={value ?? ``}\n                      />\n                    </Box>\n                    <Button\n                      padding={2}\n                      paddingX={4}\n                      tone=\"primary\"\n                      onClick={() => handleSubmit()}\n                      text=\"Query\"\n                      disabled={!value}\n                    />\n                  </Flex>\n                </form>\n              </Stack>\n            </Card>\n            {preDefinedQueries && preDefinedQueries?.length > 0 && (\n              <Card marginTop={2} padding={4} radius={3} border>\n                <Box>\n                  <Stack gap={4}>\n                    <Box>\n                      <Label>Predefined Queries</Label>\n                    </Box>\n                    <Stack gap={2}>\n                      {preDefinedQueries.map((query) => (\n                        <Button\n                          key={query.label.replace(/\\s+/g, '-')}\n                          padding={2}\n                          paddingX={4}\n                          tone=\"primary\"\n                          onClick={() => setValue(`*[${query.query}]`)}\n                          text={query.label}\n                        />\n                      ))}\n                    </Stack>\n                  </Stack>\n                </Box>\n              </Card>\n            )}\n          </Box>\n          {fetched && initialData.docs.length < 1 && (\n            <Container width={1}>\n              <Card padding={5}>\n                {value ? `No documents match this query` : `Start with a valid GROQ query`}\n              </Card>\n            </Container>\n          )}\n          {initialData.docs?.length > 0 && (\n            <Duplicator docs={initialData.docs} token={token} pluginConfig={pluginConfig} />\n          )}\n        </Grid>\n      </Container>\n    </Card>\n  )\n}\n","import {Grid, Card, Container, Button} from '@sanity/ui'\nimport {useState, useEffect} from 'react'\nimport {type SanityDocument, useClient} from 'sanity'\n\nimport type {DuplicatorProps} from './Duplicator'\nimport Duplicator from './Duplicator'\n\nexport default function DuplicatorWrapper(props: DuplicatorProps) {\n  const {docs, token, pluginConfig, onDuplicated} = props\n  const [inbound, setInbound] = useState<SanityDocument[]>([])\n  const {follow, apiVersion} = pluginConfig\n\n  // Make the first mode the default if there's only one\n  const [mode, setMode] = useState<'inbound' | 'outbound'>(\n    follow.length === 1 ? (follow[0] ?? 'outbound') : 'outbound',\n  )\n  const client = useClient({apiVersion})\n\n  // \"Inbound\" will start with all documents that reference the first one\n  // And then you can gather \"Outbound\" references thereafter\n  useEffect(() => {\n    async function fetchInbound() {\n      const firstDocId = docs[0]?._id\n\n      if (!follow.includes(`inbound`) || !firstDocId) {\n        return\n      }\n\n      const inboundReferences = await client.fetch<SanityDocument[]>(`*[references($id)]`, {\n        id: firstDocId,\n      })\n      setInbound([...docs, ...inboundReferences])\n    }\n\n    fetchInbound().catch(console.error)\n  }, [client, docs, follow])\n\n  return (\n    <Container>\n      {follow.length > 1 && (follow.includes(`inbound`) || follow.includes(`outbound`)) ? (\n        <Card paddingX={4} paddingBottom={4} marginBottom={4} borderBottom>\n          <Grid gridTemplateColumns={2} gap={4}>\n            {follow.includes(`outbound`) ? (\n              <Button\n                mode=\"ghost\"\n                tone=\"primary\"\n                selected={mode === 'outbound'}\n                onClick={() => setMode('outbound')}\n                text=\"Outbound\"\n              />\n            ) : null}\n            {follow.includes(`inbound`) ? (\n              <Button\n                mode=\"ghost\"\n                tone=\"primary\"\n                selected={mode === 'inbound'}\n                onClick={() => setMode('inbound')}\n                disabled={inbound.length === 0}\n                text={inbound.length > 0 ? `Inbound (${inbound.length})` : 'No inbound references'}\n              />\n            ) : null}\n          </Grid>\n        </Card>\n      ) : null}\n      <Duplicator\n        docs={mode === 'outbound' ? docs : inbound}\n        token={token}\n        pluginConfig={pluginConfig}\n        onDuplicated={onDuplicated}\n      />\n    </Container>\n  )\n}\n","import {Button, Flex} from '@sanity/ui'\nimport {useCallback} from 'react'\nimport {useClient} from 'sanity'\n\nimport {SECRET_NAMESPACE} from '../helpers/constants'\n\ntype ResetSecretProps = {\n  apiVersion: string\n}\n\nexport default function ResetSecret({apiVersion}: ResetSecretProps) {\n  const client = useClient({apiVersion})\n\n  const handleClick = useCallback(() => {\n    client.delete({query: `*[_id == \"secrets.${SECRET_NAMESPACE}\"]`}).catch(console.error)\n  }, [client])\n\n  return (\n    <Flex align=\"center\" justify=\"flex-end\" paddingX={[2, 2, 2, 5]} paddingY={5}>\n      <Button\n        text=\"Reset Secret\"\n        onClick={handleClick}\n        mode=\"ghost\"\n        tone=\"critical\"\n        fontSize={1}\n        padding={2}\n      />\n    </Flex>\n  )\n}\n","import {useSecrets, SettingsView} from '@sanity/studio-secrets'\nimport {Flex, Box, Spinner} from '@sanity/ui'\nimport type {SanityDocument} from 'sanity'\n\nimport {useCrossDatasetDuplicatorConfig} from '../context/ConfigProvider'\nimport {SECRET_NAMESPACE} from '../helpers/constants'\nimport DuplicatorQuery from './DuplicatorQuery'\nimport DuplicatorWrapper from './DuplicatorWrapper'\nimport Feedback from './Feedback'\nimport ResetSecret from './ResetSecret'\n\n// Check for auth secret (required for asset uploads)\nconst secretConfigKeys = [\n  {\n    key: 'bearerToken',\n    title:\n      'An API token with Viewer permissions is required to duplicate the original files of assets, and will be used for all Duplications. Create one at sanity.io/manage',\n    description: '',\n  },\n]\n\ntype Secrets = {\n  bearerToken?: string\n}\n\ntype CrossDatasetDuplicatorProps = {\n  mode: 'tool' | 'action'\n  docs: SanityDocument[]\n  onDuplicated?: () => Promise<void>\n}\n\nexport default function CrossDatasetDuplicator(props: CrossDatasetDuplicatorProps) {\n  const {mode, docs, onDuplicated} = props\n  const pluginConfig = useCrossDatasetDuplicatorConfig()\n\n  const {loading, secrets} = useSecrets<Secrets>(SECRET_NAMESPACE)\n\n  if (loading) {\n    return (\n      <Flex justify=\"center\" align=\"center\">\n        <Box padding={5}>\n          <Spinner />\n        </Box>\n      </Flex>\n    )\n  }\n\n  // A bearer token is required to duplicate assets, so the prompt cannot be\n  // dismissed until one is saved\n  if (!secrets?.bearerToken) {\n    return (\n      <SettingsView\n        title=\"Token Required\"\n        namespace={SECRET_NAMESPACE}\n        keys={secretConfigKeys}\n        onClose={() => null}\n      />\n    )\n  }\n\n  if (mode === 'tool' && pluginConfig) {\n    return (\n      <>\n        <DuplicatorQuery token={secrets.bearerToken} pluginConfig={pluginConfig} />\n        <ResetSecret apiVersion={pluginConfig.apiVersion} />\n      </>\n    )\n  }\n\n  if (!docs?.length) {\n    return <Feedback>No docs passed into Duplicator Tool</Feedback>\n  }\n\n  if (!pluginConfig) {\n    return <Feedback>No plugin config</Feedback>\n  }\n\n  return (\n    <DuplicatorWrapper\n      docs={docs}\n      token={secrets.bearerToken}\n      pluginConfig={pluginConfig}\n      onDuplicated={onDuplicated}\n    />\n  )\n}\n","import type {CrossDatasetDuplicatorActionProps} from '../types'\nimport CrossDatasetDuplicator from './CrossDatasetDuplicator'\n\n/**\n * Component to perform a migration from the Cross Dataset Duplicator plugin\n * @public\n */\nexport function CrossDatasetDuplicatorAction(props: CrossDatasetDuplicatorActionProps) {\n  const {docs, onDuplicated} = props\n\n  return <CrossDatasetDuplicator mode=\"action\" docs={docs} onDuplicated={onDuplicated} />\n}\n","import {LaunchIcon} from '@sanity/icons/Launch'\nimport {useState} from 'react'\nimport type {DocumentActionProps} from 'sanity'\n\nimport {CrossDatasetDuplicatorAction} from '../components/CrossDatasetDuplicatorAction'\n\n/**\n * Document action from the Cross Dataset Duplicator plugin\n * @public\n */\nexport const DuplicateToAction = (props: DocumentActionProps) => {\n  const {draft, published} = props\n  const [dialogOpen, setDialogOpen] = useState(false)\n\n  return {\n    disabled: Boolean(draft),\n    title: draft ? `Document must be Published to begin` : null,\n    label: 'Duplicate to...',\n    dialog: dialogOpen &&\n      published && {\n        type: 'modal',\n        title: 'Cross Dataset Duplicator',\n        content: <CrossDatasetDuplicatorAction docs={[published]} />,\n        onClose: () => setDialogOpen(false),\n      },\n    onHandle: () => setDialogOpen(true),\n    icon: LaunchIcon,\n  }\n}\n\nDuplicateToAction.action = 'duplicateTo'\n","import type {SanityDocument, Tool} from 'sanity'\n\nimport CrossDatasetDuplicator from './CrossDatasetDuplicator'\n\nexport type MultiToolConfig = {\n  docs: SanityDocument[]\n}\n\ntype CrossDatasetDuplicatorProps = {\n  tool: Tool<MultiToolConfig>\n}\n\nexport function CrossDatasetDuplicatorTool(props: CrossDatasetDuplicatorProps) {\n  const {docs = []} = props.tool.options ?? {}\n\n  return <CrossDatasetDuplicator mode=\"tool\" docs={docs} />\n}\n","import {LaunchIcon} from '@sanity/icons/Launch'\nimport type {Tool} from 'sanity'\n\nimport {\n  CrossDatasetDuplicatorTool,\n  type MultiToolConfig,\n} from '../components/CrossDatasetDuplicatorTool'\n\nexport const crossDatasetDuplicatorTool = (): Tool<MultiToolConfig> => ({\n  title: 'Duplicator',\n  name: 'duplicator',\n  icon: LaunchIcon,\n  component: CrossDatasetDuplicatorTool,\n  options: {\n    docs: [],\n  },\n})\n","import {definePlugin} from 'sanity'\n\nimport {DuplicateToAction} from './actions/DuplicateToAction'\nimport {ConfigProvider} from './context/ConfigProvider'\nimport {DEFAULT_CONFIG} from './helpers/constants'\nimport {crossDatasetDuplicatorTool} from './tool'\nimport type {PluginConfig} from './types'\n\n/**\n * Plugin: Cross Dataset Duplicator\n * @public\n */\nexport const crossDatasetDuplicator = definePlugin<Partial<PluginConfig> | void>((config = {}) => {\n  const pluginConfig = {...DEFAULT_CONFIG, ...config}\n  const {types} = pluginConfig\n\n  return {\n    name: '@sanity/cross-dataset-duplicator',\n    tools: (prev) => (pluginConfig.tool ? [...prev, crossDatasetDuplicatorTool()] : prev),\n    studio: {\n      components: {\n        layout: (props) => <ConfigProvider {...props} pluginConfig={pluginConfig} />,\n      },\n    },\n    document: {\n      actions: (prev, {schemaType}) => {\n        return types && types.includes(schemaType) ? [...prev, DuplicateToAction] : prev\n      },\n    },\n  }\n})\n"],"mappings":"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"}
\ No newline at end of file