@fishka/seqio 0.6.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,32 +1,88 @@
1
1
  export { AbifBaseCallRole, AbifBaseCallVariant, AbifBaseCalls, AbifByteRange, AbifChromatogramBundle, AbifDataChannelRole, AbifDecodedValue, AbifDirEntry, AbifDirectory, AbifEntry, AbifEntryRaw, AbifFile, AbifMetadata, ChannelSignals, Chromatogram, CropAbifOptions, CropAbifRange, ENTRY_SIZE, HEADER_SIZE, ParsedAbif, averagePeakSpacing, channelMaxLength, cropAbif, dataChannelRole, ensureRawDataChannels, findEntries, findEntry, getChannelMap, getConfidences, getConfidencesForVersion, getDataChannel, getFwo, getPositions, getPositionsForVersion, getReverseComplemented, getSamplingRate, getSequence, getSequenceForVersion, hasData9To12Block, hasSignals, insertEntrySorted, isFwoPermutation, parseAbif, readAbif, setAveragePeakSpacing, setConfidences, setPositions, setSequence, tagNameFromInt32, upsertEntry, writeAbif } from './abif/index.mjs';
2
2
 
3
3
  /**
4
- * FASTA / FASTQ / .qual text serialization.
4
+ * Content-based file-format detection.
5
5
  *
6
- * Pure, format-level writers: they turn a sequence plus optional per-base Phred
7
- * quality into text. No coupling to any binary format callers build records
8
- * from ABIF basecalls (PBAS/PCON), alignments, consensus, etc.
6
+ * Sniffs the bytes, never the file extension: binary magic first (ABIF at offset 0, or at
7
+ * 128 behind a MacBinary preamble; SCF's ".scf" magic), then the first non-blank line for
8
+ * the text formats. Text signatures are matched on the leading line's content (a keyword
9
+ * like `LOCUS`, or the first character `>` / `;` / `@`), so a mislabeled or extension-less
10
+ * file still resolves.
11
+ */
12
+ /** A format {@link detectFormat} can recognize. Some are detected before their reader ships. */
13
+ type SeqFileFormat = 'abif' | 'scf' | 'fasta' | 'fastq' | 'genbank' | 'embl' | 'swissprot' | 'clustal' | 'stockholm' | 'phylip' | 'nexus' | 'msf' | 'pir' | 'gff' | 'sam' | 'bam' | 'gfa' | 'unknown';
14
+ /**
15
+ * Detect the sequencing file format from its content. Returns 'unknown' when no signature
16
+ * matches (empty input, or a leading line that is neither a known magic nor a recognized
17
+ * text marker).
18
+ */
19
+ declare function detectFormat(bytes: Uint8Array): SeqFileFormat;
20
+
21
+ /**
22
+ * The common "a sequence with a name" record produced by every reader that extracts
23
+ * sequences for downstream picking/export (GenBank, EMBL, Swiss-Prot, the alignment
24
+ * formats, …). Data only — same shape as {@link FastaRecord}, so all readers feed one
25
+ * uniform list regardless of source format.
26
+ */
27
+ interface SeqRecord {
28
+ /** Identifier (accession/version/locus/name, per the source format's convention). */
29
+ id: string;
30
+ /** Free-text description/definition when the format carries one. */
31
+ description?: string;
32
+ /**
33
+ * Residues with line wrapping removed. Case is preserved as written; alignment gap
34
+ * characters ('-', '.') are kept (an aligned row is stored verbatim, not de-gapped).
35
+ */
36
+ sequence: string;
37
+ }
38
+ /** Build a {@link SeqRecord}, dropping an empty description so records compare cleanly. */
39
+ declare function makeSeqRecord(id: string, description: string, sequence: string): SeqRecord;
40
+
41
+ /**
42
+ * EMBL / Swiss-Prot (UniProtKB) flat-file reader — sequence extraction only.
43
+ *
44
+ * Both formats share one container: two-letter line-type codes in columns 0–1, an `SQ`
45
+ * line that introduces the sequence, indented sequence lines (residues + trailing position
46
+ * counters), and `//` between records. UniProtKB is historically derived from the EMBL
47
+ * format, so a single scanner serves both; they differ only in which field is the id:
48
+ * - EMBL: the `ID` line's accession, suffixed with the sequence version (`SV n` → `.n`),
49
+ * falling back to `AC`.
50
+ * - Swiss-Prot: the primary `AC` accession (the `ID` line is the entry name), falling
51
+ * back to that entry name.
52
+ * Description comes from the `DE` line(s), joined. Feature tables (`FT`) and all other codes
53
+ * are skipped — this is the sequence-reading path only.
9
54
  *
10
- * Quality is encoded as Phred+33 (Sanger / Illumina 1.8+). Scores are clamped
11
- * to [0, {@link MAX_PHRED}]: the upper bound is the largest value representable
12
- * as Phred+33 ('~' = ASCII 126 = 93 + 33). Callers must NOT feed quality for
13
- * reads that lack it — gate on {@link hasUsableQuality} and emit FASTA only,
14
- * rather than letting the 255 "no quality" sentinel clamp to a perfect '~'.
55
+ * Deliberately lenient (see AGENTS.md): never throws. No `SQ` block empty sequence; a
56
+ * missing `//` between records flushes the previous one when the next `ID` appears; a
57
+ * truncated final record is flushed at EOF. Residue case is preserved as written.
58
+ */
59
+
60
+ /** Read EMBL flat files (`.embl`/`.dat`): id = accession.version from the ID line. */
61
+ declare function parseEmbl(input: string | Uint8Array): SeqRecord[];
62
+ /** Read UniProtKB/Swiss-Prot flat files (`.dat`/`.txt`): id = primary AC accession. */
63
+ declare function parseSwissprot(input: string | Uint8Array): SeqRecord[];
64
+
65
+ /**
66
+ * Record + option types for the FASTA / FASTQ / .qual family.
67
+ *
68
+ * These carry the sequence's data only — the residues and (FASTQ) the per-base
69
+ * Phred scores. A file's line wrapping and newline style are cosmetic: the readers
70
+ * discard them and the writers re-impose a chosen width. The same record shape is
71
+ * used symmetrically for reading and writing, so parse → edit → write round-trips
72
+ * the data (not the exact bytes).
15
73
  */
16
- /** Largest Phred score representable as Phred+33 ('~' = ASCII 126 = 93 + 33). */
17
- declare const MAX_PHRED = 93;
18
74
  /** A FASTA record: identifier, optional description, and residues. */
19
75
  interface FastaRecord {
20
- /** Identifier written after '>', up to the first space. */
76
+ /** Identifier: the header text up to the first whitespace (the '>' is not included). */
21
77
  id: string;
22
- /** Optional free text after the id on the header line. */
78
+ /** Free text after the id on the header line; absent when the header is just an id. */
23
79
  description?: string;
24
- /** Residues, written verbatim (case and gaps preserved). */
80
+ /** Residues with all line breaks/whitespace removed; case and gap chars ('-', '.') preserved. */
25
81
  sequence: string;
26
82
  }
27
83
  /** A FASTQ record: a {@link FastaRecord} plus one Phred score per residue. */
28
84
  interface FastqRecord extends FastaRecord {
29
- /** Per-base Phred scores; must be one per residue in {@link FastaRecord.sequence}. */
85
+ /** Per-base Phred scores decoded from the quality line (Phred+33), one per residue. */
30
86
  qualities: readonly number[];
31
87
  }
32
88
  /** A .qual record: identifier, optional description, and per-base Phred scores. */
@@ -40,6 +96,58 @@ interface WrapOptions {
40
96
  /** Residues (FASTA) or scores (.qual) per line; <= 0 writes one line. Default 60. */
41
97
  lineWidth?: number;
42
98
  }
99
+
100
+ /**
101
+ * FASTA / FASTQ / .qual text codec: readers (parseFasta / parseFastq) and writers
102
+ * (formatFasta / formatFastq / formatQual).
103
+ *
104
+ * Text formats have no on-disk container, so there is no separate raw layer — this
105
+ * one file is the codec (the `<family>-format.ts` analog of `abif-format.ts`).
106
+ *
107
+ * Data only: the readers keep residues and per-base Phred scores and drop cosmetic
108
+ * formatting (line wrapping, blank lines, `\r\n` vs `\n`); the writers re-impose a
109
+ * chosen wrap width. Quality is Phred+33 (Sanger / Illumina 1.8+); scores are clamped
110
+ * to [0, {@link MAX_PHRED}] on write ('~' = ASCII 126 = 93 + 33).
111
+ */
112
+
113
+ /** Largest Phred score representable as Phred+33 ('~' = ASCII 126 = 93 + 33). */
114
+ declare const MAX_PHRED = 93;
115
+ /**
116
+ * Parse FASTA text (or bytes) into records. Deliberately lenient — it never refuses a
117
+ * file: blank lines and legacy ';' comment lines are ignored, residue lines are
118
+ * concatenated with inner whitespace stripped (case and gaps preserved), and any stray
119
+ * text before the first '>' header is skipped. id = the header up to the first
120
+ * whitespace, description = the remainder.
121
+ */
122
+ declare function parseFasta(input: string | Uint8Array): FastaRecord[];
123
+ /**
124
+ * Parse FASTQ text (or bytes) into records with decoded Phred+33 qualities.
125
+ *
126
+ * Handles multi-line records: the sequence runs to the '+' separator, then the quality
127
+ * runs until it has as many chars as the sequence has residues. Length — not "the next
128
+ * line starting with @" — terminates the quality block, because a quality character can
129
+ * itself be '@' (Phred 31) or '+' (Phred 10); this is the one subtlety the spec calls
130
+ * out (Cock et al. 2010).
131
+ *
132
+ * Deliberately lenient — it never refuses a file, and never lets one malformed record
133
+ * cost a *following* one. A stray line where a '@' header is expected is skipped (resync
134
+ * at the next '@'); a record with no '+' separator (truncated, or the next record starts)
135
+ * keeps its sequence with unknown quality; a short/over-long or out-of-range quality is
136
+ * reconciled to the residue count in {@link makeFastq}. The sequence — what callers
137
+ * actually pick — is always preserved intact, for every record.
138
+ *
139
+ * Cross-record safety comes from recognizing a real next-record header structurally: a
140
+ * line beginning '@' is the next header (not this record's quality) when a '+' separator
141
+ * follows its sequence before any other '@' — see {@link startsRecord}. This is exact for
142
+ * strict 4-line FASTQ (the real-world norm, where a quality line is followed only by the
143
+ * next '@' header or EOF) and preserves every following record even when a quality block is
144
+ * badly truncated. The one accepted blind spot is a deliberate trade-off: '@' and '+' are
145
+ * both valid Phred+33 characters, so in *wrapped* multi-line quality a continuation line
146
+ * that begins '@' and is later followed (before the next header) by one beginning '+' is
147
+ * misread as a header. That pattern is vanishingly rare, and favoring "never drop the next
148
+ * record's sequence on truncated input" over it is the right call for this parser's use.
149
+ */
150
+ declare function parseFastq(input: string | Uint8Array): FastqRecord[];
43
151
  /** Serialize one or more records to FASTA text (trailing newline included). */
44
152
  declare function formatFasta(records: FastaRecord | readonly FastaRecord[], options?: WrapOptions): string;
45
153
  /** Serialize one or more records to FASTQ text, Phred+33 (trailing newline included). */
@@ -53,4 +161,152 @@ declare function formatQual(records: QualRecord | readonly QualRecord[], options
53
161
  */
54
162
  declare function hasUsableQuality(qualities?: readonly number[]): boolean;
55
163
 
56
- export { type FastaRecord, type FastqRecord, MAX_PHRED, type QualRecord, type WrapOptions, formatFasta, formatFastq, formatQual, hasUsableQuality };
164
+ /**
165
+ * GenBank / GenPept flat-file reader — sequence extraction only.
166
+ *
167
+ * Reads the sequence(s) and their identity out of GenBank flat files (`.gb`/`.gbk`/`.gbff`,
168
+ * and the protein `.gp` variant). One file may hold many records, each ending in `//`. We
169
+ * take what a "pick a sequence" caller needs and skip the rest:
170
+ * - id: VERSION (accession.version) if present, else ACCESSION, else the LOCUS name.
171
+ * - description: DEFINITION (its continuation lines joined).
172
+ * - sequence: the ORIGIN block, with the leading base counters and spacing stripped.
173
+ * Feature-table parsing (locations, /translation, join/complement) is intentionally out of
174
+ * scope here — this is the sequence-reading path, not a full annotation model.
175
+ *
176
+ * Deliberately lenient (see AGENTS.md): never throws. A record with no ORIGIN yields an
177
+ * empty sequence rather than an error; a missing `//` between records (or a truncated final
178
+ * record) still yields every record whose LOCUS was seen. Sequence case is preserved as
179
+ * written (GenBank ORIGIN is conventionally lowercase).
180
+ */
181
+
182
+ declare function parseGenbank(input: string | Uint8Array): SeqRecord[];
183
+
184
+ /**
185
+ * GFA (Graphical Fragment Assembly, `.gfa`) reader — sequence extraction.
186
+ *
187
+ * Assembly / pangenome graphs. Only Segment (`S`) lines carry sequence; links, paths, jumps and
188
+ * containments are graph topology and hold none. Both dialects are supported by field position:
189
+ *
190
+ * GFA1: S <name> <sequence> [tags…]
191
+ * GFA2: S <sid> <slen> <sequence> [tags…]
192
+ *
193
+ * GFA2 inserts an integer segment length between the name and the sequence, so when the field after
194
+ * the name is a bare integer AND another field follows, the sequence is that next field; otherwise
195
+ * it's the field right after the name (GFA1). A `*` sequence (a segment declared without residues)
196
+ * is skipped — there's nothing to pick. Lenient: never throws; malformed lines are ignored.
197
+ */
198
+
199
+ declare function parseGfa(input: string | Uint8Array): SeqRecord[];
200
+
201
+ /**
202
+ * GFF3 (`.gff`/`.gff3`) reader — sequence extraction.
203
+ *
204
+ * A GFF3 file is annotation (feature coordinates), which carries NO sequence — except when it
205
+ * embeds a FASTA section after a `##FASTA` directive. This reader returns the records of that
206
+ * embedded FASTA and nothing else; a GFF with no `##FASTA` section yields `[]` (there is no
207
+ * sequence to pick). Feature lines are never turned into sequence.
208
+ */
209
+
210
+ declare function parseGff(input: string | Uint8Array): SeqRecord[];
211
+
212
+ /**
213
+ * Multiple-sequence-alignment readers — one aligned row = one record.
214
+ *
215
+ * Covers the common alignment formats: Clustal (`.aln`), Stockholm (`.sto`/`.stk`),
216
+ * PHYLIP (`.phy`), NEXUS (`.nex`) and GCG/MSF (`.msf`). Each returns the alignment's rows
217
+ * as {@link SeqRecord}s: `id` = the taxon/sequence name, `sequence` = that row **with its
218
+ * gap characters preserved** (an aligned row is data; de-gapping is a caller's choice).
219
+ * Only line spacing and wrap are removed. No description field — these formats don't carry
220
+ * a per-row one.
221
+ *
222
+ * Deliberately lenient (see AGENTS.md): never throws, best-effort on malformed input, and
223
+ * always returns every row it can. Interleaved blocks are accumulated by name.
224
+ */
225
+
226
+ /** Read a Clustal (`.aln`) alignment. Also handles the Clustal-format output of MUSCLE, MAFFT, etc. */
227
+ declare function parseClustal(input: string | Uint8Array): SeqRecord[];
228
+ /** Read a Stockholm (`.sto`/`.stk`) alignment; multiple `//`-separated alignments are all returned. */
229
+ declare function parseStockholm(input: string | Uint8Array): SeqRecord[];
230
+ /**
231
+ * Read a PHYLIP (`.phy`) alignment. Supports relaxed (whitespace-delimited names) interleaved
232
+ * and single-block layouts — the common modern output (RAxML/PhyML/aligners). The first line is
233
+ * `<ntax> <nchar>`; the next `ntax` non-blank lines carry names + the first block; any further
234
+ * non-blank lines are interleaved continuation, appended round-robin and clipped at `nchar` so a
235
+ * stray line can't overrun residues into another taxon.
236
+ *
237
+ * Limitation: multi-line *sequential* PHYLIP (each taxon's whole sequence spanning consecutive
238
+ * lines before the next taxon) is read as interleaved and would be misassigned; it is rare next to
239
+ * interleaved output. Single-line sequential (one line per taxon) reads correctly.
240
+ */
241
+ declare function parsePhylip(input: string | Uint8Array): SeqRecord[];
242
+ /**
243
+ * Read a NEXUS (`.nex`) DATA/CHARACTERS block's MATRIX. Handles interleaved matrices (names
244
+ * repeat across blocks), space-grouped rows, and a final row that closes the matrix with `;`.
245
+ *
246
+ * Not resolved (kept verbatim / unsupported): `FORMAT MATCHCHAR=.` — a `.` meaning "same residue
247
+ * as the first taxon here" is left literal rather than substituted; and label-less matrices
248
+ * (`FORMAT LABELS=NO`, relying on TAXLABELS order) whose rows carry no name are skipped.
249
+ */
250
+ declare function parseNexus(input: string | Uint8Array): SeqRecord[];
251
+ /** Read a GCG/MSF (`.msf`) alignment (the sequence blocks after the header's `//`). */
252
+ declare function parseMsf(input: string | Uint8Array): SeqRecord[];
253
+
254
+ /**
255
+ * PIR / NBRF (`.pir`) reader — sequence extraction.
256
+ *
257
+ * A PIR record is: a header `>XX;identifier` (the two-letter code XX is the sequence type —
258
+ * P1/F1 protein, DL/DC DNA, RL/RC RNA, N1/N3 nucleotide, XX other), a free-text title line,
259
+ * then the residues, terminated by `*`. One file may hold many records.
260
+ * - id: the identifier after the `;` (or the whole header when there is no `;`).
261
+ * - description: the title line.
262
+ * - sequence: the residues with spacing removed and the single trailing `*` terminator dropped.
263
+ *
264
+ * Deliberately lenient (see AGENTS.md): never throws; a truncated record (no `*`) keeps its
265
+ * residues; the first line after a header is taken as the title.
266
+ */
267
+
268
+ declare function parsePir(input: string | Uint8Array): SeqRecord[];
269
+
270
+ /**
271
+ * BAM (`.bam`) reader — read-sequence extraction from the binary alignment format.
272
+ *
273
+ * BAM is the binary twin of SAM. On disk it is BGZF-compressed (a gzip stream of concatenated
274
+ * blocks); this reader expects the INFLATED bytes — starting with the "BAM\1" magic. The caller
275
+ * peels the gzip/BGZF wrapper first (a gzip decompressor decodes BGZF's concatenated members), so
276
+ * this stays a synchronous, dependency-free binary parser.
277
+ *
278
+ * Semantics mirror the SAM reader exactly (see {@link parseSam}): one sequence per read (secondary
279
+ * 0x100 / supplementary 0x800 skipped), reverse-strand sequence stored verbatim (reference-forward),
280
+ * id = read name (+ /1,/2 for paired mates), description = "RNAME:POS (+/-)" or "unmapped". Records
281
+ * without a stored sequence (l_seq = 0) are skipped. Lenient: on any truncation or garble it stops
282
+ * and returns what it parsed cleanly, never throwing.
283
+ */
284
+
285
+ declare function parseBam(bytes: Uint8Array): SeqRecord[];
286
+
287
+ /**
288
+ * SAM (`.sam`) reader — read-sequence extraction.
289
+ *
290
+ * SAM is a read-alignment format: one record per alignment, tab-delimited, with 11 mandatory
291
+ * fields (QNAME FLAG RNAME POS MAPQ CIGAR RNEXT PNEXT TLEN SEQ QUAL). This reader returns each
292
+ * record's read sequence — field 10, `SEQ`. Records whose SEQ is `*` (sequence not stored) are
293
+ * skipped: there's nothing to pick.
294
+ *
295
+ * The sequence is returned VERBATIM as written. For a reverse-strand alignment (FLAG bit 0x10) SAM
296
+ * already stores the reverse complement (reference-forward orientation), so that reference-oriented
297
+ * sequence is what you get — it is deliberately not un-flipped to the original read orientation.
298
+ *
299
+ * One sequence per read: secondary (FLAG 0x100) and supplementary (0x800) alignments are skipped —
300
+ * they re-map the same read (a duplicate, or a hard-clipped split fragment), which would pollute a
301
+ * "pick the sequences" list. What's kept is the read's SEQ from its primary (or unmapped) record —
302
+ * i.e. the sequence as SAM stores it, which for a hard-clipped primary alignment omits the clipped
303
+ * flanks rather than reconstructing the original full read.
304
+ *
305
+ * `@`-prefixed lines are skipped as headers — the SAM spec's QNAME charset `[!-?A-~]` excludes '@'
306
+ * (0x40) precisely so a read name can never be confused with a header. Lenient: never throws; lines
307
+ * with fewer than 11 fields are ignored rather than rejected.
308
+ */
309
+
310
+ declare function parseSam(input: string | Uint8Array): SeqRecord[];
311
+
312
+ export { type FastaRecord, type FastqRecord, MAX_PHRED, type QualRecord, type SeqFileFormat, type SeqRecord, type WrapOptions, detectFormat, formatFasta, formatFastq, formatQual, hasUsableQuality, makeSeqRecord, parseBam, parseClustal, parseEmbl, parseFasta, parseFastq, parseGenbank, parseGfa, parseGff, parseMsf, parseNexus, parsePhylip, parsePir, parseSam, parseStockholm, parseSwissprot };
package/dist/index.d.ts CHANGED
@@ -1,32 +1,88 @@
1
1
  export { AbifBaseCallRole, AbifBaseCallVariant, AbifBaseCalls, AbifByteRange, AbifChromatogramBundle, AbifDataChannelRole, AbifDecodedValue, AbifDirEntry, AbifDirectory, AbifEntry, AbifEntryRaw, AbifFile, AbifMetadata, ChannelSignals, Chromatogram, CropAbifOptions, CropAbifRange, ENTRY_SIZE, HEADER_SIZE, ParsedAbif, averagePeakSpacing, channelMaxLength, cropAbif, dataChannelRole, ensureRawDataChannels, findEntries, findEntry, getChannelMap, getConfidences, getConfidencesForVersion, getDataChannel, getFwo, getPositions, getPositionsForVersion, getReverseComplemented, getSamplingRate, getSequence, getSequenceForVersion, hasData9To12Block, hasSignals, insertEntrySorted, isFwoPermutation, parseAbif, readAbif, setAveragePeakSpacing, setConfidences, setPositions, setSequence, tagNameFromInt32, upsertEntry, writeAbif } from './abif/index.js';
2
2
 
3
3
  /**
4
- * FASTA / FASTQ / .qual text serialization.
4
+ * Content-based file-format detection.
5
5
  *
6
- * Pure, format-level writers: they turn a sequence plus optional per-base Phred
7
- * quality into text. No coupling to any binary format callers build records
8
- * from ABIF basecalls (PBAS/PCON), alignments, consensus, etc.
6
+ * Sniffs the bytes, never the file extension: binary magic first (ABIF at offset 0, or at
7
+ * 128 behind a MacBinary preamble; SCF's ".scf" magic), then the first non-blank line for
8
+ * the text formats. Text signatures are matched on the leading line's content (a keyword
9
+ * like `LOCUS`, or the first character `>` / `;` / `@`), so a mislabeled or extension-less
10
+ * file still resolves.
11
+ */
12
+ /** A format {@link detectFormat} can recognize. Some are detected before their reader ships. */
13
+ type SeqFileFormat = 'abif' | 'scf' | 'fasta' | 'fastq' | 'genbank' | 'embl' | 'swissprot' | 'clustal' | 'stockholm' | 'phylip' | 'nexus' | 'msf' | 'pir' | 'gff' | 'sam' | 'bam' | 'gfa' | 'unknown';
14
+ /**
15
+ * Detect the sequencing file format from its content. Returns 'unknown' when no signature
16
+ * matches (empty input, or a leading line that is neither a known magic nor a recognized
17
+ * text marker).
18
+ */
19
+ declare function detectFormat(bytes: Uint8Array): SeqFileFormat;
20
+
21
+ /**
22
+ * The common "a sequence with a name" record produced by every reader that extracts
23
+ * sequences for downstream picking/export (GenBank, EMBL, Swiss-Prot, the alignment
24
+ * formats, …). Data only — same shape as {@link FastaRecord}, so all readers feed one
25
+ * uniform list regardless of source format.
26
+ */
27
+ interface SeqRecord {
28
+ /** Identifier (accession/version/locus/name, per the source format's convention). */
29
+ id: string;
30
+ /** Free-text description/definition when the format carries one. */
31
+ description?: string;
32
+ /**
33
+ * Residues with line wrapping removed. Case is preserved as written; alignment gap
34
+ * characters ('-', '.') are kept (an aligned row is stored verbatim, not de-gapped).
35
+ */
36
+ sequence: string;
37
+ }
38
+ /** Build a {@link SeqRecord}, dropping an empty description so records compare cleanly. */
39
+ declare function makeSeqRecord(id: string, description: string, sequence: string): SeqRecord;
40
+
41
+ /**
42
+ * EMBL / Swiss-Prot (UniProtKB) flat-file reader — sequence extraction only.
43
+ *
44
+ * Both formats share one container: two-letter line-type codes in columns 0–1, an `SQ`
45
+ * line that introduces the sequence, indented sequence lines (residues + trailing position
46
+ * counters), and `//` between records. UniProtKB is historically derived from the EMBL
47
+ * format, so a single scanner serves both; they differ only in which field is the id:
48
+ * - EMBL: the `ID` line's accession, suffixed with the sequence version (`SV n` → `.n`),
49
+ * falling back to `AC`.
50
+ * - Swiss-Prot: the primary `AC` accession (the `ID` line is the entry name), falling
51
+ * back to that entry name.
52
+ * Description comes from the `DE` line(s), joined. Feature tables (`FT`) and all other codes
53
+ * are skipped — this is the sequence-reading path only.
9
54
  *
10
- * Quality is encoded as Phred+33 (Sanger / Illumina 1.8+). Scores are clamped
11
- * to [0, {@link MAX_PHRED}]: the upper bound is the largest value representable
12
- * as Phred+33 ('~' = ASCII 126 = 93 + 33). Callers must NOT feed quality for
13
- * reads that lack it — gate on {@link hasUsableQuality} and emit FASTA only,
14
- * rather than letting the 255 "no quality" sentinel clamp to a perfect '~'.
55
+ * Deliberately lenient (see AGENTS.md): never throws. No `SQ` block empty sequence; a
56
+ * missing `//` between records flushes the previous one when the next `ID` appears; a
57
+ * truncated final record is flushed at EOF. Residue case is preserved as written.
58
+ */
59
+
60
+ /** Read EMBL flat files (`.embl`/`.dat`): id = accession.version from the ID line. */
61
+ declare function parseEmbl(input: string | Uint8Array): SeqRecord[];
62
+ /** Read UniProtKB/Swiss-Prot flat files (`.dat`/`.txt`): id = primary AC accession. */
63
+ declare function parseSwissprot(input: string | Uint8Array): SeqRecord[];
64
+
65
+ /**
66
+ * Record + option types for the FASTA / FASTQ / .qual family.
67
+ *
68
+ * These carry the sequence's data only — the residues and (FASTQ) the per-base
69
+ * Phred scores. A file's line wrapping and newline style are cosmetic: the readers
70
+ * discard them and the writers re-impose a chosen width. The same record shape is
71
+ * used symmetrically for reading and writing, so parse → edit → write round-trips
72
+ * the data (not the exact bytes).
15
73
  */
16
- /** Largest Phred score representable as Phred+33 ('~' = ASCII 126 = 93 + 33). */
17
- declare const MAX_PHRED = 93;
18
74
  /** A FASTA record: identifier, optional description, and residues. */
19
75
  interface FastaRecord {
20
- /** Identifier written after '>', up to the first space. */
76
+ /** Identifier: the header text up to the first whitespace (the '>' is not included). */
21
77
  id: string;
22
- /** Optional free text after the id on the header line. */
78
+ /** Free text after the id on the header line; absent when the header is just an id. */
23
79
  description?: string;
24
- /** Residues, written verbatim (case and gaps preserved). */
80
+ /** Residues with all line breaks/whitespace removed; case and gap chars ('-', '.') preserved. */
25
81
  sequence: string;
26
82
  }
27
83
  /** A FASTQ record: a {@link FastaRecord} plus one Phred score per residue. */
28
84
  interface FastqRecord extends FastaRecord {
29
- /** Per-base Phred scores; must be one per residue in {@link FastaRecord.sequence}. */
85
+ /** Per-base Phred scores decoded from the quality line (Phred+33), one per residue. */
30
86
  qualities: readonly number[];
31
87
  }
32
88
  /** A .qual record: identifier, optional description, and per-base Phred scores. */
@@ -40,6 +96,58 @@ interface WrapOptions {
40
96
  /** Residues (FASTA) or scores (.qual) per line; <= 0 writes one line. Default 60. */
41
97
  lineWidth?: number;
42
98
  }
99
+
100
+ /**
101
+ * FASTA / FASTQ / .qual text codec: readers (parseFasta / parseFastq) and writers
102
+ * (formatFasta / formatFastq / formatQual).
103
+ *
104
+ * Text formats have no on-disk container, so there is no separate raw layer — this
105
+ * one file is the codec (the `<family>-format.ts` analog of `abif-format.ts`).
106
+ *
107
+ * Data only: the readers keep residues and per-base Phred scores and drop cosmetic
108
+ * formatting (line wrapping, blank lines, `\r\n` vs `\n`); the writers re-impose a
109
+ * chosen wrap width. Quality is Phred+33 (Sanger / Illumina 1.8+); scores are clamped
110
+ * to [0, {@link MAX_PHRED}] on write ('~' = ASCII 126 = 93 + 33).
111
+ */
112
+
113
+ /** Largest Phred score representable as Phred+33 ('~' = ASCII 126 = 93 + 33). */
114
+ declare const MAX_PHRED = 93;
115
+ /**
116
+ * Parse FASTA text (or bytes) into records. Deliberately lenient — it never refuses a
117
+ * file: blank lines and legacy ';' comment lines are ignored, residue lines are
118
+ * concatenated with inner whitespace stripped (case and gaps preserved), and any stray
119
+ * text before the first '>' header is skipped. id = the header up to the first
120
+ * whitespace, description = the remainder.
121
+ */
122
+ declare function parseFasta(input: string | Uint8Array): FastaRecord[];
123
+ /**
124
+ * Parse FASTQ text (or bytes) into records with decoded Phred+33 qualities.
125
+ *
126
+ * Handles multi-line records: the sequence runs to the '+' separator, then the quality
127
+ * runs until it has as many chars as the sequence has residues. Length — not "the next
128
+ * line starting with @" — terminates the quality block, because a quality character can
129
+ * itself be '@' (Phred 31) or '+' (Phred 10); this is the one subtlety the spec calls
130
+ * out (Cock et al. 2010).
131
+ *
132
+ * Deliberately lenient — it never refuses a file, and never lets one malformed record
133
+ * cost a *following* one. A stray line where a '@' header is expected is skipped (resync
134
+ * at the next '@'); a record with no '+' separator (truncated, or the next record starts)
135
+ * keeps its sequence with unknown quality; a short/over-long or out-of-range quality is
136
+ * reconciled to the residue count in {@link makeFastq}. The sequence — what callers
137
+ * actually pick — is always preserved intact, for every record.
138
+ *
139
+ * Cross-record safety comes from recognizing a real next-record header structurally: a
140
+ * line beginning '@' is the next header (not this record's quality) when a '+' separator
141
+ * follows its sequence before any other '@' — see {@link startsRecord}. This is exact for
142
+ * strict 4-line FASTQ (the real-world norm, where a quality line is followed only by the
143
+ * next '@' header or EOF) and preserves every following record even when a quality block is
144
+ * badly truncated. The one accepted blind spot is a deliberate trade-off: '@' and '+' are
145
+ * both valid Phred+33 characters, so in *wrapped* multi-line quality a continuation line
146
+ * that begins '@' and is later followed (before the next header) by one beginning '+' is
147
+ * misread as a header. That pattern is vanishingly rare, and favoring "never drop the next
148
+ * record's sequence on truncated input" over it is the right call for this parser's use.
149
+ */
150
+ declare function parseFastq(input: string | Uint8Array): FastqRecord[];
43
151
  /** Serialize one or more records to FASTA text (trailing newline included). */
44
152
  declare function formatFasta(records: FastaRecord | readonly FastaRecord[], options?: WrapOptions): string;
45
153
  /** Serialize one or more records to FASTQ text, Phred+33 (trailing newline included). */
@@ -53,4 +161,152 @@ declare function formatQual(records: QualRecord | readonly QualRecord[], options
53
161
  */
54
162
  declare function hasUsableQuality(qualities?: readonly number[]): boolean;
55
163
 
56
- export { type FastaRecord, type FastqRecord, MAX_PHRED, type QualRecord, type WrapOptions, formatFasta, formatFastq, formatQual, hasUsableQuality };
164
+ /**
165
+ * GenBank / GenPept flat-file reader — sequence extraction only.
166
+ *
167
+ * Reads the sequence(s) and their identity out of GenBank flat files (`.gb`/`.gbk`/`.gbff`,
168
+ * and the protein `.gp` variant). One file may hold many records, each ending in `//`. We
169
+ * take what a "pick a sequence" caller needs and skip the rest:
170
+ * - id: VERSION (accession.version) if present, else ACCESSION, else the LOCUS name.
171
+ * - description: DEFINITION (its continuation lines joined).
172
+ * - sequence: the ORIGIN block, with the leading base counters and spacing stripped.
173
+ * Feature-table parsing (locations, /translation, join/complement) is intentionally out of
174
+ * scope here — this is the sequence-reading path, not a full annotation model.
175
+ *
176
+ * Deliberately lenient (see AGENTS.md): never throws. A record with no ORIGIN yields an
177
+ * empty sequence rather than an error; a missing `//` between records (or a truncated final
178
+ * record) still yields every record whose LOCUS was seen. Sequence case is preserved as
179
+ * written (GenBank ORIGIN is conventionally lowercase).
180
+ */
181
+
182
+ declare function parseGenbank(input: string | Uint8Array): SeqRecord[];
183
+
184
+ /**
185
+ * GFA (Graphical Fragment Assembly, `.gfa`) reader — sequence extraction.
186
+ *
187
+ * Assembly / pangenome graphs. Only Segment (`S`) lines carry sequence; links, paths, jumps and
188
+ * containments are graph topology and hold none. Both dialects are supported by field position:
189
+ *
190
+ * GFA1: S <name> <sequence> [tags…]
191
+ * GFA2: S <sid> <slen> <sequence> [tags…]
192
+ *
193
+ * GFA2 inserts an integer segment length between the name and the sequence, so when the field after
194
+ * the name is a bare integer AND another field follows, the sequence is that next field; otherwise
195
+ * it's the field right after the name (GFA1). A `*` sequence (a segment declared without residues)
196
+ * is skipped — there's nothing to pick. Lenient: never throws; malformed lines are ignored.
197
+ */
198
+
199
+ declare function parseGfa(input: string | Uint8Array): SeqRecord[];
200
+
201
+ /**
202
+ * GFF3 (`.gff`/`.gff3`) reader — sequence extraction.
203
+ *
204
+ * A GFF3 file is annotation (feature coordinates), which carries NO sequence — except when it
205
+ * embeds a FASTA section after a `##FASTA` directive. This reader returns the records of that
206
+ * embedded FASTA and nothing else; a GFF with no `##FASTA` section yields `[]` (there is no
207
+ * sequence to pick). Feature lines are never turned into sequence.
208
+ */
209
+
210
+ declare function parseGff(input: string | Uint8Array): SeqRecord[];
211
+
212
+ /**
213
+ * Multiple-sequence-alignment readers — one aligned row = one record.
214
+ *
215
+ * Covers the common alignment formats: Clustal (`.aln`), Stockholm (`.sto`/`.stk`),
216
+ * PHYLIP (`.phy`), NEXUS (`.nex`) and GCG/MSF (`.msf`). Each returns the alignment's rows
217
+ * as {@link SeqRecord}s: `id` = the taxon/sequence name, `sequence` = that row **with its
218
+ * gap characters preserved** (an aligned row is data; de-gapping is a caller's choice).
219
+ * Only line spacing and wrap are removed. No description field — these formats don't carry
220
+ * a per-row one.
221
+ *
222
+ * Deliberately lenient (see AGENTS.md): never throws, best-effort on malformed input, and
223
+ * always returns every row it can. Interleaved blocks are accumulated by name.
224
+ */
225
+
226
+ /** Read a Clustal (`.aln`) alignment. Also handles the Clustal-format output of MUSCLE, MAFFT, etc. */
227
+ declare function parseClustal(input: string | Uint8Array): SeqRecord[];
228
+ /** Read a Stockholm (`.sto`/`.stk`) alignment; multiple `//`-separated alignments are all returned. */
229
+ declare function parseStockholm(input: string | Uint8Array): SeqRecord[];
230
+ /**
231
+ * Read a PHYLIP (`.phy`) alignment. Supports relaxed (whitespace-delimited names) interleaved
232
+ * and single-block layouts — the common modern output (RAxML/PhyML/aligners). The first line is
233
+ * `<ntax> <nchar>`; the next `ntax` non-blank lines carry names + the first block; any further
234
+ * non-blank lines are interleaved continuation, appended round-robin and clipped at `nchar` so a
235
+ * stray line can't overrun residues into another taxon.
236
+ *
237
+ * Limitation: multi-line *sequential* PHYLIP (each taxon's whole sequence spanning consecutive
238
+ * lines before the next taxon) is read as interleaved and would be misassigned; it is rare next to
239
+ * interleaved output. Single-line sequential (one line per taxon) reads correctly.
240
+ */
241
+ declare function parsePhylip(input: string | Uint8Array): SeqRecord[];
242
+ /**
243
+ * Read a NEXUS (`.nex`) DATA/CHARACTERS block's MATRIX. Handles interleaved matrices (names
244
+ * repeat across blocks), space-grouped rows, and a final row that closes the matrix with `;`.
245
+ *
246
+ * Not resolved (kept verbatim / unsupported): `FORMAT MATCHCHAR=.` — a `.` meaning "same residue
247
+ * as the first taxon here" is left literal rather than substituted; and label-less matrices
248
+ * (`FORMAT LABELS=NO`, relying on TAXLABELS order) whose rows carry no name are skipped.
249
+ */
250
+ declare function parseNexus(input: string | Uint8Array): SeqRecord[];
251
+ /** Read a GCG/MSF (`.msf`) alignment (the sequence blocks after the header's `//`). */
252
+ declare function parseMsf(input: string | Uint8Array): SeqRecord[];
253
+
254
+ /**
255
+ * PIR / NBRF (`.pir`) reader — sequence extraction.
256
+ *
257
+ * A PIR record is: a header `>XX;identifier` (the two-letter code XX is the sequence type —
258
+ * P1/F1 protein, DL/DC DNA, RL/RC RNA, N1/N3 nucleotide, XX other), a free-text title line,
259
+ * then the residues, terminated by `*`. One file may hold many records.
260
+ * - id: the identifier after the `;` (or the whole header when there is no `;`).
261
+ * - description: the title line.
262
+ * - sequence: the residues with spacing removed and the single trailing `*` terminator dropped.
263
+ *
264
+ * Deliberately lenient (see AGENTS.md): never throws; a truncated record (no `*`) keeps its
265
+ * residues; the first line after a header is taken as the title.
266
+ */
267
+
268
+ declare function parsePir(input: string | Uint8Array): SeqRecord[];
269
+
270
+ /**
271
+ * BAM (`.bam`) reader — read-sequence extraction from the binary alignment format.
272
+ *
273
+ * BAM is the binary twin of SAM. On disk it is BGZF-compressed (a gzip stream of concatenated
274
+ * blocks); this reader expects the INFLATED bytes — starting with the "BAM\1" magic. The caller
275
+ * peels the gzip/BGZF wrapper first (a gzip decompressor decodes BGZF's concatenated members), so
276
+ * this stays a synchronous, dependency-free binary parser.
277
+ *
278
+ * Semantics mirror the SAM reader exactly (see {@link parseSam}): one sequence per read (secondary
279
+ * 0x100 / supplementary 0x800 skipped), reverse-strand sequence stored verbatim (reference-forward),
280
+ * id = read name (+ /1,/2 for paired mates), description = "RNAME:POS (+/-)" or "unmapped". Records
281
+ * without a stored sequence (l_seq = 0) are skipped. Lenient: on any truncation or garble it stops
282
+ * and returns what it parsed cleanly, never throwing.
283
+ */
284
+
285
+ declare function parseBam(bytes: Uint8Array): SeqRecord[];
286
+
287
+ /**
288
+ * SAM (`.sam`) reader — read-sequence extraction.
289
+ *
290
+ * SAM is a read-alignment format: one record per alignment, tab-delimited, with 11 mandatory
291
+ * fields (QNAME FLAG RNAME POS MAPQ CIGAR RNEXT PNEXT TLEN SEQ QUAL). This reader returns each
292
+ * record's read sequence — field 10, `SEQ`. Records whose SEQ is `*` (sequence not stored) are
293
+ * skipped: there's nothing to pick.
294
+ *
295
+ * The sequence is returned VERBATIM as written. For a reverse-strand alignment (FLAG bit 0x10) SAM
296
+ * already stores the reverse complement (reference-forward orientation), so that reference-oriented
297
+ * sequence is what you get — it is deliberately not un-flipped to the original read orientation.
298
+ *
299
+ * One sequence per read: secondary (FLAG 0x100) and supplementary (0x800) alignments are skipped —
300
+ * they re-map the same read (a duplicate, or a hard-clipped split fragment), which would pollute a
301
+ * "pick the sequences" list. What's kept is the read's SEQ from its primary (or unmapped) record —
302
+ * i.e. the sequence as SAM stores it, which for a hard-clipped primary alignment omits the clipped
303
+ * flanks rather than reconstructing the original full read.
304
+ *
305
+ * `@`-prefixed lines are skipped as headers — the SAM spec's QNAME charset `[!-?A-~]` excludes '@'
306
+ * (0x40) precisely so a read name can never be confused with a header. Lenient: never throws; lines
307
+ * with fewer than 11 fields are ignored rather than rejected.
308
+ */
309
+
310
+ declare function parseSam(input: string | Uint8Array): SeqRecord[];
311
+
312
+ export { type FastaRecord, type FastqRecord, MAX_PHRED, type QualRecord, type SeqFileFormat, type SeqRecord, type WrapOptions, detectFormat, formatFasta, formatFastq, formatQual, hasUsableQuality, makeSeqRecord, parseBam, parseClustal, parseEmbl, parseFasta, parseFastq, parseGenbank, parseGfa, parseGff, parseMsf, parseNexus, parsePhylip, parsePir, parseSam, parseStockholm, parseSwissprot };