fetchForProtein.ts 3 KB
Newer Older
Imran Salam's avatar
Imran Salam committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/**
 * See the NOTICE file distributed with this work for additional information
 * regarding copyright ownership.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

17 18
import { wrap } from 'comlink';

Imran Salam's avatar
Imran Salam committed
19 20 21 22 23 24
import downloadAsFile from 'src/shared/helpers/downloadAsFile';
import {
  ProteinOptions,
  ProteinOption,
  proteinOptionsOrder
} from 'src/shared/components/instant-download/instant-download-protein/InstantDownloadProtein';
25
import {
26 27
  fetchTranscriptSequenceMetadata,
  TranscriptSequenceMetadata
28
} from './fetchSequenceChecksums';
Imran Salam's avatar
Imran Salam committed
29

Andrey Azov's avatar
Andrey Azov committed
30 31
// @ts-expect-error There is in fact no default export in the worker
import SequenceFetcherWorker, {
32 33 34 35
  WorkerApi,
  SingleSequenceFetchParams
} from 'src/shared/workers/sequenceFetcher.worker';

Imran Salam's avatar
Imran Salam committed
36
type FetchPayload = {
37
  genomeId: string;
Imran Salam's avatar
Imran Salam committed
38 39 40 41 42
  transcriptId: string;
  options: ProteinOptions;
};

export const fetchForProtein = async (payload: FetchPayload) => {
43
  const { genomeId, transcriptId, options } = payload;
44
  const transcriptSequenceData = await fetchTranscriptSequenceMetadata({
45 46 47
    genomeId,
    transcriptId
  });
Imran Salam's avatar
Imran Salam committed
48

49 50 51 52 53
  const sequenceDownloadParams = prepareDownloadParameters({
    transcriptSequenceData,
    options
  });

Andrey Azov's avatar
Andrey Azov committed
54
  const worker = new SequenceFetcherWorker();
Imran Salam's avatar
Imran Salam committed
55

56
  const service = wrap<WorkerApi>(worker);
Imran Salam's avatar
Imran Salam committed
57

58 59 60 61 62
  const sequences = await service.downloadSequences(sequenceDownloadParams);

  worker.terminate();

  downloadAsFile(sequences, `${transcriptId}.fasta`, {
Imran Salam's avatar
Imran Salam committed
63 64 65 66
    type: 'text/x-fasta'
  });
};

67 68 69
type PrepareDownloadParametersParams = {
  transcriptSequenceData: TranscriptSequenceMetadata;
  options: ProteinOptions;
Imran Salam's avatar
Imran Salam committed
70 71
};

Imran Salam's avatar
Imran Salam committed
72 73 74 75 76 77 78 79 80
// map of field names received from component to field names returned when fetching checksums
const labelTypeToSequenceType: Record<
  ProteinOption,
  keyof Omit<TranscriptSequenceMetadata, 'stable_id' | 'unversioned_stable_id'>
> = {
  proteinSequence: 'protein',
  cds: 'cds'
};

81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
const prepareDownloadParameters = (params: PrepareDownloadParametersParams) => {
  const { transcriptSequenceData } = params;
  return proteinOptionsOrder
    .filter((option) => params.options[option])
    .map((option) => labelTypeToSequenceType[option]) // 'protein', 'cds'
    .map((option) => {
      const dataForSingleSequence = transcriptSequenceData[option];
      if (!dataForSingleSequence) {
        // shouldn't happen; but to keep typescript happy
        return null;
      }
      return {
        label: dataForSingleSequence.label,
        url: `/api/refget/sequence/${dataForSingleSequence.checksum}?accept=text/plain`
      };
    })
    .filter(Boolean) as SingleSequenceFetchParams[];
};