ci: fix eslint config, add missing ts-eslint devDeps, format src

- Add @typescript-eslint/parser and @typescript-eslint/eslint-plugin to
  devDependencies (required by eslint.config.mjs direct imports and by
  @acamarata/eslint-config peerDependencies)
- Fix eslint.config.mjs: scope files to src/**/*.ts, add parserOptions.project
  for type-aware rules, expand ignores to cover coverage/ and docs/
- Run prettier --write src/ to fix format:check failures
This commit is contained in:
Aric Camarata 2026-05-31 08:47:31 -04:00
parent 680bc72c19
commit 6caa9eed2c
10 changed files with 95 additions and 80 deletions

View file

@ -5,12 +5,19 @@ import { typescript } from '@acamarata/eslint-config';
export default [
{
plugins: { '@typescript-eslint': tsPlugin },
languageOptions: { parser: tsParser },
ignores: ['dist/**', 'node_modules/**', 'coverage/**', 'docs/**'],
},
...typescript,
eslintConfigPrettier,
{
ignores: ['dist/', 'node_modules/', '*.cjs', '*.mjs'],
files: ['src/**/*.ts'],
plugins: { '@typescript-eslint': tsPlugin },
languageOptions: {
parser: tsParser,
parserOptions: {
project: './tsconfig.json',
tsconfigRootDir: import.meta.dirname,
},
},
},
...typescript.map((cfg) => ({ ...cfg, files: ['src/**/*.ts'] })),
eslintConfigPrettier,
];

View file

@ -60,6 +60,8 @@
"@acamarata/tsconfig": "^0.1.0",
"@eslint/js": "^10.0.1",
"@types/node": "^22.15.0",
"@typescript-eslint/eslint-plugin": "^8.56.1",
"@typescript-eslint/parser": "^8.56.1",
"c8": "^10.1.0",
"eslint": "^10.0.3",
"eslint-config-prettier": "^10.1.8",

View file

@ -23,6 +23,12 @@ importers:
'@types/node':
specifier: ^22.15.0
version: 22.15.0
'@typescript-eslint/eslint-plugin':
specifier: ^8.56.1
version: 8.56.1(@typescript-eslint/parser@8.56.1(eslint@10.0.3)(typescript@5.9.3))(eslint@10.0.3)(typescript@5.9.3)
'@typescript-eslint/parser':
specifier: ^8.56.1
version: 8.56.1(eslint@10.0.3)(typescript@5.9.3)
c8:
specifier: ^10.1.0
version: 10.1.3

View file

@ -1,4 +1,4 @@
import type { HijriYearRecord } from '../types';
import type { HijriYearRecord } from "../types";
// Umm al-Qura reference table: Hijri years 1318-1501.
// Each entry records the 1 Muharram Gregorian date and a 12-bit days-per-month

View file

@ -7,9 +7,9 @@
// New moon times come from Jean Meeus, Astronomical Algorithms (2nd ed.),
// Chapter 49, accurate to within a few minutes for 1000-3000 CE.
import { hDatesTable } from '../data/hDates';
import { MS_PER_DAY, MONTHS_PER_YEAR } from '../constants';
import type { CalendarEngine, HijriDate } from '../types';
import { hDatesTable } from "../data/hDates";
import { MS_PER_DAY, MONTHS_PER_YEAR } from "../constants";
import type { CalendarEngine, HijriDate } from "../types";
// ─── Constants ───────────────────────────────────────────────────────────────
@ -211,7 +211,7 @@ function fcnaDaysInMonth(hy: number, hm: number): number {
function fcnaToHijri(gregorianDate: Date): HijriDate | null {
if (!(gregorianDate instanceof Date) || isNaN(gregorianDate.getTime())) {
throw new Error('Invalid Gregorian date');
throw new Error("Invalid Gregorian date");
}
// FCNA criterion is UTC-based, so UTC date components ensure correct round-trips.
@ -271,7 +271,7 @@ function fcnaIsValid(hy: number, hm: number, hd: number): boolean {
// ─── Engine export ────────────────────────────────────────────────────────────
export const fcnaEngine: CalendarEngine = {
id: 'fcna',
id: "fcna",
toHijri: fcnaToHijri,
toGregorian: fcnaToGregorian,
isValid: fcnaIsValid,

View file

@ -4,9 +4,9 @@
// (Gregorian 1900-2076). Each entry records the Gregorian date of 1 Muharram and
// a 12-bit days-per-month bitmask. Dates outside that window return null.
import { hDatesTable } from '../data/hDates';
import { MS_PER_DAY, MONTHS_PER_YEAR } from '../constants';
import type { CalendarEngine, HijriDate, HijriYearRecord } from '../types';
import { hDatesTable } from "../data/hDates";
import { MS_PER_DAY, MONTHS_PER_YEAR } from "../constants";
import type { CalendarEngine, HijriDate, HijriYearRecord } from "../types";
/**
* Binary search for a Hijri year entry in the UAQ table.
@ -38,7 +38,7 @@ function findYearEntry(hy: number): HijriYearRecord | null {
// the calendar-date lookup is timezone-safe regardless of the host environment.
function uaqToHijri(date: Date): HijriDate | null {
if (!(date instanceof Date) || isNaN(date.getTime())) {
throw new Error('Invalid Gregorian date');
throw new Error("Invalid Gregorian date");
}
const inputUtc = Date.UTC(date.getFullYear(), date.getMonth(), date.getDate());
@ -126,7 +126,7 @@ function uaqDaysInMonth(hy: number, hm: number): number {
}
export const uaqEngine: CalendarEngine = {
id: 'uaq',
id: "uaq",
toHijri: uaqToHijri,
toGregorian: uaqToGregorian,
isValid: uaqIsValid,

View file

@ -1,32 +1,32 @@
// Built-in engines are registered at module load so that 'uaq' and 'fcna' are
// available immediately on import. This module-level side effect is intentional
// and documented in the sideEffects field of package.json.
import { uaqEngine } from './engines/uaq';
import { fcnaEngine } from './engines/fcna';
import { registerCalendar } from './registry';
import { uaqEngine } from "./engines/uaq";
import { fcnaEngine } from "./engines/fcna";
import { registerCalendar } from "./registry";
registerCalendar('uaq', uaqEngine);
registerCalendar('fcna', fcnaEngine);
registerCalendar("uaq", uaqEngine);
registerCalendar("fcna", fcnaEngine);
// Registry
export { registerCalendar, getCalendar, listCalendars } from './registry';
export { registerCalendar, getCalendar, listCalendars } from "./registry";
// Constants
export { MS_PER_DAY, MONTHS_PER_YEAR } from './constants';
export { MS_PER_DAY, MONTHS_PER_YEAR } from "./constants";
// Types
export type { HijriDate, HijriYearRecord, CalendarEngine, ConversionOptions } from './types';
export type { HijriDate, HijriYearRecord, CalendarEngine, ConversionOptions } from "./types";
// Data
export { hDatesTable } from './data/hDates';
export { hDatesTable } from "./data/hDates";
// Names
export { hmLong, hmMedium, hmShort } from './names/months';
export { hwLong, hwShort, hwNumeric } from './names/weekdays';
export { hmLong, hmMedium, hmShort } from "./names/months";
export { hwLong, hwShort, hwNumeric } from "./names/weekdays";
// Convenience wrappers
import { getCalendar } from './registry';
import type { HijriDate, ConversionOptions } from './types';
import { getCalendar } from "./registry";
import type { HijriDate, ConversionOptions } from "./types";
/**
* Convert a Gregorian date to a Hijri date.
@ -41,9 +41,9 @@ import type { HijriDate, ConversionOptions } from './types';
*/
export function toHijri(date: Date, options?: ConversionOptions): HijriDate | null {
if (!(date instanceof Date) || isNaN(date.getTime())) {
throw new Error('Invalid Gregorian date');
throw new Error("Invalid Gregorian date");
}
return getCalendar(options?.calendar ?? 'uaq').toHijri(date);
return getCalendar(options?.calendar ?? "uaq").toHijri(date);
}
/**
@ -63,7 +63,7 @@ export function toGregorian(
hd: number,
options?: ConversionOptions,
): Date | null {
return getCalendar(options?.calendar ?? 'uaq').toGregorian(hy, hm, hd);
return getCalendar(options?.calendar ?? "uaq").toGregorian(hy, hm, hd);
}
/**
@ -81,7 +81,7 @@ export function isValidHijriDate(
hd: number,
options?: ConversionOptions,
): boolean {
return getCalendar(options?.calendar ?? 'uaq').isValid(hy, hm, hd);
return getCalendar(options?.calendar ?? "uaq").isValid(hy, hm, hd);
}
/**
@ -94,5 +94,5 @@ export function isValidHijriDate(
* @throws {RangeError} if the month or year is out of range
*/
export function daysInHijriMonth(hy: number, hm: number, options?: ConversionOptions): number {
return getCalendar(options?.calendar ?? 'uaq').daysInMonth(hy, hm);
return getCalendar(options?.calendar ?? "uaq").daysInMonth(hy, hm);
}

View file

@ -11,18 +11,18 @@
* const month = hmLong[hijriDate.hm - 1]; // "Ramadan"
*/
export const hmLong = [
'Muharram', // 1
'Safar', // 2
"Muharram", // 1
"Safar", // 2
"Rabi'l Awwal", // 3
"Rabi'l Thani", // 4
'Jumadal Awwal', // 5
'Jumadal Thani', // 6
'Rajab', // 7
"Jumadal Awwal", // 5
"Jumadal Thani", // 6
"Rajab", // 7
"Sha'ban", // 8
'Ramadan', // 9
'Shawwal', // 10
"Ramadan", // 9
"Shawwal", // 10
"Dhul Qi'dah", // 11
'Dhul Hijjah', // 12
"Dhul Hijjah", // 12
];
/**
@ -35,18 +35,18 @@ export const hmLong = [
* const label = hmMedium[hijriDate.hm - 1]; // "Ramadan"
*/
export const hmMedium = [
'Muharram',
'Safar',
'Rabi1',
'Rabi2',
'Jumada1',
'Jumada2',
'Rajab',
'Shaban',
'Ramadan',
'Shawwal',
'Dhul-Qidah',
'Dhul-Hijjah',
"Muharram",
"Safar",
"Rabi1",
"Rabi2",
"Jumada1",
"Jumada2",
"Rajab",
"Shaban",
"Ramadan",
"Shawwal",
"Dhul-Qidah",
"Dhul-Hijjah",
];
/**
@ -59,16 +59,16 @@ export const hmMedium = [
* const abbr = hmShort[hijriDate.hm - 1]; // "Ram"
*/
export const hmShort = [
'Muh',
'Saf',
'Ra1',
'Ra2',
'Ju1',
'Ju2',
'Raj',
'Shb',
'Ram',
'Shw',
'DhQ',
'DhH',
"Muh",
"Saf",
"Ra1",
"Ra2",
"Ju1",
"Ju2",
"Raj",
"Shb",
"Ram",
"Shw",
"DhQ",
"DhH",
];

View file

@ -11,13 +11,13 @@
* const dayName = hwLong[gregorianDate.getDay()]; // "Yawm al-Jum`a"
*/
export const hwLong = [
'Yawm al-Ahad', // Sunday
'Yawm al-Ithnayn', // Monday
"Yawm al-Ahad", // Sunday
"Yawm al-Ithnayn", // Monday
"Yawm ath-Thulatha'", // Tuesday
"Yawm al-Arba`a'", // Wednesday
'Yawm al-Khamis', // Thursday
'Yawm al-Jum`a', // Friday
'Yawm as-Sabt', // Saturday
"Yawm al-Khamis", // Thursday
"Yawm al-Jum`a", // Friday
"Yawm as-Sabt", // Saturday
];
/**
@ -30,13 +30,13 @@ export const hwLong = [
* const abbr = hwShort[gregorianDate.getDay()]; // "Jum`a"
*/
export const hwShort = [
'Ahad', // Sunday
'Ithn', // Monday
'Thul', // Tuesday
'Arba', // Wednesday
'Kham', // Thursday
'Jum`a', // Friday
'Sabt', // Saturday
"Ahad", // Sunday
"Ithn", // Monday
"Thul", // Tuesday
"Arba", // Wednesday
"Kham", // Thursday
"Jum`a", // Friday
"Sabt", // Saturday
];
/**

View file

@ -1,4 +1,4 @@
import type { CalendarEngine } from './types';
import type { CalendarEngine } from "./types";
const _engines = new Map<string, CalendarEngine>();
@ -25,7 +25,7 @@ export function registerCalendar(name: string, engine: CalendarEngine): void {
export function getCalendar(name: string): CalendarEngine {
const engine = _engines.get(name);
if (!engine) {
const available = listCalendars().join(', ');
const available = listCalendars().join(", ");
throw new Error(
`Unknown Hijri calendar: "${name}". Available: ${available}. Register custom calendars with registerCalendar().`,
);