Skip to content

Commit

Permalink
Eslint 9 native config
Browse files Browse the repository at this point in the history
  • Loading branch information
cmdcolin committed Aug 29, 2024
1 parent 431ccc4 commit 27e0422
Show file tree
Hide file tree
Showing 36 changed files with 433 additions and 625 deletions.
95 changes: 49 additions & 46 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -1,63 +1,45 @@
import prettier from 'eslint-plugin-prettier'
import typescriptEslint from '@typescript-eslint/eslint-plugin'
import tsParser from '@typescript-eslint/parser'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import js from '@eslint/js'
import { FlatCompat } from '@eslint/eslintrc'
import eslint from '@eslint/js'
import eslintPluginUnicorn from 'eslint-plugin-unicorn'
import tseslint from 'typescript-eslint'

const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all,
})

export default [
...compat.extends(
'plugin:@typescript-eslint/recommended',
'plugin:@typescript-eslint/recommended-type-checked',
'plugin:@typescript-eslint/stylistic-type-checked',
'plugin:prettier/recommended',
'plugin:unicorn/recommended',
),
export default tseslint.config(
{
ignores: ['esm/**/*', 'dist/**/*', '*.js', '*.mjs', 'example/*'],
},
{
plugins: {
prettier,
'@typescript-eslint': typescriptEslint,
},

languageOptions: {
parser: tsParser,
ecmaVersion: 5,
sourceType: 'script',

parserOptions: {
project: './tsconfig.lint.json',
project: ['./tsconfig.lint.json'],
tsconfigRootDir: import.meta.dirname,
},
},

},
eslint.configs.recommended,
...tseslint.configs.recommended,
...tseslint.configs.stylisticTypeChecked,
...tseslint.configs.strictTypeChecked,
eslintPluginUnicorn.configs['flat/recommended'],
{
rules: {
'@typescript-eslint/no-unused-vars': [
'warn',
{
argsIgnorePattern: '^_',
ignoreRestSiblings: true,
},
],
'no-empty': 'off',
'no-console': [
'warn',
{
allow: ['error', 'warn'],
},
],
'no-underscore-dangle': 0,
'no-underscore-dangle': 'off',
curly: 'error',
'@typescript-eslint/no-explicit-any': 0,
'@typescript-eslint/explicit-module-boundary-types': 0,
'@typescript-eslint/ban-ts-comment': 0,
semi: ['error', 'never'],
'spaced-comment': [
'error',
'always',
{
markers: ['/'],
},
],

'unicorn/prefer-structured-clone': 'off',
'unicorn/no-new-array': 'off',
'unicorn/no-empty-file': 'off',
'unicorn/prefer-type-error': 'off',
Expand Down Expand Up @@ -101,15 +83,36 @@ export default [
'unicorn/prefer-at': 'off',
'unicorn/prefer-string-replace-all': 'off',
'unicorn/no-array-reduce': 'off',

'@typescript-eslint/no-deprecated': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/no-unnecessary-type-parameters': 'off',
'@typescript-eslint/no-misused-promises': 'off',
'@typescript-eslint/no-base-to-string': 'off',
'@typescript-eslint/no-unsafe-member-access': 'off',
'@typescript-eslint/no-unsafe-argument': 'off',
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/restrict-plus-operands': 'off',
'@typescript-eslint/no-unsafe-call': 'off',
'@typescript-eslint/no-unsafe-return': 'off',
'@typescript-eslint/prefer-nullish-coalescing': 'off',
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/require-await': 'off',
'@typescript-eslint/restrict-template-expressions': 'off',
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/no-extraneous-class': 'off',
'@typescript-eslint/unbound-method': 'off',
'@typescript-eslint/no-dynamic-delete': 'off',
'@typescript-eslint/no-unused-vars': [
'warn',
{
argsIgnorePattern: '^_',
ignoreRestSiblings: true,
caughtErrors: 'none',
},
],
},
},
]
)
139 changes: 68 additions & 71 deletions src/craiIndex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { CramMalformedError } from './errors'
import { CramFileSource } from './cramFile/file'
import { Filehandle } from './cramFile/filehandle'

const BAI_MAGIC = 21578050 // BAI\1
const BAI_MAGIC = 21_578_050 // BAI\1

export interface Slice {
start: number
Expand All @@ -16,33 +16,38 @@ export interface Slice {
sliceBytes: number
}

type ParsedIndex = Record<string, Slice[]>
type ParsedIndex = Record<string, Slice[] | undefined>

function addRecordToIndex(index: ParsedIndex, record: number[]) {
const [seqId, start, span, containerStart, sliceStart, sliceBytes] = record

if (!index[seqId]) {
index[seqId] = []
const s = seqId!
if (!index[s]) {
index[s] = []
}

index[seqId].push({
start,
span,
containerStart,
sliceStart,
sliceBytes,
index[s].push({
start: start!,
span: span!,
containerStart: containerStart!,
sliceStart: sliceStart!,
sliceBytes: sliceBytes!,
})
}

export default class CraiIndex {
// A CRAM index (.crai) is a gzipped tab delimited file containing the following columns:
// A CRAM index (.crai) is a gzipped tab delimited file containing the
// following columns:
//
// 1. Sequence id
// 2. Alignment start
// 3. Alignment span
// 4. Container start byte position in the file
// 5. Slice start byte position in the container data (‘blocks’)
// 6. Slice size in bytes
// Each line represents a slice in the CRAM file. Please note that all slices must be listed in index file.
//
// Each line represents a slice in the CRAM file. Please note that all slices
// must be listed in index file.
private _parseCache: AbortablePromiseCache<unknown, ParsedIndex>
private filehandle: Filehandle

Expand All @@ -61,68 +66,60 @@ export default class CraiIndex {
})
}

parseIndex() {
async parseIndex() {
const index: ParsedIndex = {}
return this.filehandle
.readFile()
.then(data => {
if (data[0] === 31 && data[1] === 139) {
return unzip(data)
}
return data
})
.then(uncompressedBuffer => {
if (
uncompressedBuffer.length > 4 &&
uncompressedBuffer.readUInt32LE(0) === BAI_MAGIC
) {
throw new CramMalformedError(
'invalid .crai index file. note: file appears to be a .bai index. this is technically legal but please open a github issue if you need support',
)
}
// interpret the text as regular ascii, since it is
// supposed to be only digits and whitespace characters
// this is written in a deliberately low-level fashion for performance,
// because some .crai files can be pretty large.
let currentRecord: number[] = []
let currentString = ''
for (const charCode of uncompressedBuffer) {
if (
(charCode >= 48 && charCode <= 57) /* 0-9 */ ||
(!currentString && charCode === 45) /* leading - */
) {
currentString += String.fromCharCode(charCode)
} else if (charCode === 9 /* \t */) {
currentRecord.push(Number.parseInt(currentString, 10))
currentString = ''
} else if (charCode === 10 /* \n */) {
currentRecord.push(Number.parseInt(currentString, 10))
currentString = ''
addRecordToIndex(index, currentRecord)
currentRecord = []
} else if (charCode !== 13 /* \r */ && charCode !== 32 /* space */) {
// if there are other characters in the file besides
// space and \r, something is wrong.
throw new CramMalformedError('invalid .crai index file')
}
}
const data = await this.filehandle.readFile()
const uncompressedBuffer =
data[0] === 31 && data[1] === 139 ? unzip(data) : data
if (
uncompressedBuffer.length > 4 &&
uncompressedBuffer.readUInt32LE(0) === BAI_MAGIC
) {
throw new CramMalformedError(
'invalid .crai index file. note: file appears to be a .bai index. this is technically legal but please open a github issue if you need support',
)
}
// interpret the text as regular ascii, since it is
// supposed to be only digits and whitespace characters
// this is written in a deliberately low-level fashion for performance,
// because some .crai files can be pretty large.
let currentRecord: number[] = []
let currentString = ''
for (const charCode of uncompressedBuffer) {
if (
(charCode >= 48 && charCode <= 57) /* 0-9 */ ||
(!currentString && charCode === 45) /* leading - */
) {
currentString += String.fromCharCode(charCode)
} else if (charCode === 9 /* \t */) {
currentRecord.push(Number.parseInt(currentString, 10))
currentString = ''
} else if (charCode === 10 /* \n */) {
currentRecord.push(Number.parseInt(currentString, 10))
currentString = ''
addRecordToIndex(index, currentRecord)
currentRecord = []
} else if (charCode !== 13 /* \r */ && charCode !== 32 /* space */) {
// if there are other characters in the file besides
// space and \r, something is wrong.
throw new CramMalformedError('invalid .crai index file')
}
}

// if the file ends without a \n, we need to flush our buffers
if (currentString) {
currentRecord.push(Number.parseInt(currentString, 10))
}
if (currentRecord.length === 6) {
addRecordToIndex(index, currentRecord)
}
// if the file ends without a \n, we need to flush our buffers
if (currentString) {
currentRecord.push(Number.parseInt(currentString, 10))
}
if (currentRecord.length === 6) {
addRecordToIndex(index, currentRecord)
}

// sort each of them by start
Object.entries(index).forEach(([seqId, ent]) => {
index[seqId] = ent.sort(
(a, b) => a.start - b.start || a.span - b.span,
)
})
return index
})
// sort each of them by start
Object.entries(index).forEach(([seqId, ent]) => {
const e2 = ent!
index[seqId] = e2.sort((a, b) => a.start - b.start || a.span - b.span)
})
return index
}

getIndex(opts: { signal?: AbortSignal } = {}) {
Expand Down
11 changes: 3 additions & 8 deletions src/cramFile/codecs/byteArrayLength.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,6 @@ export default class ByteArrayStopCodec extends CramCodec<
) {
super(parameters, dataType)
this.instantiateCodec = instantiateCodec
if (dataType !== 'byteArray') {
throw new TypeError(
`byteArrayLength does not support data type ${dataType}`,
)
}
}

decode(
Expand Down Expand Up @@ -71,6 +66,6 @@ export default class ByteArrayStopCodec extends CramCodec<
}
}

'_getLengthCodec _getDataCodec'
.split(' ')
.forEach(method => tinyMemoize(ByteArrayStopCodec, method))
'_getLengthCodec _getDataCodec'.split(' ').forEach(method => {
tinyMemoize(ByteArrayStopCodec, method)
})
12 changes: 0 additions & 12 deletions src/cramFile/codecs/byteArrayStop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,6 @@ export default class ByteArrayStopCodec extends CramCodec<
'byteArray',
ByteArrayStopCramEncoding['parameters']
> {
constructor(
parameters: ByteArrayStopCramEncoding['parameters'],
dataType: 'byteArray',
) {
super(parameters, dataType)
if (dataType !== 'byteArray') {
throw new TypeError(
`byteArrayStop codec does not support data type ${dataType}`,
)
}
}

decode(
slice: CramSlice,
coreDataBlock: CramFileBlock,
Expand Down
3 changes: 1 addition & 2 deletions src/cramFile/codecs/external.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/unbound-method */
import { CramMalformedError, CramUnimplementedError } from '../../errors'
import CramCodec, { Cursor, Cursors } from './_base'
import { parseItf8 } from '../util'
Expand Down Expand Up @@ -64,6 +63,6 @@ export default class ExternalCodec extends CramCodec<
'attempted to read beyond end of block. this file seems truncated.',
)
}
return contentBlock.content[cursor.bytePosition++]
return contentBlock.content[cursor.bytePosition++]!
}
}
2 changes: 1 addition & 1 deletion src/cramFile/codecs/getBits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function getBits(
for (let dlen = numBits; dlen; dlen--) {
// get the next `dlen` bits in the input, put them in val
val <<= 1
val |= (data[cursor.bytePosition] >> cursor.bitPosition) & 1
val |= (data[cursor.bytePosition]! >> cursor.bitPosition) & 1
cursor.bitPosition -= 1
if (cursor.bitPosition < 0) {
cursor.bytePosition += 1
Expand Down
Loading

0 comments on commit 27e0422

Please sign in to comment.