chore(lint): fix lint warnings, TS errors, and husky deprecation

- Update husky hooks to modern format (remove deprecated sourcing)
- Fix Uint8Array to BufferSource type errors in spec files
- Remove 28 unused eslint-disable directives across 18 files
This commit is contained in:
Johannes Millan 2026-01-10 17:55:23 +01:00
parent 004c10586b
commit 6cb6aca6d9
27 changed files with 5 additions and 40 deletions

View file

@ -1,4 +1 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npx --no-install pretty-quick --staged && npm run lint

View file

@ -1,4 +1 @@
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm run lint && npm run test

View file

@ -1,5 +1,3 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { ActionType } from '../../../../op-log/core/action-types.enum';
/**

View file

@ -37,9 +37,7 @@ const DEFERRED_INIT_DELAY_MS = 1000;
providedIn: 'root',
})
export class StartupService {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
private _imexMetaService = inject(ImexViewService);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
private _translateService = inject(TranslateService);
private _localBackupService = inject(LocalBackupService);
private _globalConfigService = inject(GlobalConfigService);

View file

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { createAction } from '@ngrx/store';
import { BoardCfg, BoardPanelCfg } from '../boards.model';
import { PersistentActionMeta } from '../../../op-log/core/persistent-action.interface';

View file

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import { TestBed } from '@angular/core/testing';
import { provideMockActions } from '@ngrx/effects/testing';
import { provideMockStore, MockStore } from '@ngrx/store/testing';

View file

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { TestBed } from '@angular/core/testing';
import { provideMockStore, MockStore } from '@ngrx/store/testing';
import { StateSnapshotService } from './state-snapshot.service';

View file

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { OperationCaptureService } from './operation-capture.service';
import { OpType, EntityType } from '../core/operation.types';
import { PersistentAction } from '../core/persistent-action.interface';

View file

@ -1,5 +1,3 @@
/* eslint-disable @typescript-eslint/naming-convention */
/**
* CRITICAL: These string values are IMMUTABLE.
*

View file

@ -14,7 +14,6 @@ export interface PersistentActionMeta {
export interface PersistentAction extends Action {
type: string; // Standard NgRx action type
meta: PersistentActionMeta;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any; // Dynamic payload properties (NgRx action payloads)
}

View file

@ -42,7 +42,6 @@ export interface ModelCfg<T extends ModelBase> {
cacheOnLoad?: boolean;
validate?: <R>(data: R | T) => IValidation<R | T>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
repair?: (data: any) => T; // any is intentional: repair handles malformed data
defaultData?: T;

View file

@ -126,7 +126,7 @@ describe('compression-handler', () => {
// Decompress using DecompressionStream (same API used by server-side Node.js zlib)
const stream = new DecompressionStream('gzip');
const writer = stream.writable.getWriter();
writer.write(compressed);
writer.write(compressed as BufferSource);
writer.close();
const decompressed = await new Response(stream.readable).arrayBuffer();
const decoded = new TextDecoder().decode(decompressed);

View file

@ -322,7 +322,6 @@ export class OperationLogStoreService {
let storedEntries: StoredOperationLogEntry[];
try {
// Type assertion needed for compound index key - idb's types don't fully support this
// eslint-disable-next-line @typescript-eslint/no-explicit-any
storedEntries = await this.db.getAllFromIndex(
STORE_NAMES.OPS,
OPS_INDEXES.BY_SOURCE_AND_STATUS,
@ -621,7 +620,6 @@ export class OperationLogStoreService {
let storedEntries: StoredOperationLogEntry[];
try {
// Type assertion needed for compound index key - idb's types don't fully support this
// eslint-disable-next-line @typescript-eslint/no-explicit-any
storedEntries = await this.db.getAllFromIndex(
STORE_NAMES.OPS,
OPS_INDEXES.BY_SOURCE_AND_STATUS,

View file

@ -136,7 +136,6 @@ describe('FileBasedSyncAdapterService', () => {
mockStateSnapshotService = jasmine.createSpyObj('StateSnapshotService', [
'getStateSnapshot',
]);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
mockStateSnapshotService.getStateSnapshot.and.returnValue({
tasks: [],
projects: [],

View file

@ -430,7 +430,6 @@ describe('WebdavApi', () => {
await api.upload({ path: '/test.json', data: 'test', expectedRev: null });
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const requestArgs = mockHttpAdapter.request.calls.mostRecent()?.args[0] as any;
expect(requestArgs).toBeDefined();
expect(requestArgs.headers['If-Unmodified-Since']).toBeUndefined();
@ -446,7 +445,6 @@ describe('WebdavApi', () => {
await api.upload({ path: '/test.json', data: 'test' });
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const requestArgs = mockHttpAdapter.request.calls.mostRecent()?.args[0] as any;
expect(requestArgs).toBeDefined();
expect(requestArgs.headers['If-Unmodified-Since']).toBeUndefined();
@ -467,7 +465,6 @@ describe('WebdavApi', () => {
isForceOverwrite: true,
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const requestArgs = mockHttpAdapter.request.calls.mostRecent()?.args[0] as any;
expect(requestArgs).toBeDefined();
expect(requestArgs.headers['If-Unmodified-Since']).toBeUndefined();

View file

@ -12,7 +12,7 @@ import { SyncOperation } from '../provider.interface';
const decompressGzip = async (compressed: Uint8Array): Promise<string> => {
const stream = new DecompressionStream('gzip');
const writer = stream.writable.getWriter();
writer.write(compressed);
writer.write(compressed as BufferSource);
writer.close();
const decompressed = await new Response(stream.readable).arrayBuffer();
return new TextDecoder().decode(decompressed);
@ -1019,7 +1019,7 @@ describe('SuperSyncProvider', () => {
expect(capturedBody).not.toBeNull();
const stream = new DecompressionStream('gzip');
const writer = stream.writable.getWriter();
writer.write(capturedBody!);
writer.write(capturedBody! as BufferSource);
writer.close();
const decompressed = await new Response(stream.readable).arrayBuffer();
const payload = JSON.parse(new TextDecoder().decode(decompressed));
@ -1085,7 +1085,7 @@ describe('SuperSyncProvider', () => {
const body = fetchSpy.calls.mostRecent().args[1].body as Uint8Array;
const stream = new DecompressionStream('gzip');
const writer = stream.writable.getWriter();
writer.write(body);
writer.write(body as BufferSource);
writer.close();
const decompressed = await new Response(stream.readable).arrayBuffer();
const payload = JSON.parse(new TextDecoder().decode(decompressed));

View file

@ -632,7 +632,6 @@ export class ConflictResolutionService {
// this to MemoizedSelectorWithProps<State, {id: string}, T>. This is a
// known NgRx typing limitation. Runtime behavior is correct.
return await firstValueFrom(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
this.store.select(config.selectById as any, { id: entityId }),
);
}

View file

@ -584,7 +584,6 @@ describe('LockService', () => {
it('should pass callback to navigator.locks.request', async () => {
let callbackExecutedInLock = false;
const locksSpy = spyOn(navigator.locks, 'request').and.callFake(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async (_name: string, callback: any) => {
callbackExecutedInLock = true;
return callback(null);

View file

@ -47,7 +47,6 @@ export class LockService {
);
return this._fallbackRequest(lockName, callback);
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return navigator.locks.request(lockName, callback);
}

View file

@ -1,4 +1,4 @@
/* eslint-disable @typescript-eslint/naming-convention, @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/naming-convention */
import { TestBed } from '@angular/core/testing';
import { provideMockStore, MockStore } from '@ngrx/store/testing';
import { ServerMigrationService } from './server-migration.service';

View file

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/naming-convention */
/**
* Integration tests for LWW Update operations and store application.
*

View file

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { OperationCaptureService } from '../../capture/operation-capture.service';
import {
PersistentAction,

View file

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type,@typescript-eslint/naming-convention */
import { issueProviderSharedMetaReducer } from './issue-provider-shared.reducer';
import { TaskSharedActions } from '../task-shared.actions';
import { TASK_FEATURE_NAME } from '../../../features/tasks/store/task.reducer';

View file

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type,@typescript-eslint/naming-convention */
import { shortSyntaxSharedMetaReducer } from './short-syntax-shared.reducer';
import { RootState } from '../../root-state';
import { Task } from '../../../features/tasks/task.model';

View file

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type,@typescript-eslint/naming-convention */
import { taskRepeatCfgSharedMetaReducer } from './task-repeat-cfg-shared.reducer';
import { TaskSharedActions } from '../task-shared.actions';
import { TASK_FEATURE_NAME } from '../../../features/tasks/store/task.reducer';

View file

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type,@typescript-eslint/naming-convention */
import {
undoTaskDeleteMetaReducer,
getLastDeletePayload,

View file

@ -18,7 +18,6 @@ import { Action } from '@ngrx/store';
* );
* ```
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const filterLocalAction = <T extends Action>(): OperatorFunction<T, T> =>
filter((action: T) => !(action as any).meta?.isRemote);
@ -39,6 +38,5 @@ export const filterLocalAction = <T extends Action>(): OperatorFunction<T, T> =>
* );
* ```
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const filterRemoteAction = <T extends Action>(): OperatorFunction<T, T> =>
filter((action: T) => !!(action as any).meta?.isRemote);