superjs-core 0.3.2 → 0.3.3
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/date/index.js +9 -12
- package/dist/date/index.js.map +1 -1
- package/dist/index.js +11 -13
- package/dist/index.js.map +1 -1
- package/dist/math/index.js +2 -1
- package/dist/math/index.js.map +1 -1
- package/package.json +2 -1
package/dist/date/index.js
CHANGED
|
@@ -95,23 +95,20 @@ function parseDate(input) {
|
|
|
95
95
|
}
|
|
96
96
|
const dmyMatch = trimmed.match(/^(\d{1,2})[\/-](\d{1,2})[\/-](\d{4})$/);
|
|
97
97
|
if (dmyMatch) {
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
);
|
|
103
|
-
if (!isNaN(d.getTime())) return d;
|
|
98
|
+
const year = parseInt(dmyMatch[3], 10);
|
|
99
|
+
const month = parseInt(dmyMatch[2], 10) - 1;
|
|
100
|
+
const day = parseInt(dmyMatch[1], 10);
|
|
101
|
+
const d = new Date(year, month, day);
|
|
102
|
+
if (!isNaN(d.getTime()) && d.getMonth() === month && d.getDate() === day) return d;
|
|
104
103
|
}
|
|
105
104
|
const textMatch = trimmed.match(/^(\d{1,2})\s+([a-zA-Z]+)\s+(\d{4})$/);
|
|
106
105
|
if (textMatch) {
|
|
107
106
|
const monthIndex = MONTH_MAP[textMatch[2].toLowerCase()];
|
|
108
107
|
if (monthIndex !== void 0) {
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
);
|
|
114
|
-
if (!isNaN(d.getTime())) return d;
|
|
108
|
+
const year = parseInt(textMatch[3], 10);
|
|
109
|
+
const day = parseInt(textMatch[1], 10);
|
|
110
|
+
const d = new Date(year, monthIndex, day);
|
|
111
|
+
if (!isNaN(d.getTime()) && d.getMonth() === monthIndex && d.getDate() === day) return d;
|
|
115
112
|
}
|
|
116
113
|
}
|
|
117
114
|
const numMatch = trimmed.match(/^-?\d+$/);
|
package/dist/date/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/date/index.ts"],"sourcesContent":["/**\r\n * Error thrown when a date value is invalid.\r\n */\r\nexport class InvalidDateError extends Error {\r\n constructor(input: unknown) {\r\n super(`Invalid date: ${String(input)}`)\r\n this.name = 'InvalidDateError'\r\n }\r\n}\r\n\r\nexport interface DateDiff {\r\n years: number\r\n months: number\r\n days: number\r\n hours: number\r\n minutes: number\r\n seconds: number\r\n}\r\n\r\nconst MONTH_NAMES_SHORT = [\r\n 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\r\n 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',\r\n] as const\r\n\r\nconst MONTH_NAMES_FULL = [\r\n 'January', 'February', 'March', 'April', 'May', 'June',\r\n 'July', 'August', 'September', 'October', 'November', 'December',\r\n] as const\r\n\r\nconst MONTH_MAP: Record<string, number> = {\r\n jan: 0, january: 0,\r\n feb: 1, february: 1,\r\n mar: 2, march: 2,\r\n apr: 3, april: 3,\r\n may: 4,\r\n jun: 5, june: 5,\r\n jul: 6, july: 6,\r\n aug: 7, august: 7,\r\n sep: 8, september: 8,\r\n oct: 9, october: 9,\r\n nov: 10, november: 10,\r\n dec: 11, december: 11,\r\n}\r\n\r\n/**\r\n * Formats a Date to a string using the given format pattern.\r\n *\r\n * Supported tokens:\r\n * - `YYYY` — 4-digit year\r\n * - `YY` — 2-digit year\r\n * - `MMMM` — full month name\r\n * - `MMM` — abbreviated month name\r\n * - `MM` — 2-digit month (01–12)\r\n * - `DD` — 2-digit day (01–31)\r\n * - `HH` — 2-digit hours (00–23)\r\n * - `mm` — 2-digit minutes\r\n * - `ss` — 2-digit seconds\r\n * - `SSS` — milliseconds\r\n *\r\n * @param date - The date to format.\r\n * @param format - The format string (default `'YYYY-MM-DD'`).\r\n * @returns The formatted date string.\r\n */\r\nexport function formatDate(date: Date, format: string = 'YYYY-MM-DD'): string {\r\n const year = date.getFullYear()\r\n const month = date.getMonth()\r\n const day = date.getDate()\r\n const hours = date.getHours()\r\n const minutes = date.getMinutes()\r\n const seconds = date.getSeconds()\r\n const ms = date.getMilliseconds()\r\n\r\n const pad = (n: number, len: number = 2): string => String(n).padStart(len, '0')\r\n\r\n return format\r\n .replace(/YYYY/g, String(year))\r\n .replace(/YY/g, String(year).slice(-2))\r\n .replace(/MMMM/g, MONTH_NAMES_FULL[month]!)\r\n .replace(/MMM/g, MONTH_NAMES_SHORT[month]!)\r\n .replace(/MM/g, pad(month + 1))\r\n .replace(/DD/g, pad(day))\r\n .replace(/HH/g, pad(hours))\r\n .replace(/mm/g, pad(minutes))\r\n .replace(/ss/g, pad(seconds))\r\n .replace(/SSS/g, pad(ms, 3))\r\n}\r\n\r\n/**\r\n * Parses a date from a string, number (timestamp in ms), or Date object.\r\n *\r\n * Supported string formats:\r\n * - ISO (`YYYY-MM-DD`, `YYYY-MM-DDTHH:mm:ss`)\r\n * - `DD/MM/YYYY` or `DD-MM-YYYY`\r\n * - `DD MMM YYYY` or `DD MMMM YYYY`\r\n * - Unix timestamp (milliseconds)\r\n *\r\n * @param input - The value to parse.\r\n * @returns A valid Date object.\r\n * @throws {InvalidDateError} If the input cannot be parsed.\r\n */\r\nexport function parseDate(input: string | number | Date): Date {\r\n if (input instanceof Date) {\r\n if (isNaN(input.getTime())) throw new InvalidDateError(input)\r\n return new Date(input.getTime())\r\n }\r\n\r\n if (typeof input === 'number') {\r\n const d = new Date(input)\r\n if (isNaN(d.getTime())) throw new InvalidDateError(input)\r\n return d\r\n }\r\n\r\n const trimmed = input.trim()\r\n\r\n // ISO format: YYYY-MM-DD or YYYY-MM-DDTHH:mm:ss\r\n const isoMatch = trimmed.match(/^(\\d{4})-(\\d{2})-(\\d{2})(?:T(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?)?(?:Z|[+-]\\d{2}:?\\d{2})?$/)\r\n if (isoMatch) {\r\n const d = new Date(\r\n parseInt(isoMatch[1]!, 10),\r\n parseInt(isoMatch[2]!, 10) - 1,\r\n parseInt(isoMatch[3]!, 10),\r\n isoMatch[4] ? parseInt(isoMatch[4]!, 10) : 0,\r\n isoMatch[5] ? parseInt(isoMatch[5]!, 10) : 0,\r\n isoMatch[6] ? parseInt(isoMatch[6]!, 10) : 0,\r\n isoMatch[7] ? parseInt(isoMatch[7]!.padEnd(3, '0'), 10) : 0\r\n )\r\n if (!isNaN(d.getTime())) return d\r\n }\r\n\r\n // DD/MM/YYYY or DD-MM-YYYY\r\n const dmyMatch = trimmed.match(/^(\\d{1,2})[\\/-](\\d{1,2})[\\/-](\\d{4})$/)\r\n if (dmyMatch) {\r\n const d = new Date(\r\n parseInt(dmyMatch[3]!, 10),\r\n parseInt(dmyMatch[2]!, 10) - 1,\r\n parseInt(dmyMatch[1]!, 10)\r\n )\r\n if (!isNaN(d.getTime())) return d\r\n }\r\n\r\n // DD MMM YYYY or DD MMMM YYYY\r\n const textMatch = trimmed.match(/^(\\d{1,2})\\s+([a-zA-Z]+)\\s+(\\d{4})$/)\r\n if (textMatch) {\r\n const monthIndex = MONTH_MAP[textMatch[2]!.toLowerCase()]\r\n if (monthIndex !== undefined) {\r\n const d = new Date(\r\n parseInt(textMatch[3]!, 10),\r\n monthIndex,\r\n parseInt(textMatch[1]!, 10)\r\n )\r\n if (!isNaN(d.getTime())) return d\r\n }\r\n }\r\n\r\n // Unix timestamp (milliseconds) as string\r\n const numMatch = trimmed.match(/^-?\\d+$/)\r\n if (numMatch) {\r\n const d = new Date(parseInt(numMatch[0], 10))\r\n if (!isNaN(d.getTime())) return d\r\n }\r\n\r\n // Fallback: let Date.parse try\r\n const fallback = new Date(trimmed)\r\n if (!isNaN(fallback.getTime())) return fallback\r\n\r\n throw new InvalidDateError(input)\r\n}\r\n\r\nfunction isValidDate(d: Date): boolean {\r\n return d instanceof Date && !isNaN(d.getTime())\r\n}\r\n\r\nconst MS_IN_SECOND = 1000\r\nconst MS_IN_MINUTE = 60 * MS_IN_SECOND\r\nconst MS_IN_HOUR = 60 * MS_IN_MINUTE\r\nconst MS_IN_DAY = 24 * MS_IN_HOUR\r\n\r\n/**\r\n * Computes the difference between two dates.\r\n *\r\n * @param date1 - Start date.\r\n * @param date2 - End date.\r\n * @returns An object with years, months, days, hours, minutes, seconds.\r\n * @throws {InvalidDateError} If either date is invalid.\r\n */\r\nexport function dateDiff(date1: Date, date2: Date): DateDiff {\r\n if (!isValidDate(date1) || !isValidDate(date2)) {\r\n throw new InvalidDateError('Invalid date provided to dateDiff')\r\n }\r\n\r\n let years = date2.getFullYear() - date1.getFullYear()\r\n let months = date2.getMonth() - date1.getMonth()\r\n let days = date2.getDate() - date1.getDate()\r\n\r\n if (days < 0) {\r\n months -= 1\r\n const prevMonth = new Date(date2.getFullYear(), date2.getMonth(), 0)\r\n days += prevMonth.getDate()\r\n }\r\n\r\n if (months < 0) {\r\n years -= 1\r\n months += 12\r\n }\r\n\r\n const msDiff = Math.abs(date2.getTime() - date1.getTime())\r\n const totalSeconds = Math.floor(msDiff / MS_IN_SECOND)\r\n const hours = Math.floor((msDiff % MS_IN_DAY) / MS_IN_HOUR)\r\n const minutes = Math.floor((msDiff % MS_IN_HOUR) / MS_IN_MINUTE)\r\n const seconds = totalSeconds % 60\r\n\r\n return { years, months, days, hours, minutes, seconds }\r\n}\r\n\r\n/**\r\n * Adds days to a date.\r\n *\r\n * @param date - The original date.\r\n * @param days - Number of days to add (negative to subtract).\r\n * @returns A new Date.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function addDays(date: Date, days: number): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n const result = new Date(date.getTime())\r\n result.setDate(result.getDate() + days)\r\n return result\r\n}\r\n\r\n/**\r\n * Adds months to a date. Handles month-end overflow (e.g., Jan 31 + 1 month\r\n * becomes Feb 28).\r\n *\r\n * @param date - The original date.\r\n * @param months - Number of months to add (negative to subtract).\r\n * @returns A new Date.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function addMonths(date: Date, months: number): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n const result = new Date(date.getTime())\r\n const targetMonth = result.getMonth() + months\r\n result.setMonth(targetMonth)\r\n\r\n if (result.getMonth() !== ((targetMonth % 12) + 12) % 12) {\r\n result.setDate(0)\r\n }\r\n\r\n return result\r\n}\r\n\r\n/**\r\n * Adds years to a date. Handles leap-year overflow (e.g., Feb 29 + 1 year\r\n * becomes Feb 28).\r\n *\r\n * @param date - The original date.\r\n * @param years - Number of years to add (negative to subtract).\r\n * @returns A new Date.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function addYears(date: Date, years: number): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n const result = new Date(date.getTime())\r\n const targetYear = result.getFullYear() + years\r\n result.setFullYear(targetYear)\r\n\r\n if (result.getFullYear() !== targetYear) {\r\n result.setDate(0)\r\n }\r\n\r\n return result\r\n}\r\n\r\n/**\r\n * Returns the start of the day (00:00:00.000) for the given date.\r\n *\r\n * @param date - The date.\r\n * @returns A new Date set to midnight.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function startOfDay(date: Date): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0, 0)\r\n}\r\n\r\n/**\r\n * Returns the end of the day (23:59:59.999) for the given date.\r\n *\r\n * @param date - The date.\r\n * @returns A new Date set to the last millisecond of the day.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function endOfDay(date: Date): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59, 999)\r\n}\r\n\r\n/**\r\n * Returns the first moment of the month for the given date.\r\n *\r\n * @param date - The date.\r\n * @returns A new Date set to the start of the month.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function startOfMonth(date: Date): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n return new Date(date.getFullYear(), date.getMonth(), 1, 0, 0, 0, 0)\r\n}\r\n\r\n/**\r\n * Returns the last moment of the month for the given date.\r\n *\r\n * @param date - The date.\r\n * @returns A new Date set to the end of the month.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function endOfMonth(date: Date): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n return new Date(date.getFullYear(), date.getMonth() + 1, 0, 23, 59, 59, 999)\r\n}\r\n\r\n/**\r\n * Returns the first moment of the year for the given date.\r\n *\r\n * @param date - The date.\r\n * @returns A new Date set to Jan 1 00:00:00.000.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function startOfYear(date: Date): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n return new Date(date.getFullYear(), 0, 1, 0, 0, 0, 0)\r\n}\r\n\r\n/**\r\n * Returns the last moment of the year for the given date.\r\n *\r\n * @param date - The date.\r\n * @returns A new Date set to Dec 31 23:59:59.999.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function endOfYear(date: Date): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n return new Date(date.getFullYear(), 12, 0, 23, 59, 59, 999)\r\n}\r\n\r\n/**\r\n * Checks if the date falls on a weekend (Saturday or Sunday).\r\n *\r\n * @param date - The date to check.\r\n * @returns Whether the date is a weekend.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function isWeekend(date: Date): boolean {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n const day = date.getDay()\r\n return day === 0 || day === 6\r\n}\r\n\r\n/**\r\n * Checks if a year is a leap year.\r\n *\r\n * @param year - The year to check.\r\n * @returns Whether the year is a leap year.\r\n */\r\nexport function isLeapYear(year: number): boolean {\r\n return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0\r\n}\r\n\r\n/**\r\n * Checks if `date1` is before `date2`.\r\n *\r\n * @param date1 - First date.\r\n * @param date2 - Second date.\r\n * @returns Whether `date1` is before `date2`.\r\n * @throws {InvalidDateError} If either date is invalid.\r\n */\r\nexport function isBefore(date1: Date, date2: Date): boolean {\r\n if (!isValidDate(date1) || !isValidDate(date2)) {\r\n throw new InvalidDateError('Invalid date provided to isBefore')\r\n }\r\n return date1.getTime() < date2.getTime()\r\n}\r\n\r\n/**\r\n * Checks if `date1` is after `date2`.\r\n *\r\n * @param date1 - First date.\r\n * @param date2 - Second date.\r\n * @returns Whether `date1` is after `date2`.\r\n * @throws {InvalidDateError} If either date is invalid.\r\n */\r\nexport function isAfter(date1: Date, date2: Date): boolean {\r\n if (!isValidDate(date1) || !isValidDate(date2)) {\r\n throw new InvalidDateError('Invalid date provided to isAfter')\r\n }\r\n return date1.getTime() > date2.getTime()\r\n}\r\n\r\n/**\r\n * Checks if a date is within the inclusive range [start, end].\r\n *\r\n * @param date - The date to check.\r\n * @param start - Start of the range.\r\n * @param end - End of the range.\r\n * @returns Whether the date is between start and end.\r\n * @throws {InvalidDateError} If any date is invalid.\r\n */\r\nexport function isBetween(date: Date, start: Date, end: Date): boolean {\r\n if (!isValidDate(date) || !isValidDate(start) || !isValidDate(end)) {\r\n throw new InvalidDateError('Invalid date provided to isBetween')\r\n }\r\n return date.getTime() >= start.getTime() && date.getTime() <= end.getTime()\r\n}\r\n\r\n/**\r\n * Checks if a date is a business day (Monday to Friday).\r\n *\r\n * @param date - The date to check.\r\n * @returns Whether the date is a business day.\r\n */\r\nexport function isBusinessDay(date: Date): boolean {\r\n return isValidDate(date) && !isWeekend(date)\r\n}\r\n\r\n/**\r\n * Adds business days (skipping weekends) to a date.\r\n *\r\n * @param date - The starting date.\r\n * @param days - Number of business days to add (negative to subtract).\r\n * @returns A new Date.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function addBusinessDays(date: Date, days: number): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n\r\n const result = new Date(date.getTime())\r\n let remaining = Math.abs(days)\r\n const step = days >= 0 ? 1 : -1\r\n\r\n while (remaining > 0) {\r\n result.setDate(result.getDate() + step)\r\n const day = result.getDay()\r\n if (day !== 0 && day !== 6) {\r\n remaining--\r\n }\r\n }\r\n\r\n return result\r\n}\r\n\r\n/**\r\n * Calculates age in years from a birth date.\r\n *\r\n * @param birthDate - The date of birth.\r\n * @returns The age in years.\r\n * @throws {InvalidDateError} If the birth date is invalid.\r\n */\r\nexport function calculateAge(birthDate: Date): number {\r\n if (!isValidDate(birthDate)) throw new InvalidDateError(birthDate)\r\n\r\n const today = new Date()\r\n let age = today.getFullYear() - birthDate.getFullYear()\r\n const monthDiff = today.getMonth() - birthDate.getMonth()\r\n\r\n if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {\r\n age--\r\n }\r\n\r\n return age\r\n}\r\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/date/index.ts"],"sourcesContent":["/**\r\n * Error thrown when a date value is invalid.\r\n */\r\nexport class InvalidDateError extends Error {\r\n constructor(input: unknown) {\r\n super(`Invalid date: ${String(input)}`)\r\n this.name = 'InvalidDateError'\r\n }\r\n}\r\n\r\nexport interface DateDiff {\r\n years: number\r\n months: number\r\n days: number\r\n hours: number\r\n minutes: number\r\n seconds: number\r\n}\r\n\r\nconst MONTH_NAMES_SHORT = [\r\n 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\r\n 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',\r\n] as const\r\n\r\nconst MONTH_NAMES_FULL = [\r\n 'January', 'February', 'March', 'April', 'May', 'June',\r\n 'July', 'August', 'September', 'October', 'November', 'December',\r\n] as const\r\n\r\nconst MONTH_MAP: Record<string, number> = {\r\n jan: 0, january: 0,\r\n feb: 1, february: 1,\r\n mar: 2, march: 2,\r\n apr: 3, april: 3,\r\n may: 4,\r\n jun: 5, june: 5,\r\n jul: 6, july: 6,\r\n aug: 7, august: 7,\r\n sep: 8, september: 8,\r\n oct: 9, october: 9,\r\n nov: 10, november: 10,\r\n dec: 11, december: 11,\r\n}\r\n\r\n/**\r\n * Formats a Date to a string using the given format pattern.\r\n *\r\n * Supported tokens:\r\n * - `YYYY` — 4-digit year\r\n * - `YY` — 2-digit year\r\n * - `MMMM` — full month name\r\n * - `MMM` — abbreviated month name\r\n * - `MM` — 2-digit month (01–12)\r\n * - `DD` — 2-digit day (01–31)\r\n * - `HH` — 2-digit hours (00–23)\r\n * - `mm` — 2-digit minutes\r\n * - `ss` — 2-digit seconds\r\n * - `SSS` — milliseconds\r\n *\r\n * @param date - The date to format.\r\n * @param format - The format string (default `'YYYY-MM-DD'`).\r\n * @returns The formatted date string.\r\n */\r\nexport function formatDate(date: Date, format: string = 'YYYY-MM-DD'): string {\r\n const year = date.getFullYear()\r\n const month = date.getMonth()\r\n const day = date.getDate()\r\n const hours = date.getHours()\r\n const minutes = date.getMinutes()\r\n const seconds = date.getSeconds()\r\n const ms = date.getMilliseconds()\r\n\r\n const pad = (n: number, len: number = 2): string => String(n).padStart(len, '0')\r\n\r\n return format\r\n .replace(/YYYY/g, String(year))\r\n .replace(/YY/g, String(year).slice(-2))\r\n .replace(/MMMM/g, MONTH_NAMES_FULL[month]!)\r\n .replace(/MMM/g, MONTH_NAMES_SHORT[month]!)\r\n .replace(/MM/g, pad(month + 1))\r\n .replace(/DD/g, pad(day))\r\n .replace(/HH/g, pad(hours))\r\n .replace(/mm/g, pad(minutes))\r\n .replace(/ss/g, pad(seconds))\r\n .replace(/SSS/g, pad(ms, 3))\r\n}\r\n\r\n/**\r\n * Parses a date from a string, number (timestamp in ms), or Date object.\r\n *\r\n * Supported string formats:\r\n * - ISO (`YYYY-MM-DD`, `YYYY-MM-DDTHH:mm:ss`)\r\n * - `DD/MM/YYYY` or `DD-MM-YYYY`\r\n * - `DD MMM YYYY` or `DD MMMM YYYY`\r\n * - Unix timestamp (milliseconds)\r\n *\r\n * @param input - The value to parse.\r\n * @returns A valid Date object.\r\n * @throws {InvalidDateError} If the input cannot be parsed.\r\n */\r\nexport function parseDate(input: string | number | Date): Date {\r\n if (input instanceof Date) {\r\n if (isNaN(input.getTime())) throw new InvalidDateError(input)\r\n return new Date(input.getTime())\r\n }\r\n\r\n if (typeof input === 'number') {\r\n const d = new Date(input)\r\n if (isNaN(d.getTime())) throw new InvalidDateError(input)\r\n return d\r\n }\r\n\r\n const trimmed = input.trim()\r\n\r\n // ISO format: YYYY-MM-DD or YYYY-MM-DDTHH:mm:ss\r\n const isoMatch = trimmed.match(/^(\\d{4})-(\\d{2})-(\\d{2})(?:T(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?)?(?:Z|[+-]\\d{2}:?\\d{2})?$/)\r\n if (isoMatch) {\r\n const d = new Date(\r\n parseInt(isoMatch[1]!, 10),\r\n parseInt(isoMatch[2]!, 10) - 1,\r\n parseInt(isoMatch[3]!, 10),\r\n isoMatch[4] ? parseInt(isoMatch[4]!, 10) : 0,\r\n isoMatch[5] ? parseInt(isoMatch[5]!, 10) : 0,\r\n isoMatch[6] ? parseInt(isoMatch[6]!, 10) : 0,\r\n isoMatch[7] ? parseInt(isoMatch[7]!.padEnd(3, '0'), 10) : 0\r\n )\r\n if (!isNaN(d.getTime())) return d\r\n }\r\n\r\n // DD/MM/YYYY or DD-MM-YYYY\r\n const dmyMatch = trimmed.match(/^(\\d{1,2})[\\/-](\\d{1,2})[\\/-](\\d{4})$/)\r\n if (dmyMatch) {\r\n const year = parseInt(dmyMatch[3]!, 10)\r\n const month = parseInt(dmyMatch[2]!, 10) - 1\r\n const day = parseInt(dmyMatch[1]!, 10)\r\n const d = new Date(year, month, day)\r\n // Validate that the date didn't overflow (e.g. Feb 29 in non-leap year)\r\n if (!isNaN(d.getTime()) && d.getMonth() === month && d.getDate() === day) return d\r\n }\r\n\r\n // DD MMM YYYY or DD MMMM YYYY\r\n const textMatch = trimmed.match(/^(\\d{1,2})\\s+([a-zA-Z]+)\\s+(\\d{4})$/)\r\n if (textMatch) {\r\n const monthIndex = MONTH_MAP[textMatch[2]!.toLowerCase()]\r\n if (monthIndex !== undefined) {\r\n const year = parseInt(textMatch[3]!, 10)\r\n const day = parseInt(textMatch[1]!, 10)\r\n const d = new Date(year, monthIndex, day)\r\n if (!isNaN(d.getTime()) && d.getMonth() === monthIndex && d.getDate() === day) return d\r\n }\r\n }\r\n\r\n // Unix timestamp (milliseconds) as string\r\n const numMatch = trimmed.match(/^-?\\d+$/)\r\n if (numMatch) {\r\n const d = new Date(parseInt(numMatch[0], 10))\r\n if (!isNaN(d.getTime())) return d\r\n }\r\n\r\n // Fallback: let Date.parse try\r\n const fallback = new Date(trimmed)\r\n if (!isNaN(fallback.getTime())) return fallback\r\n\r\n throw new InvalidDateError(input)\r\n}\r\n\r\nfunction isValidDate(d: Date): boolean {\r\n return d instanceof Date && !isNaN(d.getTime())\r\n}\r\n\r\nconst MS_IN_SECOND = 1000\r\nconst MS_IN_MINUTE = 60 * MS_IN_SECOND\r\nconst MS_IN_HOUR = 60 * MS_IN_MINUTE\r\nconst MS_IN_DAY = 24 * MS_IN_HOUR\r\n\r\n/**\r\n * Computes the difference between two dates.\r\n *\r\n * @param date1 - Start date.\r\n * @param date2 - End date.\r\n * @returns An object with years, months, days, hours, minutes, seconds.\r\n * @throws {InvalidDateError} If either date is invalid.\r\n */\r\nexport function dateDiff(date1: Date, date2: Date): DateDiff {\r\n if (!isValidDate(date1) || !isValidDate(date2)) {\r\n throw new InvalidDateError('Invalid date provided to dateDiff')\r\n }\r\n\r\n let years = date2.getFullYear() - date1.getFullYear()\r\n let months = date2.getMonth() - date1.getMonth()\r\n let days = date2.getDate() - date1.getDate()\r\n\r\n if (days < 0) {\r\n months -= 1\r\n const prevMonth = new Date(date2.getFullYear(), date2.getMonth(), 0)\r\n days += prevMonth.getDate()\r\n }\r\n\r\n if (months < 0) {\r\n years -= 1\r\n months += 12\r\n }\r\n\r\n const msDiff = Math.abs(date2.getTime() - date1.getTime())\r\n const totalSeconds = Math.floor(msDiff / MS_IN_SECOND)\r\n const hours = Math.floor((msDiff % MS_IN_DAY) / MS_IN_HOUR)\r\n const minutes = Math.floor((msDiff % MS_IN_HOUR) / MS_IN_MINUTE)\r\n const seconds = totalSeconds % 60\r\n\r\n return { years, months, days, hours, minutes, seconds }\r\n}\r\n\r\n/**\r\n * Adds days to a date.\r\n *\r\n * @param date - The original date.\r\n * @param days - Number of days to add (negative to subtract).\r\n * @returns A new Date.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function addDays(date: Date, days: number): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n const result = new Date(date.getTime())\r\n result.setDate(result.getDate() + days)\r\n return result\r\n}\r\n\r\n/**\r\n * Adds months to a date. Handles month-end overflow (e.g., Jan 31 + 1 month\r\n * becomes Feb 28).\r\n *\r\n * @param date - The original date.\r\n * @param months - Number of months to add (negative to subtract).\r\n * @returns A new Date.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function addMonths(date: Date, months: number): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n const result = new Date(date.getTime())\r\n const targetMonth = result.getMonth() + months\r\n result.setMonth(targetMonth)\r\n\r\n if (result.getMonth() !== ((targetMonth % 12) + 12) % 12) {\r\n result.setDate(0)\r\n }\r\n\r\n return result\r\n}\r\n\r\n/**\r\n * Adds years to a date. Handles leap-year overflow (e.g., Feb 29 + 1 year\r\n * becomes Feb 28).\r\n *\r\n * @param date - The original date.\r\n * @param years - Number of years to add (negative to subtract).\r\n * @returns A new Date.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function addYears(date: Date, years: number): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n const result = new Date(date.getTime())\r\n const targetYear = result.getFullYear() + years\r\n result.setFullYear(targetYear)\r\n\r\n if (result.getFullYear() !== targetYear) {\r\n result.setDate(0)\r\n }\r\n\r\n return result\r\n}\r\n\r\n/**\r\n * Returns the start of the day (00:00:00.000) for the given date.\r\n *\r\n * @param date - The date.\r\n * @returns A new Date set to midnight.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function startOfDay(date: Date): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0, 0)\r\n}\r\n\r\n/**\r\n * Returns the end of the day (23:59:59.999) for the given date.\r\n *\r\n * @param date - The date.\r\n * @returns A new Date set to the last millisecond of the day.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function endOfDay(date: Date): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59, 999)\r\n}\r\n\r\n/**\r\n * Returns the first moment of the month for the given date.\r\n *\r\n * @param date - The date.\r\n * @returns A new Date set to the start of the month.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function startOfMonth(date: Date): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n return new Date(date.getFullYear(), date.getMonth(), 1, 0, 0, 0, 0)\r\n}\r\n\r\n/**\r\n * Returns the last moment of the month for the given date.\r\n *\r\n * @param date - The date.\r\n * @returns A new Date set to the end of the month.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function endOfMonth(date: Date): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n return new Date(date.getFullYear(), date.getMonth() + 1, 0, 23, 59, 59, 999)\r\n}\r\n\r\n/**\r\n * Returns the first moment of the year for the given date.\r\n *\r\n * @param date - The date.\r\n * @returns A new Date set to Jan 1 00:00:00.000.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function startOfYear(date: Date): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n return new Date(date.getFullYear(), 0, 1, 0, 0, 0, 0)\r\n}\r\n\r\n/**\r\n * Returns the last moment of the year for the given date.\r\n *\r\n * @param date - The date.\r\n * @returns A new Date set to Dec 31 23:59:59.999.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function endOfYear(date: Date): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n return new Date(date.getFullYear(), 12, 0, 23, 59, 59, 999)\r\n}\r\n\r\n/**\r\n * Checks if the date falls on a weekend (Saturday or Sunday).\r\n *\r\n * @param date - The date to check.\r\n * @returns Whether the date is a weekend.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function isWeekend(date: Date): boolean {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n const day = date.getDay()\r\n return day === 0 || day === 6\r\n}\r\n\r\n/**\r\n * Checks if a year is a leap year.\r\n *\r\n * @param year - The year to check.\r\n * @returns Whether the year is a leap year.\r\n */\r\nexport function isLeapYear(year: number): boolean {\r\n return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0\r\n}\r\n\r\n/**\r\n * Checks if `date1` is before `date2`.\r\n *\r\n * @param date1 - First date.\r\n * @param date2 - Second date.\r\n * @returns Whether `date1` is before `date2`.\r\n * @throws {InvalidDateError} If either date is invalid.\r\n */\r\nexport function isBefore(date1: Date, date2: Date): boolean {\r\n if (!isValidDate(date1) || !isValidDate(date2)) {\r\n throw new InvalidDateError('Invalid date provided to isBefore')\r\n }\r\n return date1.getTime() < date2.getTime()\r\n}\r\n\r\n/**\r\n * Checks if `date1` is after `date2`.\r\n *\r\n * @param date1 - First date.\r\n * @param date2 - Second date.\r\n * @returns Whether `date1` is after `date2`.\r\n * @throws {InvalidDateError} If either date is invalid.\r\n */\r\nexport function isAfter(date1: Date, date2: Date): boolean {\r\n if (!isValidDate(date1) || !isValidDate(date2)) {\r\n throw new InvalidDateError('Invalid date provided to isAfter')\r\n }\r\n return date1.getTime() > date2.getTime()\r\n}\r\n\r\n/**\r\n * Checks if a date is within the inclusive range [start, end].\r\n *\r\n * @param date - The date to check.\r\n * @param start - Start of the range.\r\n * @param end - End of the range.\r\n * @returns Whether the date is between start and end.\r\n * @throws {InvalidDateError} If any date is invalid.\r\n */\r\nexport function isBetween(date: Date, start: Date, end: Date): boolean {\r\n if (!isValidDate(date) || !isValidDate(start) || !isValidDate(end)) {\r\n throw new InvalidDateError('Invalid date provided to isBetween')\r\n }\r\n return date.getTime() >= start.getTime() && date.getTime() <= end.getTime()\r\n}\r\n\r\n/**\r\n * Checks if a date is a business day (Monday to Friday).\r\n *\r\n * @param date - The date to check.\r\n * @returns Whether the date is a business day.\r\n */\r\nexport function isBusinessDay(date: Date): boolean {\r\n return isValidDate(date) && !isWeekend(date)\r\n}\r\n\r\n/**\r\n * Adds business days (skipping weekends) to a date.\r\n *\r\n * @param date - The starting date.\r\n * @param days - Number of business days to add (negative to subtract).\r\n * @returns A new Date.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function addBusinessDays(date: Date, days: number): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n\r\n const result = new Date(date.getTime())\r\n let remaining = Math.abs(days)\r\n const step = days >= 0 ? 1 : -1\r\n\r\n while (remaining > 0) {\r\n result.setDate(result.getDate() + step)\r\n const day = result.getDay()\r\n if (day !== 0 && day !== 6) {\r\n remaining--\r\n }\r\n }\r\n\r\n return result\r\n}\r\n\r\n/**\r\n * Calculates age in years from a birth date.\r\n *\r\n * @param birthDate - The date of birth.\r\n * @returns The age in years.\r\n * @throws {InvalidDateError} If the birth date is invalid.\r\n */\r\nexport function calculateAge(birthDate: Date): number {\r\n if (!isValidDate(birthDate)) throw new InvalidDateError(birthDate)\r\n\r\n const today = new Date()\r\n let age = today.getFullYear() - birthDate.getFullYear()\r\n const monthDiff = today.getMonth() - birthDate.getMonth()\r\n\r\n if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {\r\n age--\r\n }\r\n\r\n return age\r\n}\r\n"],"mappings":"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","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -302,7 +302,8 @@ function div(a, b) {
|
|
|
302
302
|
}
|
|
303
303
|
function round(value, precision = 0) {
|
|
304
304
|
const factor = Math.pow(10, precision);
|
|
305
|
-
|
|
305
|
+
const shifted = Number((value * factor).toPrecision(15));
|
|
306
|
+
return Math.round(shifted) / factor;
|
|
306
307
|
}
|
|
307
308
|
function floor(value, precision = 0) {
|
|
308
309
|
const factor = Math.pow(10, precision);
|
|
@@ -444,23 +445,20 @@ function parseDate(input) {
|
|
|
444
445
|
}
|
|
445
446
|
const dmyMatch = trimmed.match(/^(\d{1,2})[\/-](\d{1,2})[\/-](\d{4})$/);
|
|
446
447
|
if (dmyMatch) {
|
|
447
|
-
const
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
);
|
|
452
|
-
if (!isNaN(d.getTime())) return d;
|
|
448
|
+
const year = parseInt(dmyMatch[3], 10);
|
|
449
|
+
const month = parseInt(dmyMatch[2], 10) - 1;
|
|
450
|
+
const day = parseInt(dmyMatch[1], 10);
|
|
451
|
+
const d = new Date(year, month, day);
|
|
452
|
+
if (!isNaN(d.getTime()) && d.getMonth() === month && d.getDate() === day) return d;
|
|
453
453
|
}
|
|
454
454
|
const textMatch = trimmed.match(/^(\d{1,2})\s+([a-zA-Z]+)\s+(\d{4})$/);
|
|
455
455
|
if (textMatch) {
|
|
456
456
|
const monthIndex = MONTH_MAP[textMatch[2].toLowerCase()];
|
|
457
457
|
if (monthIndex !== void 0) {
|
|
458
|
-
const
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
);
|
|
463
|
-
if (!isNaN(d.getTime())) return d;
|
|
458
|
+
const year = parseInt(textMatch[3], 10);
|
|
459
|
+
const day = parseInt(textMatch[1], 10);
|
|
460
|
+
const d = new Date(year, monthIndex, day);
|
|
461
|
+
if (!isNaN(d.getTime()) && d.getMonth() === monthIndex && d.getDate() === day) return d;
|
|
464
462
|
}
|
|
465
463
|
}
|
|
466
464
|
const numMatch = trimmed.match(/^-?\d+$/);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/index.ts","../src/math/index.ts","../src/date/index.ts","../src/crypto/index.ts","../src/path/index.ts","../src/collection/index.ts","../src/string/index.ts","../src/async/index.ts","../src/io/index.ts","../src/type/index.ts","../src/dep-exray/scanner/index.ts","../src/dep-exray/known-mappings.ts","../src/dep-exray/reporter/index.ts","../src/dep-exray/analyzer/index.ts"],"sourcesContent":["export interface DebounceOptions {\r\n leading?: boolean\r\n trailing?: boolean\r\n maxWait?: number\r\n}\r\n\r\nexport interface DebouncedFunction<T extends (...args: unknown[]) => unknown> {\r\n (...args: Parameters<T>): void\r\n cancel(): void\r\n flush(): void\r\n}\r\n\r\nexport interface MemoizedFunction<T extends (...args: unknown[]) => unknown> {\r\n (...args: Parameters<T>): ReturnType<T>\r\n cache: Map<string, ReturnType<T>>\r\n}\r\n\r\nexport interface RetryOptions {\r\n attempts?: number\r\n baseDelay?: number\r\n maxDelay?: number\r\n shouldRetry?: (error: unknown) => boolean\r\n}\r\n\r\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\r\n if (value === null || typeof value !== 'object') return false\r\n const proto = Object.getPrototypeOf(value)\r\n return proto === Object.prototype || proto === null\r\n}\r\n\r\nfunction getType(value: unknown): string {\r\n return Object.prototype.toString.call(value)\r\n}\r\n\r\nfunction clone<T>(value: T, seen: WeakMap<object, unknown>): T {\r\n if (value === null || typeof value !== 'object') return value\r\n\r\n if (seen.has(value as object)) return seen.get(value as object) as T\r\n\r\n const tag = getType(value)\r\n\r\n if (tag === '[object Date]') {\r\n const cloned = new Date((value as unknown as Date).getTime())\r\n seen.set(value as object, cloned)\r\n return cloned as unknown as T\r\n }\r\n\r\n if (tag === '[object RegExp]') {\r\n const regExp = value as unknown as RegExp\r\n const cloned = new RegExp(regExp.source, regExp.flags)\r\n cloned.lastIndex = regExp.lastIndex\r\n seen.set(value as object, cloned)\r\n return cloned as unknown as T\r\n }\r\n\r\n if (tag === '[object Map]') {\r\n const cloned = new Map<unknown, unknown>()\r\n seen.set(value as object, cloned)\r\n ;(value as unknown as Map<unknown, unknown>).forEach((v, k) => {\r\n cloned.set(clone(k, seen), clone(v, seen))\r\n })\r\n return cloned as unknown as T\r\n }\r\n\r\n if (tag === '[object Set]') {\r\n const cloned = new Set<unknown>()\r\n seen.set(value as object, cloned)\r\n ;(value as unknown as Set<unknown>).forEach(v => {\r\n cloned.add(clone(v, seen))\r\n })\r\n return cloned as unknown as T\r\n }\r\n\r\n if (Array.isArray(value)) {\r\n const cloned: unknown[] = []\r\n seen.set(value as object, cloned)\r\n for (let i = 0; i < value.length; i++) {\r\n cloned[i] = clone(value[i], seen)\r\n }\r\n return cloned as unknown as T\r\n }\r\n\r\n if (tag === '[object Object]') {\r\n const cloned: Record<string, unknown> = {}\r\n seen.set(value as object, cloned)\r\n const keys = Object.keys(value as Record<string, unknown>)\r\n for (let i = 0; i < keys.length; i++) {\r\n const key = keys[i]!\r\n cloned[key] = clone((value as Record<string, unknown>)[key], seen)\r\n }\r\n return cloned as unknown as T\r\n }\r\n\r\n return value\r\n}\r\n\r\n/**\r\n * Deep clone a value, supporting objects, arrays, Date, RegExp, Map, Set,\r\n * and cyclic references.\r\n *\r\n * @param value - The value to clone.\r\n * @returns A deep copy of the input value.\r\n */\r\nexport function deepClone<T>(value: T): T {\r\n const seen = new WeakMap<object, unknown>()\r\n return clone(value, seen)\r\n}\r\n\r\n/**\r\n * Deep merge multiple objects. Arrays are overwritten, not concatenated.\r\n * `null` and `undefined` source objects are skipped.\r\n *\r\n * @param objects - The objects to merge.\r\n * @returns A new object with merged properties.\r\n */\r\nexport function deepMerge<T extends Record<string, unknown>>(...objects: Partial<T>[]): T {\r\n const result = {} as T\r\n\r\n for (let i = 0; i < objects.length; i++) {\r\n const obj = objects[i]\r\n if (obj === null || obj === undefined) continue\r\n\r\n const keys = Object.keys(obj) as (keyof T)[]\r\n for (let j = 0; j < keys.length; j++) {\r\n const key = keys[j]!\r\n const val = obj[key]\r\n const existing = result[key]\r\n\r\n if (val !== undefined && isPlainObject(val) && isPlainObject(existing)) {\r\n result[key] = deepMerge(\r\n existing as Record<string, unknown>,\r\n val as Record<string, unknown>\r\n ) as T[keyof T]\r\n } else if (val !== undefined) {\r\n result[key] = val as T[keyof T]\r\n }\r\n }\r\n }\r\n\r\n return result\r\n}\r\n\r\n/**\r\n * Creates a debounced function that delays invoking `fn` until after `wait`\r\n * milliseconds have elapsed since the last invocation. Supports leading,\r\n * trailing, and maxWait options. The returned function also has `.cancel()`\r\n * and `.flush()` methods.\r\n *\r\n * @param fn - The function to debounce.\r\n * @param wait - The number of milliseconds to delay.\r\n * @param options - Optional configuration.\r\n * @returns A debounced function with `.cancel()` and `.flush()`.\r\n */\r\nexport function debounce<T extends (...args: unknown[]) => unknown>(\r\n fn: T,\r\n wait: number,\r\n options?: DebounceOptions\r\n): DebouncedFunction<T> {\r\n const { leading = false, trailing = true, maxWait } = options ?? {}\r\n\r\n let timer: ReturnType<typeof setTimeout> | null = null\r\n let maxTimer: ReturnType<typeof setTimeout> | null = null\r\n let lastArgs: Parameters<T> | null = null\r\n let lastCallTime: number | null = null\r\n let lastInvokeTime = 0\r\n\r\n function invoke(time: number): void {\r\n lastInvokeTime = time\r\n if (lastArgs) {\r\n fn(...lastArgs)\r\n lastArgs = null\r\n }\r\n }\r\n\r\n function startTimer(waitTime: number): void {\r\n if (timer) clearTimeout(timer)\r\n timer = setTimeout(() => {\r\n const now = Date.now()\r\n if (lastArgs && trailing) {\r\n invoke(now)\r\n }\r\n timer = null\r\n lastCallTime = null\r\n }, waitTime)\r\n }\r\n\r\n function startMaxTimer(): void {\r\n if (maxWait === undefined || maxTimer) return\r\n maxTimer = setTimeout(() => {\r\n if (lastArgs) {\r\n invoke(Date.now())\r\n if (timer) {\r\n clearTimeout(timer)\r\n timer = null\r\n }\r\n lastCallTime = null\r\n }\r\n }, maxWait)\r\n }\r\n\r\n function clearAllTimers(): void {\r\n if (timer) {\r\n clearTimeout(timer)\r\n timer = null\r\n }\r\n if (maxTimer) {\r\n clearTimeout(maxTimer)\r\n maxTimer = null\r\n }\r\n }\r\n\r\n function shouldInvoke(time: number): boolean {\r\n if (lastCallTime === null) return true\r\n const timeSinceLastCall = time - lastCallTime\r\n const timeSinceLastInvoke = time - lastInvokeTime\r\n return (\r\n timeSinceLastCall >= wait ||\r\n (maxWait !== undefined && timeSinceLastInvoke >= maxWait)\r\n )\r\n }\r\n\r\n const debounced = function (this: unknown, ...args: Parameters<T>): void {\r\n const time = Date.now()\r\n const isInvoking = shouldInvoke(time)\r\n\r\n lastArgs = args\r\n lastCallTime = time\r\n\r\n if (isInvoking && !timer && leading) {\r\n invoke(time)\r\n }\r\n\r\n if (!timer) {\r\n startTimer(wait)\r\n if (maxWait !== undefined) {\r\n startMaxTimer()\r\n }\r\n }\r\n } as DebouncedFunction<T>\r\n\r\n debounced.cancel = (): void => {\r\n clearAllTimers()\r\n lastArgs = null\r\n lastCallTime = null\r\n lastInvokeTime = 0\r\n }\r\n\r\n debounced.flush = (): void => {\r\n if (timer && lastArgs) {\r\n invoke(Date.now())\r\n clearAllTimers()\r\n lastCallTime = null\r\n }\r\n }\r\n\r\n return debounced\r\n}\r\n\r\n/**\r\n * Creates a throttled function that only invokes `fn` at most once per\r\n * `wait` milliseconds.\r\n *\r\n * @param fn - The function to throttle.\r\n * @param wait - The number of milliseconds to throttle invocations to.\r\n * @returns A throttled function.\r\n */\r\nexport function throttle<T extends (...args: unknown[]) => unknown>(\r\n fn: T,\r\n wait: number\r\n): (...args: Parameters<T>) => void {\r\n let lastTime = 0\r\n let timer: ReturnType<typeof setTimeout> | null = null\r\n let lastArgs: Parameters<T> | null = null\r\n\r\n const throttled = function (this: unknown, ...args: Parameters<T>): void {\r\n const now = Date.now()\r\n const remaining = wait - (now - lastTime)\r\n\r\n if (remaining <= 0) {\r\n if (timer) {\r\n clearTimeout(timer)\r\n timer = null\r\n }\r\n lastTime = now\r\n lastArgs = null\r\n fn.apply(this, args)\r\n } else {\r\n lastArgs = args\r\n if (!timer) {\r\n timer = setTimeout(() => {\r\n lastTime = Date.now()\r\n timer = null\r\n if (lastArgs) {\r\n fn.apply(this, lastArgs)\r\n lastArgs = null\r\n }\r\n }, remaining)\r\n }\r\n }\r\n }\r\n\r\n return throttled\r\n}\r\n\r\n/**\r\n * Creates a memoized version of `fn`. Uses a `Map` cache keyed by the\r\n * first argument by default, or by a custom `resolver` function.\r\n *\r\n * @param fn - The function to memoize.\r\n * @param resolver - Optional function to determine the cache key.\r\n * @returns The memoized function with a `.cache` property.\r\n */\r\nexport function memoize<T extends (...args: unknown[]) => unknown>(\r\n fn: T,\r\n resolver?: (...args: Parameters<T>) => string\r\n): MemoizedFunction<T> {\r\n const cache = new Map<string, ReturnType<T>>()\r\n\r\n const memoized = function (this: unknown, ...args: Parameters<T>): ReturnType<T> {\r\n const key = resolver ? resolver(...args) : String(args[0])\r\n if (cache.has(key)) {\r\n return cache.get(key) as ReturnType<T>\r\n }\r\n const result = fn.apply(this, args) as ReturnType<T>\r\n cache.set(key, result)\r\n return result\r\n }\r\n\r\n memoized.cache = cache\r\n\r\n return memoized as MemoizedFunction<T>\r\n}\r\n\r\n/**\r\n * Retries an async function with exponential backoff and jitter.\r\n *\r\n * @param fn - The async function to retry.\r\n * @param options - Retry configuration.\r\n * @returns A promise that resolves with the function result.\r\n */\r\nexport function retry<T>(\r\n fn: () => Promise<T>,\r\n options?: RetryOptions\r\n): Promise<T> {\r\n const {\r\n attempts = 3,\r\n baseDelay = 1000,\r\n maxDelay = 30000,\r\n shouldRetry = () => true,\r\n } = options ?? {}\r\n\r\n let attempt = 0\r\n\r\n const execute = (): Promise<T> => {\r\n attempt++\r\n return fn().catch((error: unknown) => {\r\n if (attempt >= attempts || !shouldRetry(error)) {\r\n throw error\r\n }\r\n\r\n const delay = Math.min(\r\n baseDelay * Math.pow(2, attempt - 1) + Math.random() * baseDelay,\r\n maxDelay\r\n )\r\n\r\n return new Promise<T>(resolve => {\r\n setTimeout(() => {\r\n resolve(execute())\r\n }, delay)\r\n })\r\n })\r\n }\r\n\r\n return execute()\r\n}\r\n\r\n/**\r\n * A no-operation function that returns `undefined`.\r\n */\r\nexport function noop(): void {\r\n return undefined\r\n}\r\n\r\n/**\r\n * Returns the given value unchanged.\r\n *\r\n * @param value - The value to return.\r\n * @returns The same value.\r\n */\r\nexport function identity<T>(value: T): T {\r\n return value\r\n}\r\n\r\n/**\r\n * Creates a function that invokes `fn` only once. Subsequent calls return\r\n * the result of the first invocation.\r\n *\r\n * @param fn - The function to wrap.\r\n * @returns A function that runs only once.\r\n */\r\nexport function once<T extends (...args: unknown[]) => unknown>(\r\n fn: T\r\n): (...args: Parameters<T>) => ReturnType<T> {\r\n let called = false\r\n let result: ReturnType<T>\r\n\r\n return function (this: unknown, ...args: Parameters<T>): ReturnType<T> {\r\n if (!called) {\r\n called = true\r\n result = fn.apply(this, args) as ReturnType<T>\r\n }\r\n return result\r\n }\r\n}\r\n","/**\r\n * Error thrown when attempting to divide by zero.\r\n */\r\nexport class DivisionByZeroError extends Error {\r\n constructor() {\r\n super('Division by zero')\r\n this.name = 'DivisionByZeroError'\r\n }\r\n}\r\n\r\nfunction getPrecision(value: number): number {\r\n if (!isFinite(value)) return 0\r\n const eIndex = String(value).indexOf('e')\r\n if (eIndex > -1) {\r\n const exp = parseInt(String(value).slice(eIndex + 1), 10)\r\n if (exp < 0) return Math.abs(exp)\r\n return 0\r\n }\r\n const str = String(value)\r\n const dot = str.indexOf('.')\r\n return dot === -1 ? 0 : str.length - dot - 1\r\n}\r\n\r\nfunction toPrecisionFactor(a: number, b: number): number {\r\n return Math.pow(10, Math.max(getPrecision(a), getPrecision(b)))\r\n}\r\n\r\n/**\r\n * Safely adds two numbers, handling floating-point precision.\r\n *\r\n * @param a - First number.\r\n * @param b - Second number.\r\n * @returns The sum.\r\n */\r\nexport function add(a: number, b: number): number {\r\n const factor = toPrecisionFactor(a, b)\r\n return (Math.round(a * factor) + Math.round(b * factor)) / factor\r\n}\r\n\r\n/**\r\n * Safely subtracts two numbers, handling floating-point precision.\r\n *\r\n * @param a - First number.\r\n * @param b - Second number.\r\n * @returns The difference.\r\n */\r\nexport function sub(a: number, b: number): number {\r\n const factor = toPrecisionFactor(a, b)\r\n return (Math.round(a * factor) - Math.round(b * factor)) / factor\r\n}\r\n\r\n/**\r\n * Safely multiplies two numbers, handling floating-point precision.\r\n *\r\n * @param a - First number.\r\n * @param b - Second number.\r\n * @returns The product.\r\n */\r\nexport function mul(a: number, b: number): number {\r\n const factorA = toPrecisionFactor(a, 1)\r\n const factorB = toPrecisionFactor(1, b)\r\n const result = (Math.round(a * factorA) * Math.round(b * factorB)) / (factorA * factorB)\r\n return result\r\n}\r\n\r\n/**\r\n * Safely divides two numbers.\r\n *\r\n * @param a - The dividend.\r\n * @param b - The divisor.\r\n * @returns The quotient.\r\n * @throws {DivisionByZeroError} If `b` is zero.\r\n */\r\nexport function div(a: number, b: number): number {\r\n if (b === 0) throw new DivisionByZeroError()\r\n const factor = toPrecisionFactor(a, b)\r\n return Math.round(a * factor) / Math.round(b * factor)\r\n}\r\n\r\n/**\r\n * Rounds a number to the given precision.\r\n *\r\n * @param value - The number to round.\r\n * @param precision - Number of decimal places (default 0).\r\n * @returns The rounded value.\r\n */\r\nexport function round(value: number, precision: number = 0): number {\r\n const factor = Math.pow(10, precision)\r\n return Math.round(value * factor) / factor\r\n}\r\n\r\n/**\r\n * Floors a number to the given precision.\r\n *\r\n * @param value - The number to floor.\r\n * @param precision - Number of decimal places (default 0).\r\n * @returns The floored value.\r\n */\r\nexport function floor(value: number, precision: number = 0): number {\r\n const factor = Math.pow(10, precision)\r\n return Math.floor(value * factor) / factor\r\n}\r\n\r\n/**\r\n * Ceils a number to the given precision.\r\n *\r\n * @param value - The number to ceil.\r\n * @param precision - Number of decimal places (default 0).\r\n * @returns The ceiled value.\r\n */\r\nexport function ceil(value: number, precision: number = 0): number {\r\n const factor = Math.pow(10, precision)\r\n return Math.ceil(value * factor) / factor\r\n}\r\n\r\n/**\r\n * Checks if two numbers are approximately equal within a tolerance.\r\n *\r\n * @param a - First number.\r\n * @param b - Second number.\r\n * @param tolerance - Maximum difference (default `Number.EPSILON`).\r\n * @returns Whether the numbers are approximately equal.\r\n */\r\nexport function approxEqual(a: number, b: number, tolerance: number = Number.EPSILON): boolean {\r\n return Math.abs(a - b) <= tolerance\r\n}\r\n\r\n/**\r\n * Clamps a value within the inclusive range [min, max].\r\n *\r\n * @param value - The value to clamp.\r\n * @param min - The lower bound.\r\n * @param max - The upper bound.\r\n * @returns The clamped value.\r\n * @throws {RangeError} If `min` exceeds `max`.\r\n */\r\nexport function clamp(value: number, min: number, max: number): number {\r\n if (min > max) {\r\n throw new RangeError('Minimum value cannot exceed maximum value')\r\n }\r\n return Math.min(Math.max(value, min), max)\r\n}\r\n\r\n/**\r\n * Computes the sum of an array of numbers.\r\n *\r\n * @param values - Array of numbers.\r\n * @returns The total sum.\r\n */\r\nexport function sum(values: number[]): number {\r\n let total = 0\r\n for (let i = 0; i < values.length; i++) {\r\n total += values[i]!\r\n }\r\n return total\r\n}\r\n\r\n/**\r\n * Computes the average (mean) of an array of numbers.\r\n *\r\n * @param values - Array of numbers.\r\n * @returns The average.\r\n * @throws {RangeError} If the array is empty.\r\n */\r\nexport function average(values: number[]): number {\r\n if (values.length === 0) {\r\n throw new RangeError('Cannot compute average of an empty array')\r\n }\r\n return sum(values) / values.length\r\n}\r\n\r\n/**\r\n * Generates a random integer between `min` and `max` (inclusive).\r\n *\r\n * @param min - The minimum integer.\r\n * @param max - The maximum integer.\r\n * @returns A random integer.\r\n * @throws {RangeError} If arguments are not integers or `min > max`.\r\n */\r\nexport function randomInt(min: number, max: number): number {\r\n if (!Number.isInteger(min) || !Number.isInteger(max)) {\r\n throw new RangeError('Arguments must be integers')\r\n }\r\n if (min > max) {\r\n throw new RangeError('Minimum value cannot exceed maximum value')\r\n }\r\n return Math.floor(Math.random() * (max - min + 1)) + min\r\n}\r\n\r\n/**\r\n * Checks if a number is within the inclusive range [min, max].\r\n *\r\n * @param value - The number to check.\r\n * @param min - The lower bound.\r\n * @param max - The upper bound.\r\n * @returns Whether the value is in range.\r\n */\r\nexport function inRange(value: number, min: number, max: number): boolean {\r\n return value >= min && value <= max\r\n}\r\n","/**\r\n * Error thrown when a date value is invalid.\r\n */\r\nexport class InvalidDateError extends Error {\r\n constructor(input: unknown) {\r\n super(`Invalid date: ${String(input)}`)\r\n this.name = 'InvalidDateError'\r\n }\r\n}\r\n\r\nexport interface DateDiff {\r\n years: number\r\n months: number\r\n days: number\r\n hours: number\r\n minutes: number\r\n seconds: number\r\n}\r\n\r\nconst MONTH_NAMES_SHORT = [\r\n 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\r\n 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',\r\n] as const\r\n\r\nconst MONTH_NAMES_FULL = [\r\n 'January', 'February', 'March', 'April', 'May', 'June',\r\n 'July', 'August', 'September', 'October', 'November', 'December',\r\n] as const\r\n\r\nconst MONTH_MAP: Record<string, number> = {\r\n jan: 0, january: 0,\r\n feb: 1, february: 1,\r\n mar: 2, march: 2,\r\n apr: 3, april: 3,\r\n may: 4,\r\n jun: 5, june: 5,\r\n jul: 6, july: 6,\r\n aug: 7, august: 7,\r\n sep: 8, september: 8,\r\n oct: 9, october: 9,\r\n nov: 10, november: 10,\r\n dec: 11, december: 11,\r\n}\r\n\r\n/**\r\n * Formats a Date to a string using the given format pattern.\r\n *\r\n * Supported tokens:\r\n * - `YYYY` — 4-digit year\r\n * - `YY` — 2-digit year\r\n * - `MMMM` — full month name\r\n * - `MMM` — abbreviated month name\r\n * - `MM` — 2-digit month (01–12)\r\n * - `DD` — 2-digit day (01–31)\r\n * - `HH` — 2-digit hours (00–23)\r\n * - `mm` — 2-digit minutes\r\n * - `ss` — 2-digit seconds\r\n * - `SSS` — milliseconds\r\n *\r\n * @param date - The date to format.\r\n * @param format - The format string (default `'YYYY-MM-DD'`).\r\n * @returns The formatted date string.\r\n */\r\nexport function formatDate(date: Date, format: string = 'YYYY-MM-DD'): string {\r\n const year = date.getFullYear()\r\n const month = date.getMonth()\r\n const day = date.getDate()\r\n const hours = date.getHours()\r\n const minutes = date.getMinutes()\r\n const seconds = date.getSeconds()\r\n const ms = date.getMilliseconds()\r\n\r\n const pad = (n: number, len: number = 2): string => String(n).padStart(len, '0')\r\n\r\n return format\r\n .replace(/YYYY/g, String(year))\r\n .replace(/YY/g, String(year).slice(-2))\r\n .replace(/MMMM/g, MONTH_NAMES_FULL[month]!)\r\n .replace(/MMM/g, MONTH_NAMES_SHORT[month]!)\r\n .replace(/MM/g, pad(month + 1))\r\n .replace(/DD/g, pad(day))\r\n .replace(/HH/g, pad(hours))\r\n .replace(/mm/g, pad(minutes))\r\n .replace(/ss/g, pad(seconds))\r\n .replace(/SSS/g, pad(ms, 3))\r\n}\r\n\r\n/**\r\n * Parses a date from a string, number (timestamp in ms), or Date object.\r\n *\r\n * Supported string formats:\r\n * - ISO (`YYYY-MM-DD`, `YYYY-MM-DDTHH:mm:ss`)\r\n * - `DD/MM/YYYY` or `DD-MM-YYYY`\r\n * - `DD MMM YYYY` or `DD MMMM YYYY`\r\n * - Unix timestamp (milliseconds)\r\n *\r\n * @param input - The value to parse.\r\n * @returns A valid Date object.\r\n * @throws {InvalidDateError} If the input cannot be parsed.\r\n */\r\nexport function parseDate(input: string | number | Date): Date {\r\n if (input instanceof Date) {\r\n if (isNaN(input.getTime())) throw new InvalidDateError(input)\r\n return new Date(input.getTime())\r\n }\r\n\r\n if (typeof input === 'number') {\r\n const d = new Date(input)\r\n if (isNaN(d.getTime())) throw new InvalidDateError(input)\r\n return d\r\n }\r\n\r\n const trimmed = input.trim()\r\n\r\n // ISO format: YYYY-MM-DD or YYYY-MM-DDTHH:mm:ss\r\n const isoMatch = trimmed.match(/^(\\d{4})-(\\d{2})-(\\d{2})(?:T(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?)?(?:Z|[+-]\\d{2}:?\\d{2})?$/)\r\n if (isoMatch) {\r\n const d = new Date(\r\n parseInt(isoMatch[1]!, 10),\r\n parseInt(isoMatch[2]!, 10) - 1,\r\n parseInt(isoMatch[3]!, 10),\r\n isoMatch[4] ? parseInt(isoMatch[4]!, 10) : 0,\r\n isoMatch[5] ? parseInt(isoMatch[5]!, 10) : 0,\r\n isoMatch[6] ? parseInt(isoMatch[6]!, 10) : 0,\r\n isoMatch[7] ? parseInt(isoMatch[7]!.padEnd(3, '0'), 10) : 0\r\n )\r\n if (!isNaN(d.getTime())) return d\r\n }\r\n\r\n // DD/MM/YYYY or DD-MM-YYYY\r\n const dmyMatch = trimmed.match(/^(\\d{1,2})[\\/-](\\d{1,2})[\\/-](\\d{4})$/)\r\n if (dmyMatch) {\r\n const d = new Date(\r\n parseInt(dmyMatch[3]!, 10),\r\n parseInt(dmyMatch[2]!, 10) - 1,\r\n parseInt(dmyMatch[1]!, 10)\r\n )\r\n if (!isNaN(d.getTime())) return d\r\n }\r\n\r\n // DD MMM YYYY or DD MMMM YYYY\r\n const textMatch = trimmed.match(/^(\\d{1,2})\\s+([a-zA-Z]+)\\s+(\\d{4})$/)\r\n if (textMatch) {\r\n const monthIndex = MONTH_MAP[textMatch[2]!.toLowerCase()]\r\n if (monthIndex !== undefined) {\r\n const d = new Date(\r\n parseInt(textMatch[3]!, 10),\r\n monthIndex,\r\n parseInt(textMatch[1]!, 10)\r\n )\r\n if (!isNaN(d.getTime())) return d\r\n }\r\n }\r\n\r\n // Unix timestamp (milliseconds) as string\r\n const numMatch = trimmed.match(/^-?\\d+$/)\r\n if (numMatch) {\r\n const d = new Date(parseInt(numMatch[0], 10))\r\n if (!isNaN(d.getTime())) return d\r\n }\r\n\r\n // Fallback: let Date.parse try\r\n const fallback = new Date(trimmed)\r\n if (!isNaN(fallback.getTime())) return fallback\r\n\r\n throw new InvalidDateError(input)\r\n}\r\n\r\nfunction isValidDate(d: Date): boolean {\r\n return d instanceof Date && !isNaN(d.getTime())\r\n}\r\n\r\nconst MS_IN_SECOND = 1000\r\nconst MS_IN_MINUTE = 60 * MS_IN_SECOND\r\nconst MS_IN_HOUR = 60 * MS_IN_MINUTE\r\nconst MS_IN_DAY = 24 * MS_IN_HOUR\r\n\r\n/**\r\n * Computes the difference between two dates.\r\n *\r\n * @param date1 - Start date.\r\n * @param date2 - End date.\r\n * @returns An object with years, months, days, hours, minutes, seconds.\r\n * @throws {InvalidDateError} If either date is invalid.\r\n */\r\nexport function dateDiff(date1: Date, date2: Date): DateDiff {\r\n if (!isValidDate(date1) || !isValidDate(date2)) {\r\n throw new InvalidDateError('Invalid date provided to dateDiff')\r\n }\r\n\r\n let years = date2.getFullYear() - date1.getFullYear()\r\n let months = date2.getMonth() - date1.getMonth()\r\n let days = date2.getDate() - date1.getDate()\r\n\r\n if (days < 0) {\r\n months -= 1\r\n const prevMonth = new Date(date2.getFullYear(), date2.getMonth(), 0)\r\n days += prevMonth.getDate()\r\n }\r\n\r\n if (months < 0) {\r\n years -= 1\r\n months += 12\r\n }\r\n\r\n const msDiff = Math.abs(date2.getTime() - date1.getTime())\r\n const totalSeconds = Math.floor(msDiff / MS_IN_SECOND)\r\n const hours = Math.floor((msDiff % MS_IN_DAY) / MS_IN_HOUR)\r\n const minutes = Math.floor((msDiff % MS_IN_HOUR) / MS_IN_MINUTE)\r\n const seconds = totalSeconds % 60\r\n\r\n return { years, months, days, hours, minutes, seconds }\r\n}\r\n\r\n/**\r\n * Adds days to a date.\r\n *\r\n * @param date - The original date.\r\n * @param days - Number of days to add (negative to subtract).\r\n * @returns A new Date.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function addDays(date: Date, days: number): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n const result = new Date(date.getTime())\r\n result.setDate(result.getDate() + days)\r\n return result\r\n}\r\n\r\n/**\r\n * Adds months to a date. Handles month-end overflow (e.g., Jan 31 + 1 month\r\n * becomes Feb 28).\r\n *\r\n * @param date - The original date.\r\n * @param months - Number of months to add (negative to subtract).\r\n * @returns A new Date.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function addMonths(date: Date, months: number): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n const result = new Date(date.getTime())\r\n const targetMonth = result.getMonth() + months\r\n result.setMonth(targetMonth)\r\n\r\n if (result.getMonth() !== ((targetMonth % 12) + 12) % 12) {\r\n result.setDate(0)\r\n }\r\n\r\n return result\r\n}\r\n\r\n/**\r\n * Adds years to a date. Handles leap-year overflow (e.g., Feb 29 + 1 year\r\n * becomes Feb 28).\r\n *\r\n * @param date - The original date.\r\n * @param years - Number of years to add (negative to subtract).\r\n * @returns A new Date.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function addYears(date: Date, years: number): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n const result = new Date(date.getTime())\r\n const targetYear = result.getFullYear() + years\r\n result.setFullYear(targetYear)\r\n\r\n if (result.getFullYear() !== targetYear) {\r\n result.setDate(0)\r\n }\r\n\r\n return result\r\n}\r\n\r\n/**\r\n * Returns the start of the day (00:00:00.000) for the given date.\r\n *\r\n * @param date - The date.\r\n * @returns A new Date set to midnight.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function startOfDay(date: Date): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0, 0)\r\n}\r\n\r\n/**\r\n * Returns the end of the day (23:59:59.999) for the given date.\r\n *\r\n * @param date - The date.\r\n * @returns A new Date set to the last millisecond of the day.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function endOfDay(date: Date): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59, 999)\r\n}\r\n\r\n/**\r\n * Returns the first moment of the month for the given date.\r\n *\r\n * @param date - The date.\r\n * @returns A new Date set to the start of the month.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function startOfMonth(date: Date): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n return new Date(date.getFullYear(), date.getMonth(), 1, 0, 0, 0, 0)\r\n}\r\n\r\n/**\r\n * Returns the last moment of the month for the given date.\r\n *\r\n * @param date - The date.\r\n * @returns A new Date set to the end of the month.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function endOfMonth(date: Date): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n return new Date(date.getFullYear(), date.getMonth() + 1, 0, 23, 59, 59, 999)\r\n}\r\n\r\n/**\r\n * Returns the first moment of the year for the given date.\r\n *\r\n * @param date - The date.\r\n * @returns A new Date set to Jan 1 00:00:00.000.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function startOfYear(date: Date): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n return new Date(date.getFullYear(), 0, 1, 0, 0, 0, 0)\r\n}\r\n\r\n/**\r\n * Returns the last moment of the year for the given date.\r\n *\r\n * @param date - The date.\r\n * @returns A new Date set to Dec 31 23:59:59.999.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function endOfYear(date: Date): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n return new Date(date.getFullYear(), 12, 0, 23, 59, 59, 999)\r\n}\r\n\r\n/**\r\n * Checks if the date falls on a weekend (Saturday or Sunday).\r\n *\r\n * @param date - The date to check.\r\n * @returns Whether the date is a weekend.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function isWeekend(date: Date): boolean {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n const day = date.getDay()\r\n return day === 0 || day === 6\r\n}\r\n\r\n/**\r\n * Checks if a year is a leap year.\r\n *\r\n * @param year - The year to check.\r\n * @returns Whether the year is a leap year.\r\n */\r\nexport function isLeapYear(year: number): boolean {\r\n return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0\r\n}\r\n\r\n/**\r\n * Checks if `date1` is before `date2`.\r\n *\r\n * @param date1 - First date.\r\n * @param date2 - Second date.\r\n * @returns Whether `date1` is before `date2`.\r\n * @throws {InvalidDateError} If either date is invalid.\r\n */\r\nexport function isBefore(date1: Date, date2: Date): boolean {\r\n if (!isValidDate(date1) || !isValidDate(date2)) {\r\n throw new InvalidDateError('Invalid date provided to isBefore')\r\n }\r\n return date1.getTime() < date2.getTime()\r\n}\r\n\r\n/**\r\n * Checks if `date1` is after `date2`.\r\n *\r\n * @param date1 - First date.\r\n * @param date2 - Second date.\r\n * @returns Whether `date1` is after `date2`.\r\n * @throws {InvalidDateError} If either date is invalid.\r\n */\r\nexport function isAfter(date1: Date, date2: Date): boolean {\r\n if (!isValidDate(date1) || !isValidDate(date2)) {\r\n throw new InvalidDateError('Invalid date provided to isAfter')\r\n }\r\n return date1.getTime() > date2.getTime()\r\n}\r\n\r\n/**\r\n * Checks if a date is within the inclusive range [start, end].\r\n *\r\n * @param date - The date to check.\r\n * @param start - Start of the range.\r\n * @param end - End of the range.\r\n * @returns Whether the date is between start and end.\r\n * @throws {InvalidDateError} If any date is invalid.\r\n */\r\nexport function isBetween(date: Date, start: Date, end: Date): boolean {\r\n if (!isValidDate(date) || !isValidDate(start) || !isValidDate(end)) {\r\n throw new InvalidDateError('Invalid date provided to isBetween')\r\n }\r\n return date.getTime() >= start.getTime() && date.getTime() <= end.getTime()\r\n}\r\n\r\n/**\r\n * Checks if a date is a business day (Monday to Friday).\r\n *\r\n * @param date - The date to check.\r\n * @returns Whether the date is a business day.\r\n */\r\nexport function isBusinessDay(date: Date): boolean {\r\n return isValidDate(date) && !isWeekend(date)\r\n}\r\n\r\n/**\r\n * Adds business days (skipping weekends) to a date.\r\n *\r\n * @param date - The starting date.\r\n * @param days - Number of business days to add (negative to subtract).\r\n * @returns A new Date.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function addBusinessDays(date: Date, days: number): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n\r\n const result = new Date(date.getTime())\r\n let remaining = Math.abs(days)\r\n const step = days >= 0 ? 1 : -1\r\n\r\n while (remaining > 0) {\r\n result.setDate(result.getDate() + step)\r\n const day = result.getDay()\r\n if (day !== 0 && day !== 6) {\r\n remaining--\r\n }\r\n }\r\n\r\n return result\r\n}\r\n\r\n/**\r\n * Calculates age in years from a birth date.\r\n *\r\n * @param birthDate - The date of birth.\r\n * @returns The age in years.\r\n * @throws {InvalidDateError} If the birth date is invalid.\r\n */\r\nexport function calculateAge(birthDate: Date): number {\r\n if (!isValidDate(birthDate)) throw new InvalidDateError(birthDate)\r\n\r\n const today = new Date()\r\n let age = today.getFullYear() - birthDate.getFullYear()\r\n const monthDiff = today.getMonth() - birthDate.getMonth()\r\n\r\n if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {\r\n age--\r\n }\r\n\r\n return age\r\n}\r\n","/**\r\n * Simple hash function using the djb2 algorithm.\r\n * Fast, non-cryptographic — suitable for hashtables, not security.\r\n *\r\n * @param str - The string to hash.\r\n * @returns A 32-bit integer hash.\r\n */\r\nexport function hash(str: string): number {\r\n let h = 5381\r\n for (let i = 0; i < str.length; i++) {\r\n h = ((h << 5) + h + str.charCodeAt(i)) | 0\r\n }\r\n return h >>> 0\r\n}\r\n\r\n/**\r\n * Produces a deterministic hex hash from a string.\r\n * NOT actual MD5 — use for cache keys / deterministic IDs.\r\n *\r\n * @param str - The string to hash.\r\n * @returns A 32-character hex string.\r\n */\r\nexport function simpleHash(str: string): string {\r\n let h1 = 0x67452301\r\n let h2 = 0xefcdab89\r\n let h3 = 0x98badcfe\r\n let h4 = 0x10325476\r\n\r\n for (let i = 0; i < str.length; i++) {\r\n const c = str.charCodeAt(i)\r\n h1 = (h1 + c) | 0\r\n h2 = (h2 + (c << 3) + i) | 0\r\n h3 = (h3 ^ c) | 0\r\n h4 = (h4 + (c << 5) + (c << 1)) | 0\r\n }\r\n\r\n const toHex = (n: number): string => (n >>> 0).toString(16).padStart(8, '0')\r\n return toHex(h1) + toHex(h2) + toHex(h3) + toHex(h4)\r\n}\r\n\r\nfunction getRandomBytes(size: number): Uint8Array {\r\n const bytes = new Uint8Array(size)\r\n if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') {\r\n crypto.getRandomValues(bytes)\r\n } else {\r\n for (let i = 0; i < size; i++) {\r\n bytes[i] = Math.floor(Math.random() * 256)\r\n }\r\n }\r\n return bytes\r\n}\r\n\r\n/**\r\n * Generates random bytes as a hex string.\r\n *\r\n * @param size - Number of random bytes (default 16).\r\n * @returns A hex string of length `size * 2`.\r\n */\r\nexport function randomHex(size: number = 16): string {\r\n const bytes = getRandomBytes(size)\r\n let result = ''\r\n for (let i = 0; i < bytes.length; i++) {\r\n result += bytes[i]!.toString(16).padStart(2, '0')\r\n }\r\n return result\r\n}\r\n\r\nfunction utf8ToBytes(str: string): Uint8Array {\r\n if (typeof TextEncoder !== 'undefined') {\r\n return new TextEncoder().encode(str)\r\n }\r\n const bytes = new Uint8Array(str.length)\r\n for (let i = 0; i < str.length; i++) {\r\n bytes[i] = str.charCodeAt(i)\r\n }\r\n return bytes\r\n}\r\n\r\nfunction bytesToUtf8(bytes: Uint8Array): string {\r\n if (typeof TextDecoder !== 'undefined') {\r\n return new TextDecoder().decode(bytes)\r\n }\r\n let result = ''\r\n for (let i = 0; i < bytes.length; i++) {\r\n result += String.fromCharCode(bytes[i]!)\r\n }\r\n return result\r\n}\r\n\r\nfunction bytesToBase64(bytes: Uint8Array): string {\r\n let binary = ''\r\n for (let i = 0; i < bytes.length; i++) {\r\n binary += String.fromCharCode(bytes[i]!)\r\n }\r\n if (typeof btoa === 'function') {\r\n return btoa(binary)\r\n }\r\n return Buffer.from(binary, 'latin1').toString('base64')\r\n}\r\n\r\nfunction base64ToBytes(str: string): Uint8Array {\r\n let binary: string\r\n if (typeof atob === 'function') {\r\n binary = atob(str)\r\n } else {\r\n binary = Buffer.from(str, 'base64').toString('latin1')\r\n }\r\n const bytes = new Uint8Array(binary.length)\r\n for (let i = 0; i < binary.length; i++) {\r\n bytes[i] = binary.charCodeAt(i)\r\n }\r\n return bytes\r\n}\r\n\r\n/**\r\n * Encodes a string to base64. Works in both Node.js and browser.\r\n * Handles UTF-8 characters correctly.\r\n *\r\n * @param str - The string to encode.\r\n * @returns The base64-encoded string.\r\n */\r\nexport function base64Encode(str: string): string {\r\n const bytes = utf8ToBytes(str)\r\n return bytesToBase64(bytes)\r\n}\r\n\r\n/**\r\n * Decodes a base64-encoded string. Works in both Node.js and browser.\r\n *\r\n * @param str - The base64 string to decode.\r\n * @returns The decoded string.\r\n */\r\nexport function base64Decode(str: string): string {\r\n const bytes = base64ToBytes(str)\r\n return bytesToUtf8(bytes)\r\n}\r\n\r\n/**\r\n * Generates a cryptographically random token string.\r\n *\r\n * @param bytes - Number of random bytes (default 32 → 64-char hex).\r\n * @returns A hex string suitable for API keys, reset tokens, etc.\r\n */\r\nexport function generateToken(bytes: number = 32): string {\r\n return randomHex(bytes)\r\n}\r\n\r\n/**\r\n * Generates a numeric OTP of the given length.\r\n *\r\n * @param length - Number of digits (default 6).\r\n * @returns A numeric string of the specified length.\r\n */\r\nexport function generateOTP(length: number = 6): string {\r\n const bytes = getRandomBytes(length)\r\n let otp = ''\r\n for (let i = 0; i < length; i++) {\r\n otp += (bytes[i]! % 10).toString()\r\n }\r\n return otp\r\n}\r\n\r\n/**\r\n * Simple XOR cipher — symmetrical, for light obfuscation only.\r\n *\r\n * ⚠️ WARNING: This is NOT encryption. XOR cipher provides zero security\r\n * against any attacker. Do NOT use this for passwords, API keys, personal\r\n * data, or any sensitive information. It can be trivially reversed.\r\n * For real encryption, use native `crypto.subtle` (Web) or `node:crypto`.\r\n *\r\n * Suitable only for: basic data masking, simple anti-scraping, educational purposes.\r\n *\r\n * @param str - The input string (will be transformed).\r\n * @param key - The cipher key.\r\n * @returns The XOR-transformed string.\r\n */\r\nexport function xorCipher(str: string, key: string): string {\r\n let result = ''\r\n for (let i = 0; i < str.length; i++) {\r\n const code = str.charCodeAt(i) ^ key.charCodeAt(i % key.length)\r\n result += String.fromCharCode(code)\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Computes a simple checksum (CRC-like) for file integrity checks.\r\n *\r\n * @param input - The input string.\r\n * @returns An 8-character hex checksum.\r\n */\r\nexport function checksum(input: string): string {\r\n let crc = 0xffffffff\r\n for (let i = 0; i < input.length; i++) {\r\n crc ^= input.charCodeAt(i)\r\n for (let j = 0; j < 8; j++) {\r\n if (crc & 1) {\r\n crc = (crc >>> 1) ^ 0xedb88320\r\n } else {\r\n crc = crc >>> 1\r\n }\r\n }\r\n }\r\n return ((crc ^ 0xffffffff) >>> 0).toString(16).padStart(8, '0')\r\n}\r\n\r\n/**\r\n * Constant-time string comparison to prevent timing attacks.\r\n *\r\n * @param a - First string.\r\n * @param b - Second string.\r\n * @returns Whether the strings are equal.\r\n */\r\nexport function constantTimeEqual(a: string, b: string): boolean {\r\n if (a.length !== b.length) return false\r\n let result = 0\r\n for (let i = 0; i < a.length; i++) {\r\n result |= a.charCodeAt(i) ^ b.charCodeAt(i)\r\n }\r\n return result === 0\r\n}\r\n","const SEP = '/'\r\n\r\n/**\r\n * Joins path segments with the proper separator.\r\n *\r\n * @param segments - Path segments to join.\r\n * @returns The joined path.\r\n */\r\nexport function join(...segments: string[]): string {\r\n const parts: string[] = []\r\n for (const seg of segments) {\r\n if (seg === '') continue\r\n const split = seg.split(/[\\\\/]/)\r\n for (const part of split) {\r\n if (part === '' || part === '.') continue\r\n if (part === '..') {\r\n if (parts.length > 0 && parts[parts.length - 1] !== '..') {\r\n parts.pop()\r\n } else {\r\n parts.push('..')\r\n }\r\n } else {\r\n parts.push(part)\r\n }\r\n }\r\n }\r\n if (parts.length === 0) return '.'\r\n const result = parts.join(SEP)\r\n if (segments.length > 0 && segments[0]!.startsWith('/')) {\r\n return SEP + result\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Resolves path segments to an absolute path.\r\n *\r\n * @param segments - Path segments to resolve.\r\n * @returns The resolved absolute path.\r\n */\r\nexport function resolve(...segments: string[]): string {\r\n let resolved = ''\r\n let isAbs = false\r\n\r\n for (const seg of segments) {\r\n if (seg.startsWith('/')) {\r\n resolved = seg\r\n isAbs = true\r\n } else if (isAbs) {\r\n resolved = join(resolved, seg)\r\n } else {\r\n resolved = resolved ? join(resolved, seg) : seg\r\n }\r\n }\r\n\r\n if (!isAbs) {\r\n resolved = join(SEP, resolved)\r\n }\r\n\r\n return normalize(resolved)\r\n}\r\n\r\n/**\r\n * Returns the filename from a path.\r\n *\r\n * @param p - The path.\r\n * @param ext - Optional extension to strip.\r\n * @returns The filename.\r\n */\r\nexport function basename(p: string, ext?: string): string {\r\n const normalized = p.replace(/[\\\\/]+$/, '')\r\n const idx = normalized.lastIndexOf(SEP)\r\n let base = idx === -1 ? normalized : normalized.slice(idx + 1)\r\n if (ext && base.endsWith(ext)) {\r\n base = base.slice(0, -ext.length)\r\n }\r\n return base\r\n}\r\n\r\n/**\r\n * Returns the directory portion of a path.\r\n *\r\n * @param p - The path.\r\n * @returns The directory path.\r\n */\r\nexport function dirname(p: string): string {\r\n if (p === SEP) return SEP\r\n const normalized = p.replace(/[\\\\/]+$/, '')\r\n if (normalized === '') return '.'\r\n const idx = normalized.lastIndexOf(SEP)\r\n if (idx === -1) return '.'\r\n if (idx === 0) return SEP\r\n return normalized.slice(0, idx)\r\n}\r\n\r\n/**\r\n * Returns the file extension from a path.\r\n *\r\n * @param p - The path.\r\n * @returns The extension including the dot, or empty string.\r\n */\r\nexport function extname(p: string): string {\r\n const base = basename(p)\r\n const idx = base.lastIndexOf('.')\r\n if (idx === -1 || idx === 0) return ''\r\n return base.slice(idx)\r\n}\r\n\r\n/**\r\n * Normalizes a path, resolving '..' and '.' segments.\r\n *\r\n * @param p - The path to normalize.\r\n * @returns The normalized path.\r\n */\r\nexport function normalize(p: string): string {\r\n const parts = p.split(/[\\\\/]+/)\r\n const stack: string[] = []\r\n let isAbs = p.startsWith('/')\r\n\r\n for (const part of parts) {\r\n if (part === '' || part === '.') continue\r\n if (part === '..') {\r\n if (stack.length > 0 && stack[stack.length - 1] !== '..') {\r\n stack.pop()\r\n } else if (!isAbs) {\r\n stack.push('..')\r\n }\r\n } else {\r\n stack.push(part)\r\n }\r\n }\r\n\r\n const result = stack.join(SEP)\r\n if (isAbs) return SEP + result\r\n if (result === '') return '.'\r\n return result\r\n}\r\n\r\n/**\r\n * Checks if a path is absolute.\r\n *\r\n * @param p - The path to check.\r\n * @returns Whether the path is absolute.\r\n */\r\nexport function isAbsolute(p: string): boolean {\r\n return p.startsWith('/')\r\n}\r\n\r\n/**\r\n * Computes the relative path from `from` to `to`.\r\n *\r\n * @param from - The base path.\r\n * @param to - The target path.\r\n * @returns The relative path.\r\n */\r\nexport function relative(from: string, to: string): string {\r\n const fromParts = normalize(from).split(SEP)\r\n const toParts = normalize(to).split(SEP)\r\n\r\n let i = 0\r\n while (i < fromParts.length && i < toParts.length && fromParts[i] === toParts[i]) {\r\n i++\r\n }\r\n\r\n const up = fromParts.slice(i).map(() => '..')\r\n const down = toParts.slice(i)\r\n const result = [...up, ...down].join(SEP)\r\n\r\n return result || '.'\r\n}\r\n\r\nexport interface ParsedPath {\r\n root: string\r\n dir: string\r\n base: string\r\n name: string\r\n ext: string\r\n}\r\n\r\n/**\r\n * Parses a path into its components.\r\n *\r\n * @param p - The path to parse.\r\n * @returns An object with root, dir, base, name, and ext.\r\n */\r\nexport function parse(p: string): ParsedPath {\r\n const root = p.startsWith(SEP) ? SEP : ''\r\n const base = basename(p)\r\n const ext = extname(base)\r\n const name = ext ? base.slice(0, -ext.length) : base\r\n const dir = root ? dirname(p) : (dirname(p) === '.' ? '' : dirname(p))\r\n\r\n return { root, dir, base, name, ext }\r\n}\r\n\r\n/**\r\n * Formats a parsed path object back into a path string.\r\n *\r\n * @param parsed - The parsed path components.\r\n * @returns The formatted path string.\r\n */\r\nexport function format(parsed: Partial<ParsedPath>): string {\r\n const { root = '', dir = '', base = '', name = '', ext = '' } = parsed\r\n const baseName = base || name + ext\r\n if (dir) {\r\n return dir + SEP + baseName\r\n }\r\n return root + baseName\r\n}\r\n","/**\r\n * Groups an array of items by a key extracted from each item.\r\n *\r\n * @example groupBy([{ type: 'a' }, { type: 'b' }, { type: 'a' }], x => x.type)\r\n * // => { a: [{ type: 'a' }, { type: 'a' }], b: [{ type: 'b' }] }\r\n */\r\nexport function groupBy<T, K extends string | number | symbol>(items: T[], keyFn: (item: T) => K): Record<K, T[]> {\r\n const result = {} as Record<K, T[]>\r\n for (const item of items) {\r\n const key = keyFn(item)\r\n if (!result[key]) result[key] = []\r\n result[key]!.push(item)\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Creates an object keyed by the result of keyFn for each item.\r\n *\r\n * @example keyBy([{ id: 1, name: 'a' }, { id: 2, name: 'b' }], x => x.id)\r\n * // => { 1: { id: 1, name: 'a' }, 2: { id: 2, name: 'b' } }\r\n */\r\nexport function keyBy<T, K extends string | number | symbol>(items: T[], keyFn: (item: T) => K): Record<K, T> {\r\n const result = {} as Record<K, T>\r\n for (const item of items) {\r\n const key = keyFn(item)\r\n result[key] = item\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Returns a copy of the object with the specified keys omitted.\r\n */\r\nexport function omit<T extends Record<string, unknown>, K extends keyof T>(obj: T, keys: K[]): Omit<T, K> {\r\n const result = { ...obj } as T\r\n for (const key of keys) {\r\n delete result[key]\r\n }\r\n return result as Omit<T, K>\r\n}\r\n\r\n/**\r\n * Returns a copy of the object with only the specified keys.\r\n */\r\nexport function pick<T extends Record<string, unknown>, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {\r\n const result = {} as Pick<T, K>\r\n for (const key of keys) {\r\n if (key in obj) {\r\n result[key] = obj[key]\r\n }\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Extracts a property value from each item in an array.\r\n */\r\nexport function pluck<T, K extends keyof T>(items: T[], key: K): T[K][] {\r\n return items.map(item => item[key])\r\n}\r\n\r\n/**\r\n * Randomizes array order in-place using the Fisher-Yates algorithm.\r\n */\r\nexport function shuffle<T>(items: T[]): T[] {\r\n const result = [...items]\r\n for (let i = result.length - 1; i > 0; i--) {\r\n const j = Math.floor(Math.random() * (i + 1))\r\n const temp = result[i]!\r\n result[i] = result[j]!\r\n result[j] = temp\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Returns a random element from the array, or undefined if empty.\r\n */\r\nexport function sample<T>(items: T[]): T | undefined {\r\n return items.length > 0 ? items[Math.floor(Math.random() * items.length)] : undefined\r\n}\r\n\r\n/**\r\n * Returns an array of `size` random elements (without duplicates).\r\n */\r\nexport function sampleSize<T>(items: T[], size: number): T[] {\r\n if (size <= 0 || items.length === 0) return []\r\n const pool = shuffle(items)\r\n return pool.slice(0, Math.min(size, items.length))\r\n}\r\n\r\n/**\r\n * Splits an array into chunks of the specified size.\r\n */\r\nexport function chunk<T>(items: T[], size: number): T[][] {\r\n if (size <= 0 || items.length === 0) return []\r\n const result: T[][] = []\r\n for (let i = 0; i < items.length; i += size) {\r\n result.push(items.slice(i, i + size))\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Returns a sorted copy of the array using the provided criteria functions.\r\n * Earlier criteria take precedence.\r\n */\r\nfunction compareValues(a: unknown, b: unknown): number {\r\n if (a === b) return 0\r\n if (a == null) return -1\r\n if (b == null) return 1\r\n if (typeof a === 'string' && typeof b === 'string') return a < b ? -1 : 1\r\n if (typeof a === 'number' && typeof b === 'number') return a < b ? -1 : 1\r\n return String(a) < String(b) ? -1 : 1\r\n}\r\n\r\nexport function sortBy<T>(items: T[], ...criteria: Array<(item: T) => unknown>): T[] {\r\n return [...items].sort((a, b) => {\r\n for (const criterion of criteria) {\r\n const cmp = compareValues(criterion(a), criterion(b))\r\n if (cmp !== 0) return cmp\r\n }\r\n return 0\r\n })\r\n}\r\n\r\n/**\r\n * Returns a sorted copy of the array by a single key and direction.\r\n */\r\nexport function orderBy<T>(items: T[], key: (item: T) => unknown, direction: SortDirection = 'asc'): T[] {\r\n return [...items].sort((a, b) => {\r\n const cmp = compareValues(key(a), key(b))\r\n return direction === 'asc' ? cmp : -cmp\r\n })\r\n}\r\n\r\n/**\r\n * Returns unique elements based on the result of keyFn.\r\n */\r\nexport function uniqueBy<T>(items: T[], keyFn: (item: T) => unknown): T[] {\r\n const seen = new Set<unknown>()\r\n return items.filter(item => {\r\n const key = keyFn(item)\r\n if (seen.has(key)) return false\r\n seen.add(key)\r\n return true\r\n })\r\n}\r\n\r\n/**\r\n * Flattens an array of arrays one level.\r\n */\r\nexport function flatten<T>(items: T[][]): T[] {\r\n const result: T[] = []\r\n for (const sub of items) {\r\n for (const item of sub) {\r\n result.push(item)\r\n }\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Returns an array with unique primitive values.\r\n */\r\nexport function uniq<T>(items: T[]): T[] {\r\n return [...new Set(items)]\r\n}\r\n\r\n/**\r\n * Returns the first element, or undefined if empty.\r\n */\r\nexport function first<T>(items: T[]): T | undefined {\r\n return items[0]\r\n}\r\n\r\n/**\r\n * Returns the last element, or undefined if empty.\r\n */\r\nexport function last<T>(items: T[]): T | undefined {\r\n return items[items.length - 1]\r\n}\r\n\r\n/**\r\n * Checks if a value is empty.\r\n * Works for arrays, objects, strings, Map, and Set.\r\n */\r\nexport function isEmpty(value: unknown): boolean {\r\n if (Array.isArray(value)) return value.length === 0\r\n if (typeof value === 'string') return value.length === 0\r\n if (value instanceof Map || value instanceof Set) return value.size === 0\r\n if (value !== null && typeof value === 'object') return Object.keys(value as Record<string, unknown>).length === 0\r\n return false\r\n}\r\n\r\nexport type SortDirection = 'asc' | 'desc'\r\n","const WORD_SPLIT_RE = /[A-Z]?[a-z]+|[A-Z]+(?=[A-Z][a-z]|\\d|\\b)|\\d+/g\r\n\r\nfunction splitWords(str: string): string[] {\r\n return str.match(WORD_SPLIT_RE) ?? []\r\n}\r\n\r\n/**\r\n * Capitalizes the first character and lowercases the rest.\r\n */\r\nexport function capitalize(str: string): string {\r\n if (str.length === 0) return str\r\n return str[0]!.toUpperCase() + str.slice(1).toLowerCase()\r\n}\r\n\r\n/**\r\n * Converts a string to camelCase.\r\n */\r\nexport function camelCase(str: string): string {\r\n const words = splitWords(str)\r\n if (words.length === 0) return ''\r\n const [firstWord, ...rest] = words\r\n return firstWord!.toLowerCase() + rest.map(w => w[0]!.toUpperCase() + w.slice(1).toLowerCase()).join('')\r\n}\r\n\r\n/**\r\n * Converts a string to kebab-case.\r\n */\r\nexport function kebabCase(str: string): string {\r\n return splitWords(str).map(w => w.toLowerCase()).join('-')\r\n}\r\n\r\n/**\r\n * Converts a string to snake_case.\r\n */\r\nexport function snakeCase(str: string): string {\r\n return splitWords(str).map(w => w.toLowerCase()).join('_')\r\n}\r\n\r\n/**\r\n * Converts a string to PascalCase.\r\n */\r\nexport function pascalCase(str: string): string {\r\n return splitWords(str).map(w => w[0]!.toUpperCase() + w.slice(1).toLowerCase()).join('')\r\n}\r\n\r\n/**\r\n * Truncates a string to the specified length, appending a suffix (default \"...\").\r\n */\r\nexport function truncate(str: string, maxLength: number, suffix = '...'): string {\r\n if (str.length <= maxLength) return str\r\n return str.slice(0, Math.max(0, maxLength - suffix.length)) + suffix\r\n}\r\n\r\n/**\r\n * Simple string interpolation using {{key}} syntax.\r\n *\r\n * @example template(\"Hello {{name}}\", { name: \"world\" }) // => \"Hello world\"\r\n */\r\nexport function template(str: string, data: Record<string, string | number>): string {\r\n return str.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key: string) => {\r\n const value = data[key]\r\n return value !== undefined ? String(value) : `{{${key}}}`\r\n })\r\n}\r\n\r\n/**\r\n * Generates a UUID v4 string.\r\n * Uses crypto.randomUUID when available, falls back to manual implementation.\r\n */\r\nexport function uuid(): string {\r\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\r\n return crypto.randomUUID()\r\n }\r\n const hex = '0123456789abcdef'\r\n const chars: string[] = []\r\n for (let i = 0; i < 36; i++) {\r\n if (i === 8 || i === 13 || i === 18 || i === 23) {\r\n chars.push('-')\r\n } else if (i === 14) {\r\n chars.push('4')\r\n } else if (i === 19) {\r\n chars.push(hex[Math.floor(Math.random() * 4) + 8]!)\r\n } else {\r\n chars.push(hex[Math.floor(Math.random() * 16)]!)\r\n }\r\n }\r\n return chars.join('')\r\n}\r\n\r\n/**\r\n * Generates a short random ID with configurable length and alphabet.\r\n *\r\n * @default size = 21, alphabet = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-\"\r\n */\r\nexport function nanoid(size = 21, alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-'): string {\r\n const len = alphabet.length\r\n let result = ''\r\n for (let i = 0; i < size; i++) {\r\n result += alphabet[Math.floor(Math.random() * len)]!\r\n }\r\n return result\r\n}\r\n\r\nconst HTML_ESCAPE_MAP: Record<string, string> = {\r\n '&': '&',\r\n '<': '<',\r\n '>': '>',\r\n '\"': '"',\r\n \"'\": ''',\r\n}\r\n\r\nconst HTML_UNESCAPE_MAP: Record<string, string> = {\r\n '&': '&',\r\n '<': '<',\r\n '>': '>',\r\n '"': '\"',\r\n ''': \"'\",\r\n ''': \"'\",\r\n}\r\n\r\n/**\r\n * Escapes HTML special characters (&, <, >, \", ').\r\n */\r\nexport function escapeHtml(str: string): string {\r\n return str.replace(/[&<>\"']/g, ch => HTML_ESCAPE_MAP[ch] ?? ch)\r\n}\r\n\r\n/**\r\n * Unescapes common HTML entities.\r\n */\r\nexport function unescapeHtml(str: string): string {\r\n return str.replace(/&(?:amp|lt|gt|quot|#39|#x27);/g, entity => HTML_UNESCAPE_MAP[entity] ?? entity)\r\n}\r\n\r\n/**\r\n * Removes whitespace from both ends of a string.\r\n */\r\nexport function trim(str: string): string {\r\n return str.trim()\r\n}\r\n\r\n/**\r\n * Removes whitespace from the start of a string.\r\n */\r\nexport function trimStart(str: string): string {\r\n return str.trimStart()\r\n}\r\n\r\n/**\r\n * Removes whitespace from the end of a string.\r\n */\r\nexport function trimEnd(str: string): string {\r\n return str.trimEnd()\r\n}\r\n\r\n/**\r\n * Pads a string to the given length by adding characters to both sides.\r\n */\r\nexport function pad(str: string, length: number, char = ' '): string {\r\n const totalPadding = Math.max(0, length - str.length)\r\n const leftPad = Math.floor(totalPadding / 2)\r\n const rightPad = totalPadding - leftPad\r\n return char.repeat(leftPad) + str + char.repeat(rightPad)\r\n}\r\n\r\n/**\r\n * Pads the start of a string to the given length.\r\n */\r\nexport function padStart(str: string, length: number, char = ' '): string {\r\n return str.padStart(length, char)\r\n}\r\n\r\n/**\r\n * Pads the end of a string to the given length.\r\n */\r\nexport function padEnd(str: string, length: number, char = ' '): string {\r\n return str.padEnd(length, char)\r\n}\r\n\r\n/**\r\n * Reverses a string.\r\n */\r\nexport function reverse(str: string): string {\r\n return str.split('').reverse().join('')\r\n}\r\n\r\n/**\r\n * Splits a string into words.\r\n */\r\nexport function words(str: string): string[] {\r\n return splitWords(str)\r\n}\r\n\r\n/**\r\n * Converts a string to a URL-friendly slug.\r\n */\r\nexport function slugify(str: string): string {\r\n return str\r\n .toLowerCase()\r\n .replace(/[^\\w\\s-]/g, '')\r\n .replace(/[\\s_]+/g, '-')\r\n .replace(/-+/g, '-')\r\n .replace(/^-+/, '')\r\n .replace(/-+$/, '')\r\n}\r\n\r\n/**\r\n * Counts occurrences of a substring in a string.\r\n */\r\nexport function countOccurrences(str: string, substring: string): number {\r\n if (substring.length === 0 || str.length === 0) return 0\r\n let count = 0\r\n let pos = 0\r\n while ((pos = str.indexOf(substring, pos)) !== -1) {\r\n count++\r\n pos += substring.length\r\n }\r\n return count\r\n}\r\n","import type { RetryOptions } from '../core/index.js'\r\n\r\n/**\r\n * Delays execution for the given number of milliseconds.\r\n */\r\nexport function sleep(ms: number): Promise<void> {\r\n return new Promise(resolve => setTimeout(resolve, ms))\r\n}\r\n\r\n/**\r\n * Rejects a promise if it does not resolve within the specified timeout.\r\n */\r\nexport async function timeout<T>(promise: Promise<T>, ms: number, errorMessage?: string): Promise<T> {\r\n let timer: ReturnType<typeof setTimeout> | undefined\r\n const timeoutPromise = new Promise<never>((_, reject) => {\r\n timer = setTimeout(() => reject(new Error(errorMessage ?? `Promise timed out after ${ms}ms`)), ms)\r\n })\r\n try {\r\n return await Promise.race([promise, timeoutPromise])\r\n } finally {\r\n if (timer !== undefined) clearTimeout(timer)\r\n }\r\n}\r\n\r\n/**\r\n * Races a promise against a timeout, returning 'timeout' if the timer wins.\r\n */\r\nexport async function raceWithTimeout<T>(promise: Promise<T>, ms: number): Promise<T | 'timeout'> {\r\n let timer: ReturnType<typeof setTimeout> | undefined\r\n const timeoutPromise = new Promise<'timeout'>(resolve => {\r\n timer = setTimeout(() => resolve('timeout'), ms)\r\n })\r\n try {\r\n return await Promise.race([promise, timeoutPromise])\r\n } finally {\r\n if (timer !== undefined) clearTimeout(timer)\r\n }\r\n}\r\n\r\n/**\r\n * Maps over an array with an async function, using Promise.allSettled.\r\n * Returns an array of PromiseSettledResult.\r\n */\r\nexport async function allSettledMap<T, R>(\r\n items: T[],\r\n fn: (item: T) => Promise<R>,\r\n): Promise<PromiseSettledResult<R>[]> {\r\n return await Promise.allSettled(items.map(fn))\r\n}\r\n\r\n/**\r\n * Maps over an array with an async function, limiting concurrency.\r\n *\r\n * @param concurrency - Maximum number of concurrent operations (default Infinity)\r\n */\r\nexport async function parallelMap<T, R>(\r\n items: T[],\r\n fn: (item: T) => Promise<R>,\r\n concurrency = Number.POSITIVE_INFINITY,\r\n): Promise<R[]> {\r\n if (concurrency === Number.POSITIVE_INFINITY) {\r\n return await Promise.all(items.map(fn))\r\n }\r\n\r\n const results: R[] = []\r\n const queue = [...items]\r\n\r\n const worker = async (): Promise<void> => {\r\n while (queue.length > 0) {\r\n const item = queue.shift()!\r\n results.push(await fn(item))\r\n }\r\n }\r\n\r\n const workerCount = Math.min(concurrency, items.length)\r\n const workers = Array.from({ length: workerCount }, () => worker())\r\n await Promise.all(workers)\r\n return results\r\n}\r\n\r\n/**\r\n * Retries an async function with exponential backoff.\r\n */\r\nexport async function retryAsync<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T> {\r\n const { attempts = 3, baseDelay = 1000, maxDelay = 30000, shouldRetry = () => true } = options ?? {}\r\n let lastError: unknown\r\n for (let attempt = 0; attempt < attempts; attempt++) {\r\n try {\r\n return await fn()\r\n } catch (error) {\r\n lastError = error\r\n if (!shouldRetry(error) || attempt >= attempts - 1) break\r\n const delay = Math.min(baseDelay * 2 ** attempt + Math.random() * baseDelay, maxDelay)\r\n await sleep(delay)\r\n }\r\n }\r\n throw lastError\r\n}\r\n\r\n/**\r\n * Composes async functions, passing the result of each to the next.\r\n */\r\nexport async function pipeline<T>(initial: T, ...fns: Array<(arg: T) => Promise<T>>): Promise<T> {\r\n let result = initial\r\n for (const fn of fns) {\r\n result = await fn(result)\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Creates a deferred promise with external resolve and reject methods.\r\n */\r\nexport function deferred<T>(): Deferred<T> {\r\n let resolve!: (value: T) => void\r\n let reject!: (reason: unknown) => void\r\n const promise = new Promise<T>((res, rej) => {\r\n resolve = res\r\n reject = rej\r\n })\r\n return { promise, resolve, reject }\r\n}\r\n\r\nexport interface Deferred<T> {\r\n promise: Promise<T>\r\n resolve: (value: T) => void\r\n reject: (reason: unknown) => void\r\n}\r\n","/**\r\n * Options for CSV parsing.\r\n */\r\nexport interface CsvOptions {\r\n delimiter?: string\r\n header?: boolean\r\n skipEmptyLines?: boolean\r\n}\r\n\r\n/**\r\n * Parses a CSV string into an array of records (objects).\r\n *\r\n * @param input - CSV string\r\n * @param options - Optional parsing options\r\n */\r\nexport function parseCsv(input: string, options?: CsvOptions): Record<string, string>[] {\r\n const { delimiter = ',', header = true, skipEmptyLines = true } = options ?? {}\r\n\r\n const lines = input.split(/\\r?\\n/)\r\n const rows: string[][] = []\r\n\r\n for (const line of lines) {\r\n const trimmed = line.trim()\r\n if (skipEmptyLines && trimmed.length === 0) continue\r\n const values = parseCsvLine(trimmed, delimiter)\r\n rows.push(values)\r\n }\r\n\r\n if (rows.length === 0) return []\r\n\r\n if (header) {\r\n const [head, ...body] = rows\r\n if (head === undefined) return []\r\n return body.map(row => {\r\n const record: Record<string, string> = {}\r\n for (let i = 0; i < head.length; i++) {\r\n record[head[i]!] = row[i] ?? ''\r\n }\r\n return record\r\n })\r\n }\r\n\r\n return rows.map(row => {\r\n const record: Record<string, string> = {}\r\n for (let i = 0; i < row.length; i++) {\r\n record[String(i)] = row[i]!\r\n }\r\n return record\r\n })\r\n}\r\n\r\nfunction parseCsvLine(line: string, delimiter: string): string[] {\r\n const result: string[] = []\r\n let current = ''\r\n let inQuotes = false\r\n\r\n for (let i = 0; i < line.length; i++) {\r\n const ch = line[i]!\r\n if (inQuotes) {\r\n if (ch === '\"') {\r\n if (line[i + 1] === '\"') {\r\n current += '\"'\r\n i++\r\n } else {\r\n inQuotes = false\r\n }\r\n } else {\r\n current += ch\r\n }\r\n } else {\r\n if (ch === '\"') {\r\n inQuotes = true\r\n } else if (ch === delimiter) {\r\n result.push(current)\r\n current = ''\r\n } else {\r\n current += ch\r\n }\r\n }\r\n }\r\n result.push(current)\r\n return result\r\n}\r\n\r\n/**\r\n * Converts an array of records to a CSV string.\r\n */\r\nexport function stringifyCsv(data: Record<string, unknown>[], options?: { delimiter?: string }): string {\r\n const { delimiter = ',' } = options ?? {}\r\n if (data.length === 0) return ''\r\n\r\n const headers = Object.keys(data[0]!)\r\n const lines: string[] = [headers.map(v => escapeCsvField(v, delimiter)).join(delimiter)]\r\n\r\n for (const record of data) {\r\n const row = headers.map(h => escapeCsvField(String(record[h] ?? ''), delimiter))\r\n lines.push(row.join(delimiter))\r\n }\r\n\r\n return lines.join('\\n')\r\n}\r\n\r\nfunction escapeCsvField(value: string, delimiter: string): string {\r\n if (value.includes('\"') || value.includes(delimiter) || value.includes('\\n') || value.includes('\\r')) {\r\n return '\"' + value.replace(/\"/g, '\"\"') + '\"'\r\n }\r\n return value\r\n}\r\n\r\n/**\r\n * Safely parses a JSON string, returning the default value or null on failure.\r\n */\r\nexport function safeJsonParse<T>(input: string, default_?: T): T | null {\r\n try {\r\n return JSON.parse(input) as T\r\n } catch {\r\n return default_ ?? null\r\n }\r\n}\r\n\r\n/**\r\n * Reads an environment variable with optional default.\r\n */\r\nexport function env(name: string, default_?: string): string {\r\n const value = process.env[name]\r\n return value ?? default_ ?? ''\r\n}\r\n\r\n/**\r\n * Reads an environment variable as an integer.\r\n */\r\nexport function envInt(name: string, default_?: number): number {\r\n const value = process.env[name]\r\n if (value === undefined || value === '') return default_ ?? 0\r\n const parsed = Number.parseInt(value, 10)\r\n return Number.isNaN(parsed) ? (default_ ?? 0) : parsed\r\n}\r\n\r\n/**\r\n * Reads an environment variable as a boolean.\r\n */\r\nexport function envBool(name: string, default_?: boolean): boolean {\r\n const value = process.env[name]\r\n if (value === undefined || value === '') return default_ ?? false\r\n return value === 'true' || value === '1' || value === 'yes'\r\n}\r\n","/**\r\n * Checks if a value is a string.\r\n */\r\nexport function isString(value: unknown): value is string {\r\n return typeof value === 'string'\r\n}\r\n\r\n/**\r\n * Checks if a value is a number (not NaN, not Infinity).\r\n */\r\nexport function isNumber(value: unknown): value is number {\r\n return typeof value === 'number' && Number.isFinite(value)\r\n}\r\n\r\n/**\r\n * Checks if a value is a boolean.\r\n */\r\nexport function isBoolean(value: unknown): value is boolean {\r\n return typeof value === 'boolean'\r\n}\r\n\r\n/**\r\n * Checks if a value is a plain object (not null, not array, typeof 'object').\r\n */\r\nexport function isObject(value: unknown): value is Record<string, unknown> {\r\n return value !== null && typeof value === 'object' && !Array.isArray(value)\r\n}\r\n\r\n/**\r\n * Checks if a value is an array.\r\n */\r\nexport function isArray(value: unknown): value is unknown[] {\r\n return Array.isArray(value)\r\n}\r\n\r\n/**\r\n * Checks if a value is a function.\r\n */\r\nexport function isFunction(value: unknown): value is (...args: unknown[]) => unknown {\r\n return typeof value === 'function'\r\n}\r\n\r\n/**\r\n * Checks if a value is a Date.\r\n */\r\nexport function isDate(value: unknown): value is Date {\r\n return value instanceof Date && !Number.isNaN(value.getTime())\r\n}\r\n\r\n/**\r\n * Checks if a value is a RegExp.\r\n */\r\nexport function isRegExp(value: unknown): value is RegExp {\r\n return value instanceof RegExp\r\n}\r\n\r\n/**\r\n * Checks if a value is a Map.\r\n */\r\nexport function isMap(value: unknown): value is Map<unknown, unknown> {\r\n return value instanceof Map\r\n}\r\n\r\n/**\r\n * Checks if a value is a Set.\r\n */\r\nexport function isSet(value: unknown): value is Set<unknown> {\r\n return value instanceof Set\r\n}\r\n\r\n/**\r\n * Checks if a value is a Promise.\r\n */\r\nexport function isPromise(value: unknown): value is Promise<unknown> {\r\n return value instanceof Promise\r\n}\r\n\r\n/**\r\n * Checks if a value is null.\r\n */\r\nexport function isNull(value: unknown): value is null {\r\n return value === null\r\n}\r\n\r\n/**\r\n * Checks if a value is undefined.\r\n */\r\nexport function isUndefined(value: unknown): value is undefined {\r\n return value === undefined\r\n}\r\n\r\n/**\r\n * Checks if a value is null or undefined.\r\n */\r\nexport function isNil(value: unknown): value is null | undefined {\r\n return value === null || value === undefined\r\n}\r\n\r\n/**\r\n * Checks if a value is empty.\r\n * Works for strings, arrays, objects, Map, and Set.\r\n */\r\nexport function isEmpty(value: unknown): boolean {\r\n if (value === null || value === undefined) return true\r\n if (typeof value === 'string') return value.length === 0\r\n if (Array.isArray(value)) return value.length === 0\r\n if (value instanceof Map || value instanceof Set) return value.size === 0\r\n if (typeof value === 'object') return Object.keys(value as Record<string, unknown>).length === 0\r\n return false\r\n}\r\n\r\n/**\r\n * Asserts that a value is defined (not null or undefined).\r\n * Throws if the value is null or undefined.\r\n */\r\nexport function assertDefined<T>(value: T, message?: string): asserts value is NonNullable<T> {\r\n if (value === null || value === undefined) {\r\n throw new Error(message ?? 'Expected value to be defined')\r\n }\r\n}\r\n\r\n/**\r\n * Asserts that a value matches a type guard. Throws if it doesn't.\r\n */\r\nexport function assertType<T>(value: unknown, guard: (v: unknown) => v is T, message?: string): asserts value is T {\r\n if (!guard(value)) {\r\n throw new Error(message ?? 'Value does not match expected type')\r\n }\r\n}\r\n\r\n/**\r\n * Wraps a value in an array if it is not already one.\r\n */\r\nexport function ensureArray<T>(value: T | T[]): T[] {\r\n return Array.isArray(value) ? value : [value]\r\n}\r\n\r\n/**\r\n * Alias for ensureArray.\r\n */\r\nexport function castArray<T>(value: T | T[]): T[] {\r\n return ensureArray(value)\r\n}\r\n\r\n/**\r\n * Returns a string representation of the value's type.\r\n *\r\n * Possible values: \"string\", \"number\", \"boolean\", \"array\", \"object\", \"function\",\r\n * \"date\", \"regexp\", \"map\", \"set\", \"promise\", \"null\", \"undefined\", \"nan\", \"infinity\"\r\n */\r\nexport function getType(value: unknown): string {\r\n if (value === null) return 'null'\r\n if (value === undefined) return 'undefined'\r\n if (typeof value === 'string') return 'string'\r\n if (typeof value === 'boolean') return 'boolean'\r\n if (typeof value === 'function') return 'function'\r\n if (typeof value === 'number') {\r\n if (Number.isNaN(value)) return 'nan'\r\n if (!Number.isFinite(value)) return 'infinity'\r\n return 'number'\r\n }\r\n if (Array.isArray(value)) return 'array'\r\n if (value instanceof Date) return 'date'\r\n if (value instanceof RegExp) return 'regexp'\r\n if (value instanceof Map) return 'map'\r\n if (value instanceof Set) return 'set'\r\n if (value instanceof Promise) return 'promise'\r\n return 'object'\r\n}\r\n","import { readFileSync, readdirSync, existsSync } from 'node:fs'\r\nimport { join, basename } from 'node:path'\r\nimport type { ScanResult, ReplacementSuggestion, SecurityIssue, ScannerConfig } from '../types.js'\r\nimport { KNOWN_MAPPINGS, KNOWN_CVES, type PackageMapping } from '../known-mappings.js'\r\n\r\ninterface LockfilePackages {\r\n [key: string]: { version?: string; dependencies?: Record<string, string> } | undefined\r\n}\r\n\r\ninterface LockfileData {\r\n packages: LockfilePackages\r\n}\r\n\r\nfunction parsePackageJson(path: string): { name: string; dependencies: Record<string, string>; devDependencies: Record<string, string> } {\r\n const raw = readFileSync(path, 'utf-8')\r\n const json = JSON.parse(raw)\r\n return {\r\n name: json.name ?? basename(join(path, '..')),\r\n dependencies: (json.dependencies as Record<string, string>) ?? {},\r\n devDependencies: (json.devDependencies as Record<string, string>) ?? {},\r\n }\r\n}\r\n\r\nfunction parseLockfile(projectPath: string): LockfileData | null {\r\n const lockPath = join(projectPath, 'package-lock.json')\r\n if (!existsSync(lockPath)) return null\r\n try {\r\n const raw = readFileSync(lockPath, 'utf-8')\r\n const json = JSON.parse(raw)\r\n const packages: LockfilePackages = {}\r\n\r\n if (json.packages) {\r\n for (const [key, val] of Object.entries(json.packages as Record<string, { version?: string }>)) {\r\n if (key) {\r\n packages[key] = val\r\n }\r\n }\r\n }\r\n\r\n if (json.dependencies && Object.keys(packages).length === 0) {\r\n for (const [key, val] of Object.entries(json.dependencies as Record<string, { version?: string; requires?: Record<string, string> }>)) {\r\n packages[key] = { version: val.version, dependencies: val.requires }\r\n }\r\n }\r\n\r\n return { packages }\r\n } catch {\r\n return null\r\n }\r\n}\r\n\r\nfunction detectImportInFile(filePath: string, regex: RegExp): boolean {\r\n try {\r\n const content = readFileSync(filePath, 'utf-8')\r\n return regex.test(content)\r\n } catch {\r\n return false\r\n }\r\n}\r\n\r\nfunction detectImportsInSrc(projectPath: string, mapping: PackageMapping): boolean {\r\n const regex = new RegExp(mapping.detectionPattern)\r\n const srcDir = join(projectPath, 'src')\r\n if (!existsSync(srcDir)) return false\r\n\r\n try {\r\n const files = collectSourceFiles(srcDir)\r\n for (const file of files) {\r\n if (detectImportInFile(file, regex)) return true\r\n }\r\n } catch {\r\n return false\r\n }\r\n return false\r\n}\r\n\r\nfunction collectSourceFiles(dir: string): string[] {\r\n const results: string[] = []\r\n try {\r\n const entries = readdirSync(dir, { withFileTypes: true })\r\n for (const entry of entries) {\r\n if (entry.name === 'node_modules' || entry.name === 'dist' || entry.name === '.git' || entry.name === 'coverage' || entry.name === '.tsup') {\r\n continue\r\n }\r\n const full = join(dir, entry.name)\r\n if (entry.isDirectory()) {\r\n results.push(...collectSourceFiles(full))\r\n } else if (entry.isFile()) {\r\n const ext = entry.name.split('.').pop()\r\n if (ext === 'ts' || ext === 'tsx' || ext === 'js' || ext === 'jsx' || ext === 'mjs' || ext === 'cjs') {\r\n results.push(full)\r\n }\r\n }\r\n }\r\n } catch {\r\n // skip inaccessible dirs\r\n }\r\n return results\r\n}\r\n\r\nfunction estimateTransitiveCount(lockfile: LockfileData | null, directNames: Set<string>): number {\r\n if (!lockfile) return 0\r\n let count = 0\r\n for (const key of Object.keys(lockfile.packages)) {\r\n if (!key || key === '') continue\r\n const name = key.startsWith('node_modules/') ? key.slice('node_modules/'.length) : key\r\n const rootName = name.startsWith('@') ? `${name.split('/')[0]}/${name.split('/')[1]}` : name.split('/')[0]\r\n if (rootName && !directNames.has(rootName)) {\r\n count++\r\n }\r\n }\r\n return count\r\n}\r\n\r\nfunction parseSize(value: string): number {\r\n const cleaned = value.replace(/\\(.*?\\)/g, '').trim()\r\n const match = cleaned.match(/^([\\d.]+)\\s*(KB|MB)/i)\r\n if (!match) return 0\r\n const num = Number.parseFloat(match[1]!)\r\n if (!match[2]) return 0\r\n if (match[2].toUpperCase() === 'MB') return num * 1024\r\n return num\r\n}\r\n\r\nexport async function scanProject(config: ScannerConfig): Promise<ScanResult> {\r\n const projectPath = config.path ?? '.'\r\n const pkgPath = join(projectPath, 'package.json')\r\n\r\n if (!existsSync(pkgPath)) {\r\n throw new Error(`No package.json found at ${projectPath}. Run dep-exray in a JavaScript/TypeScript project directory.`)\r\n }\r\n\r\n const pkg = parsePackageJson(pkgPath)\r\n const lockfile = parseLockfile(projectPath)\r\n\r\n const allDeps: Record<string, string> = { ...pkg.dependencies, ...pkg.devDependencies }\r\n const directNames = new Set(Object.keys(allDeps))\r\n\r\n const transitiveCount = estimateTransitiveCount(lockfile, directNames)\r\n\r\n const highImpactReplacements: ReplacementSuggestion[] = []\r\n const mediumImpactReplacements: ReplacementSuggestion[] = []\r\n const securityIssues: SecurityIssue[] = []\r\n\r\n const sizeMap: Record<string, string> = {}\r\n for (const m of KNOWN_MAPPINGS) {\r\n sizeMap[m.name] = m.size\r\n }\r\n\r\n for (const mapping of KNOWN_MAPPINGS) {\r\n const isDirect = directNames.has(mapping.name)\r\n if (!isDirect) continue\r\n\r\n const isUsed = detectImportsInSrc(projectPath, mapping)\r\n if (!isUsed && !config.verbose) continue\r\n\r\n const mappingSize = parseSize(sizeMap[mapping.name] ?? '0 KB')\r\n const replacementSize = mapping.replacement.startsWith('native') ? 0 : 5\r\n const reductionStr = mappingSize > 1024\r\n ? `${(mappingSize / 1024).toFixed(1)} MB → ${replacementSize} KB`\r\n : `${mappingSize.toFixed(0)} KB → ${replacementSize} KB`\r\n\r\n const suggestion: ReplacementSuggestion = {\r\n packageName: mapping.name,\r\n reason: mapping.reason,\r\n replacement: mapping.replacement,\r\n estimatedSizeReduction: reductionStr,\r\n confidence: mapping.confidence,\r\n autoPrReady: mapping.autoPrReady,\r\n }\r\n\r\n if (mapping.confidence === 'high') {\r\n highImpactReplacements.push(suggestion)\r\n } else {\r\n mediumImpactReplacements.push(suggestion)\r\n }\r\n }\r\n\r\n for (const [name, cves] of Object.entries(KNOWN_CVES)) {\r\n if (directNames.has(name)) {\r\n for (const cveItem of cves) {\r\n securityIssues.push({\r\n packageName: name,\r\n cveId: cveItem.cve,\r\n severity: cveItem.severity as SecurityIssue['severity'],\r\n fix: cveItem.fix,\r\n })\r\n }\r\n }\r\n }\r\n\r\n let totalSizeKB = 0\r\n for (const depName of directNames) {\r\n const sizeStr = sizeMap[depName]\r\n if (sizeStr) {\r\n totalSizeKB += parseSize(sizeStr)\r\n } else {\r\n totalSizeKB += 50\r\n }\r\n }\r\n totalSizeKB += transitiveCount * 30\r\n\r\n const totalSizeStr = totalSizeKB > 1024\r\n ? `${(totalSizeKB / 1024).toFixed(1)} MB`\r\n : `${totalSizeKB.toFixed(0)} KB`\r\n\r\n return {\r\n projectName: pkg.name,\r\n directDeps: directNames.size,\r\n transitiveDeps: transitiveCount,\r\n totalEstimatedSize: totalSizeStr,\r\n highImpactReplacements,\r\n mediumImpactReplacements,\r\n securityIssues,\r\n }\r\n}\r\n","\r\n\r\nexport interface PackageMapping {\r\n name: string\r\n size: string\r\n replacement: string\r\n confidence: 'high' | 'medium' | 'low'\r\n autoPrReady: boolean\r\n reason: string\r\n detectionPattern: string\r\n}\r\n\r\nexport const KNOWN_MAPPINGS: PackageMapping[] = [\r\n {\r\n name: 'lodash',\r\n size: '4.2 MB',\r\n replacement: 'jscore-core',\r\n confidence: 'high',\r\n autoPrReady: true,\r\n reason: 'Most lodash functions have direct replacements in jscore-core with 99% API compatibility',\r\n detectionPattern: 'from [\\'\"]lodash[\\'\"]|require\\\\([\\'\"]lodash[\\'\"]\\\\)',\r\n },\r\n {\r\n name: 'moment',\r\n size: '2.5 MB',\r\n replacement: 'jscore-core/date',\r\n confidence: 'high',\r\n autoPrReady: true,\r\n reason: 'date utilities in jscore-core cover 95% of common moment use cases',\r\n detectionPattern: 'from [\\'\"]moment[\\'\"]|require\\\\([\\'\"]moment[\\'\"]\\\\)',\r\n },\r\n {\r\n name: 'date-fns',\r\n size: '1.2 MB (tree-shaked ~50KB)',\r\n replacement: 'jscore-core/date',\r\n confidence: 'medium',\r\n autoPrReady: false,\r\n reason: 'Partially overlapping — jscore-core covers basic date ops but not all locale support',\r\n detectionPattern: 'from [\\'\"]date-fns[\\'\"]|require\\\\([\\'\"]date-fns[\\'\"]\\\\)',\r\n },\r\n {\r\n name: 'axios',\r\n size: '1.6 MB',\r\n replacement: 'native fetch + jscore-core/async/retry',\r\n confidence: 'medium',\r\n autoPrReady: false,\r\n reason: 'Native fetch covers most use cases; needs manual review for interceptors',\r\n detectionPattern: 'from [\\'\"]axios[\\'\"]|require\\\\([\\'\"]axios[\\'\"]\\\\)',\r\n },\r\n {\r\n name: 'uuid',\r\n size: '30 KB',\r\n replacement: 'crypto.randomUUID() (native)',\r\n confidence: 'high',\r\n autoPrReady: true,\r\n reason: 'crypto.randomUUID() is available in all modern Node.js and browsers',\r\n detectionPattern: 'from [\\'\"]uuid[\\'\"]|require\\\\([\\'\"]uuid[\\'\"]\\\\)',\r\n },\r\n {\r\n name: 'deepmerge',\r\n size: '15 KB',\r\n replacement: 'jscore-core',\r\n confidence: 'high',\r\n autoPrReady: true,\r\n reason: 'jscore-core provides deepMerge out of the box',\r\n detectionPattern: 'from [\\'\"]deepmerge[\\'\"]|require\\\\([\\'\"]deepmerge[\\'\"]\\\\)',\r\n },\r\n {\r\n name: 'lodash.merge',\r\n size: '25 KB',\r\n replacement: 'jscore-core',\r\n confidence: 'high',\r\n autoPrReady: true,\r\n reason: 'jscore-core provides deepMerge out of the box',\r\n detectionPattern: 'from [\\'\"]lodash\\\\.(merge|clone|pick|omit|get|set)[\\'\"]',\r\n },\r\n {\r\n name: 'chalk',\r\n size: '45 KB',\r\n replacement: 'picocolors',\r\n confidence: 'medium',\r\n autoPrReady: false,\r\n reason: \"picocolors is 3KB vs chalk's 45KB with same API\",\r\n detectionPattern: 'from [\\'\"]chalk[\\'\"]|require\\\\([\\'\"]chalk[\\'\"]\\\\)',\r\n },\r\n {\r\n name: 'nanoid',\r\n size: '8 KB',\r\n replacement: 'jscore-core/string (nanoid)',\r\n confidence: 'high',\r\n autoPrReady: true,\r\n reason: 'jscore-core provides nanoid with same API',\r\n detectionPattern: 'from [\\'\"]nanoid[\\'\"]|require\\\\([\\'\"]nanoid[\\'\"]\\\\)',\r\n },\r\n {\r\n name: 'dayjs',\r\n size: '50 KB',\r\n replacement: 'jscore-core/date',\r\n confidence: 'medium',\r\n autoPrReady: false,\r\n reason: 'Partially overlapping — covers basics but not all plugins',\r\n detectionPattern: 'from [\\'\"]dayjs[\\'\"]|require\\\\([\\'\"]dayjs[\\'\"]\\\\)',\r\n },\r\n {\r\n name: 'clsx',\r\n size: '5 KB',\r\n replacement: 'native template literals',\r\n confidence: 'high',\r\n autoPrReady: true,\r\n reason: 'Can be replaced with simple template literal conditional pattern',\r\n detectionPattern: 'from [\\'\"]clsx[\\'\"]|require\\\\([\\'\"]clsx[\\'\"]\\\\)',\r\n },\r\n]\r\n\r\nexport const KNOWN_CVES: Record<string, { cve: string; severity: string; fix: string }[]> = {\r\n 'ansi-regex': [\r\n { cve: 'CVE-2021-3807', severity: 'high', fix: 'Update to ansi-regex@6.0.1 or later' },\r\n ],\r\n 'semver': [\r\n { cve: 'CVE-2022-25883', severity: 'medium', fix: 'Update to semver@7.5.2 or later' },\r\n ],\r\n 'json5': [\r\n { cve: 'CVE-2022-46175', severity: 'high', fix: 'Update to json5@2.2.3 or later' },\r\n ],\r\n 'lodash': [\r\n { cve: 'CVE-2020-28502', severity: 'high', fix: 'Update to lodash@4.17.21 or later' },\r\n { cve: 'CVE-2020-8203', severity: 'medium', fix: 'Update to lodash@4.17.21 or later' },\r\n ],\r\n}\r\n","import pc from 'picocolors'\r\nimport type { ScanResult, ReplacementSuggestion, SecurityIssue } from '../types.js'\r\n\r\nfunction severityColor(severity: SecurityIssue['severity']): string {\r\n switch (severity) {\r\n case 'critical': return pc.bold(pc.red(severity.toUpperCase()))\r\n case 'high': return pc.red(severity.toUpperCase())\r\n case 'medium': return pc.yellow(severity.toUpperCase())\r\n case 'low': return pc.dim(severity.toUpperCase())\r\n }\r\n}\r\n\r\nfunction confidenceIcon(confidence: ReplacementSuggestion['confidence']): string {\r\n switch (confidence) {\r\n case 'high': return pc.green('●')\r\n case 'medium': return pc.yellow('●')\r\n case 'low': return pc.red('●')\r\n }\r\n}\r\n\r\nexport function generateReport(result: ScanResult, jsonOutput?: boolean): string {\r\n if (jsonOutput) {\r\n return JSON.stringify(result, null, 2)\r\n }\r\n\r\n const lines: string[] = []\r\n\r\n // ┌─┐│└┘─\r\n lines.push(pc.bold(pc.cyan(`┌${'─'.repeat(58)}┐`)))\r\n lines.push(pc.bold(pc.cyan(`│${' '.repeat(18)}dep-exray Report${' '.repeat(21)}│`)))\r\n lines.push(pc.bold(pc.cyan(`├${'─'.repeat(58)}┤`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.white('📦 PROJECT:')} ${pc.bold(result.projectName)}${' '.repeat(Math.max(1, 47 - result.projectName.length))}│`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.white('📊 DEPENDENCIES:')} ${pc.bold(String(result.directDeps))} direct + ${pc.bold(String(result.transitiveDeps))} transitive${' '.repeat(Math.max(1, 27 - String(result.transitiveDeps).length))}│`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.white('💾 TOTAL SIZE:')} ${pc.bold(result.totalEstimatedSize)}${' '.repeat(Math.max(1, 42 - result.totalEstimatedSize.length))}│`)))\r\n lines.push(pc.bold(pc.cyan(`├${'─'.repeat(58)}┤`)))\r\n\r\n if (result.highImpactReplacements.length > 0) {\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.green('🟢')} ${pc.bold(pc.green('HIGH IMPACT REPLACEMENTS'))}${' '.repeat(23)}│`)))\r\n for (const item of result.highImpactReplacements) {\r\n const autoPr = item.autoPrReady ? pc.green('✓ Auto-PR ready') : pc.dim('Manual review needed')\r\n const confIcon = confidenceIcon(item.confidence)\r\n lines.push(pc.bold(pc.cyan(`├${'─'.repeat(58)}┤`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.red('✗')} ${pc.bold(item.packageName)} (${item.estimatedSizeReduction})${' '.repeat(Math.max(1, 38 - item.estimatedSizeReduction.length))}│`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.dim('→')} ${pc.cyan(item.replacement)}${' '.repeat(Math.max(1, 51 - item.replacement.length))}│`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.dim('└─')} ${autoPr} ${confIcon} ${item.confidence}${' '.repeat(Math.max(1, 35))}│`)))\r\n }\r\n }\r\n\r\n if (result.mediumImpactReplacements.length > 0) {\r\n lines.push(pc.bold(pc.cyan(`├${'─'.repeat(58)}┤`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.yellow('🟡')} ${pc.bold(pc.yellow('MEDIUM IMPACT REPLACEMENTS'))}${' '.repeat(20)}│`)))\r\n for (const item of result.mediumImpactReplacements) {\r\n const autoPr = item.autoPrReady ? pc.green('✓ Auto-PR ready') : pc.dim('Manual review needed')\r\n const confIcon = confidenceIcon(item.confidence)\r\n lines.push(pc.bold(pc.cyan(`├${'─'.repeat(58)}┤`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.red('✗')} ${pc.bold(item.packageName)} (${item.estimatedSizeReduction})${' '.repeat(Math.max(1, 38 - item.estimatedSizeReduction.length))}│`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.dim('→')} ${pc.cyan(item.replacement)}${' '.repeat(Math.max(1, 51 - item.replacement.length))}│`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.dim('└─')} ${autoPr} ${confIcon} ${item.confidence}${' '.repeat(Math.max(1, 35))}│`)))\r\n }\r\n }\r\n\r\n if (result.securityIssues.length > 0) {\r\n lines.push(pc.bold(pc.cyan(`├${'─'.repeat(58)}┤`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.red('🔴')} ${pc.bold(pc.red('SECURITY ISSUES'))}${' '.repeat(33)}│`)))\r\n for (const issue of result.securityIssues) {\r\n lines.push(pc.bold(pc.cyan(`├${'─'.repeat(58)}┤`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${severityColor(issue.severity)} ${pc.bold(issue.cveId)} in ${issue.packageName}${' '.repeat(Math.max(1, 40 - issue.packageName.length))}│`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.dim('→')} ${issue.fix}${' '.repeat(Math.max(1, 52 - issue.fix.length))}│`)))\r\n }\r\n }\r\n\r\n lines.push(pc.bold(pc.cyan(`└${'─'.repeat(58)}┘`)))\r\n\r\n return lines.join('\\n')\r\n}\r\n","import { readFileSync } from 'node:fs'\r\nimport { readdirSync, statSync } from 'node:fs'\r\nimport { join, extname } from 'node:path'\r\n\r\nconst SOURCE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'])\r\n\r\nfunction isSourceFile(file: string): boolean {\r\n return SOURCE_EXTENSIONS.has(extname(file))\r\n}\r\n\r\nfunction collectSourceFiles(dir: string): string[] {\r\n const results: string[] = []\r\n try {\r\n const entries = readdirSync(dir, { withFileTypes: true })\r\n for (const entry of entries) {\r\n const fullPath = join(dir, entry.name)\r\n if (entry.name === 'node_modules' || entry.name === 'dist' || entry.name === '.git' || entry.name === 'coverage' || entry.name === '.tsup') {\r\n continue\r\n }\r\n if (entry.isDirectory()) {\r\n results.push(...collectSourceFiles(fullPath))\r\n } else if (entry.isFile() && isSourceFile(entry.name)) {\r\n results.push(fullPath)\r\n }\r\n }\r\n } catch {\r\n // skip directories we can't read\r\n }\r\n return results\r\n}\r\n\r\nfunction escapeRegex(str: string): string {\r\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\r\n}\r\n\r\nexport async function analyzeUsage(\r\n projectPath: string,\r\n packageName: string,\r\n): Promise<{\r\n isUsed: boolean\r\n importCount: number\r\n importLocations: string[]\r\n}> {\r\n const importLocations: string[] = []\r\n const escaped = escapeRegex(packageName)\r\n const importRegex = new RegExp(\r\n `(?:from\\\\s+['\"]${escaped}(?:/['\"]|['\"])|require\\\\(\\\\s*['\"]${escaped}(?:/|['\"]))`,\r\n 'g',\r\n )\r\n\r\n const srcDir = join(projectPath, 'src')\r\n let files: string[]\r\n try {\r\n if (statSync(srcDir).isDirectory()) {\r\n files = collectSourceFiles(srcDir)\r\n } else {\r\n files = collectSourceFiles(projectPath)\r\n }\r\n } catch {\r\n files = collectSourceFiles(projectPath)\r\n }\r\n\r\n for (const file of files) {\r\n try {\r\n const content = readFileSync(file, 'utf-8')\r\n importRegex.lastIndex = 0\r\n if (importRegex.test(content)) {\r\n importLocations.push(file)\r\n }\r\n } catch {\r\n // skip unreadable files\r\n }\r\n }\r\n\r\n return {\r\n isUsed: importLocations.length > 0,\r\n importCount: importLocations.length,\r\n importLocations,\r\n }\r\n}\r\n"],"mappings":"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","names":["resolve","format","pad","sub","words","resolve","getType","join","basename","basename","join","readFileSync","readdirSync","join","extname","collectSourceFiles"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/index.ts","../src/math/index.ts","../src/date/index.ts","../src/crypto/index.ts","../src/path/index.ts","../src/collection/index.ts","../src/string/index.ts","../src/async/index.ts","../src/io/index.ts","../src/type/index.ts","../src/dep-exray/scanner/index.ts","../src/dep-exray/known-mappings.ts","../src/dep-exray/reporter/index.ts","../src/dep-exray/analyzer/index.ts"],"sourcesContent":["export interface DebounceOptions {\r\n leading?: boolean\r\n trailing?: boolean\r\n maxWait?: number\r\n}\r\n\r\nexport interface DebouncedFunction<T extends (...args: unknown[]) => unknown> {\r\n (...args: Parameters<T>): void\r\n cancel(): void\r\n flush(): void\r\n}\r\n\r\nexport interface MemoizedFunction<T extends (...args: unknown[]) => unknown> {\r\n (...args: Parameters<T>): ReturnType<T>\r\n cache: Map<string, ReturnType<T>>\r\n}\r\n\r\nexport interface RetryOptions {\r\n attempts?: number\r\n baseDelay?: number\r\n maxDelay?: number\r\n shouldRetry?: (error: unknown) => boolean\r\n}\r\n\r\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\r\n if (value === null || typeof value !== 'object') return false\r\n const proto = Object.getPrototypeOf(value)\r\n return proto === Object.prototype || proto === null\r\n}\r\n\r\nfunction getType(value: unknown): string {\r\n return Object.prototype.toString.call(value)\r\n}\r\n\r\nfunction clone<T>(value: T, seen: WeakMap<object, unknown>): T {\r\n if (value === null || typeof value !== 'object') return value\r\n\r\n if (seen.has(value as object)) return seen.get(value as object) as T\r\n\r\n const tag = getType(value)\r\n\r\n if (tag === '[object Date]') {\r\n const cloned = new Date((value as unknown as Date).getTime())\r\n seen.set(value as object, cloned)\r\n return cloned as unknown as T\r\n }\r\n\r\n if (tag === '[object RegExp]') {\r\n const regExp = value as unknown as RegExp\r\n const cloned = new RegExp(regExp.source, regExp.flags)\r\n cloned.lastIndex = regExp.lastIndex\r\n seen.set(value as object, cloned)\r\n return cloned as unknown as T\r\n }\r\n\r\n if (tag === '[object Map]') {\r\n const cloned = new Map<unknown, unknown>()\r\n seen.set(value as object, cloned)\r\n ;(value as unknown as Map<unknown, unknown>).forEach((v, k) => {\r\n cloned.set(clone(k, seen), clone(v, seen))\r\n })\r\n return cloned as unknown as T\r\n }\r\n\r\n if (tag === '[object Set]') {\r\n const cloned = new Set<unknown>()\r\n seen.set(value as object, cloned)\r\n ;(value as unknown as Set<unknown>).forEach(v => {\r\n cloned.add(clone(v, seen))\r\n })\r\n return cloned as unknown as T\r\n }\r\n\r\n if (Array.isArray(value)) {\r\n const cloned: unknown[] = []\r\n seen.set(value as object, cloned)\r\n for (let i = 0; i < value.length; i++) {\r\n cloned[i] = clone(value[i], seen)\r\n }\r\n return cloned as unknown as T\r\n }\r\n\r\n if (tag === '[object Object]') {\r\n const cloned: Record<string, unknown> = {}\r\n seen.set(value as object, cloned)\r\n const keys = Object.keys(value as Record<string, unknown>)\r\n for (let i = 0; i < keys.length; i++) {\r\n const key = keys[i]!\r\n cloned[key] = clone((value as Record<string, unknown>)[key], seen)\r\n }\r\n return cloned as unknown as T\r\n }\r\n\r\n return value\r\n}\r\n\r\n/**\r\n * Deep clone a value, supporting objects, arrays, Date, RegExp, Map, Set,\r\n * and cyclic references.\r\n *\r\n * @param value - The value to clone.\r\n * @returns A deep copy of the input value.\r\n */\r\nexport function deepClone<T>(value: T): T {\r\n const seen = new WeakMap<object, unknown>()\r\n return clone(value, seen)\r\n}\r\n\r\n/**\r\n * Deep merge multiple objects. Arrays are overwritten, not concatenated.\r\n * `null` and `undefined` source objects are skipped.\r\n *\r\n * @param objects - The objects to merge.\r\n * @returns A new object with merged properties.\r\n */\r\nexport function deepMerge<T extends Record<string, unknown>>(...objects: Partial<T>[]): T {\r\n const result = {} as T\r\n\r\n for (let i = 0; i < objects.length; i++) {\r\n const obj = objects[i]\r\n if (obj === null || obj === undefined) continue\r\n\r\n const keys = Object.keys(obj) as (keyof T)[]\r\n for (let j = 0; j < keys.length; j++) {\r\n const key = keys[j]!\r\n const val = obj[key]\r\n const existing = result[key]\r\n\r\n if (val !== undefined && isPlainObject(val) && isPlainObject(existing)) {\r\n result[key] = deepMerge(\r\n existing as Record<string, unknown>,\r\n val as Record<string, unknown>\r\n ) as T[keyof T]\r\n } else if (val !== undefined) {\r\n result[key] = val as T[keyof T]\r\n }\r\n }\r\n }\r\n\r\n return result\r\n}\r\n\r\n/**\r\n * Creates a debounced function that delays invoking `fn` until after `wait`\r\n * milliseconds have elapsed since the last invocation. Supports leading,\r\n * trailing, and maxWait options. The returned function also has `.cancel()`\r\n * and `.flush()` methods.\r\n *\r\n * @param fn - The function to debounce.\r\n * @param wait - The number of milliseconds to delay.\r\n * @param options - Optional configuration.\r\n * @returns A debounced function with `.cancel()` and `.flush()`.\r\n */\r\nexport function debounce<T extends (...args: unknown[]) => unknown>(\r\n fn: T,\r\n wait: number,\r\n options?: DebounceOptions\r\n): DebouncedFunction<T> {\r\n const { leading = false, trailing = true, maxWait } = options ?? {}\r\n\r\n let timer: ReturnType<typeof setTimeout> | null = null\r\n let maxTimer: ReturnType<typeof setTimeout> | null = null\r\n let lastArgs: Parameters<T> | null = null\r\n let lastCallTime: number | null = null\r\n let lastInvokeTime = 0\r\n\r\n function invoke(time: number): void {\r\n lastInvokeTime = time\r\n if (lastArgs) {\r\n fn(...lastArgs)\r\n lastArgs = null\r\n }\r\n }\r\n\r\n function startTimer(waitTime: number): void {\r\n if (timer) clearTimeout(timer)\r\n timer = setTimeout(() => {\r\n const now = Date.now()\r\n if (lastArgs && trailing) {\r\n invoke(now)\r\n }\r\n timer = null\r\n lastCallTime = null\r\n }, waitTime)\r\n }\r\n\r\n function startMaxTimer(): void {\r\n if (maxWait === undefined || maxTimer) return\r\n maxTimer = setTimeout(() => {\r\n if (lastArgs) {\r\n invoke(Date.now())\r\n if (timer) {\r\n clearTimeout(timer)\r\n timer = null\r\n }\r\n lastCallTime = null\r\n }\r\n }, maxWait)\r\n }\r\n\r\n function clearAllTimers(): void {\r\n if (timer) {\r\n clearTimeout(timer)\r\n timer = null\r\n }\r\n if (maxTimer) {\r\n clearTimeout(maxTimer)\r\n maxTimer = null\r\n }\r\n }\r\n\r\n function shouldInvoke(time: number): boolean {\r\n if (lastCallTime === null) return true\r\n const timeSinceLastCall = time - lastCallTime\r\n const timeSinceLastInvoke = time - lastInvokeTime\r\n return (\r\n timeSinceLastCall >= wait ||\r\n (maxWait !== undefined && timeSinceLastInvoke >= maxWait)\r\n )\r\n }\r\n\r\n const debounced = function (this: unknown, ...args: Parameters<T>): void {\r\n const time = Date.now()\r\n const isInvoking = shouldInvoke(time)\r\n\r\n lastArgs = args\r\n lastCallTime = time\r\n\r\n if (isInvoking && !timer && leading) {\r\n invoke(time)\r\n }\r\n\r\n if (!timer) {\r\n startTimer(wait)\r\n if (maxWait !== undefined) {\r\n startMaxTimer()\r\n }\r\n }\r\n } as DebouncedFunction<T>\r\n\r\n debounced.cancel = (): void => {\r\n clearAllTimers()\r\n lastArgs = null\r\n lastCallTime = null\r\n lastInvokeTime = 0\r\n }\r\n\r\n debounced.flush = (): void => {\r\n if (timer && lastArgs) {\r\n invoke(Date.now())\r\n clearAllTimers()\r\n lastCallTime = null\r\n }\r\n }\r\n\r\n return debounced\r\n}\r\n\r\n/**\r\n * Creates a throttled function that only invokes `fn` at most once per\r\n * `wait` milliseconds.\r\n *\r\n * @param fn - The function to throttle.\r\n * @param wait - The number of milliseconds to throttle invocations to.\r\n * @returns A throttled function.\r\n */\r\nexport function throttle<T extends (...args: unknown[]) => unknown>(\r\n fn: T,\r\n wait: number\r\n): (...args: Parameters<T>) => void {\r\n let lastTime = 0\r\n let timer: ReturnType<typeof setTimeout> | null = null\r\n let lastArgs: Parameters<T> | null = null\r\n\r\n const throttled = function (this: unknown, ...args: Parameters<T>): void {\r\n const now = Date.now()\r\n const remaining = wait - (now - lastTime)\r\n\r\n if (remaining <= 0) {\r\n if (timer) {\r\n clearTimeout(timer)\r\n timer = null\r\n }\r\n lastTime = now\r\n lastArgs = null\r\n fn.apply(this, args)\r\n } else {\r\n lastArgs = args\r\n if (!timer) {\r\n timer = setTimeout(() => {\r\n lastTime = Date.now()\r\n timer = null\r\n if (lastArgs) {\r\n fn.apply(this, lastArgs)\r\n lastArgs = null\r\n }\r\n }, remaining)\r\n }\r\n }\r\n }\r\n\r\n return throttled\r\n}\r\n\r\n/**\r\n * Creates a memoized version of `fn`. Uses a `Map` cache keyed by the\r\n * first argument by default, or by a custom `resolver` function.\r\n *\r\n * @param fn - The function to memoize.\r\n * @param resolver - Optional function to determine the cache key.\r\n * @returns The memoized function with a `.cache` property.\r\n */\r\nexport function memoize<T extends (...args: unknown[]) => unknown>(\r\n fn: T,\r\n resolver?: (...args: Parameters<T>) => string\r\n): MemoizedFunction<T> {\r\n const cache = new Map<string, ReturnType<T>>()\r\n\r\n const memoized = function (this: unknown, ...args: Parameters<T>): ReturnType<T> {\r\n const key = resolver ? resolver(...args) : String(args[0])\r\n if (cache.has(key)) {\r\n return cache.get(key) as ReturnType<T>\r\n }\r\n const result = fn.apply(this, args) as ReturnType<T>\r\n cache.set(key, result)\r\n return result\r\n }\r\n\r\n memoized.cache = cache\r\n\r\n return memoized as MemoizedFunction<T>\r\n}\r\n\r\n/**\r\n * Retries an async function with exponential backoff and jitter.\r\n *\r\n * @param fn - The async function to retry.\r\n * @param options - Retry configuration.\r\n * @returns A promise that resolves with the function result.\r\n */\r\nexport function retry<T>(\r\n fn: () => Promise<T>,\r\n options?: RetryOptions\r\n): Promise<T> {\r\n const {\r\n attempts = 3,\r\n baseDelay = 1000,\r\n maxDelay = 30000,\r\n shouldRetry = () => true,\r\n } = options ?? {}\r\n\r\n let attempt = 0\r\n\r\n const execute = (): Promise<T> => {\r\n attempt++\r\n return fn().catch((error: unknown) => {\r\n if (attempt >= attempts || !shouldRetry(error)) {\r\n throw error\r\n }\r\n\r\n const delay = Math.min(\r\n baseDelay * Math.pow(2, attempt - 1) + Math.random() * baseDelay,\r\n maxDelay\r\n )\r\n\r\n return new Promise<T>(resolve => {\r\n setTimeout(() => {\r\n resolve(execute())\r\n }, delay)\r\n })\r\n })\r\n }\r\n\r\n return execute()\r\n}\r\n\r\n/**\r\n * A no-operation function that returns `undefined`.\r\n */\r\nexport function noop(): void {\r\n return undefined\r\n}\r\n\r\n/**\r\n * Returns the given value unchanged.\r\n *\r\n * @param value - The value to return.\r\n * @returns The same value.\r\n */\r\nexport function identity<T>(value: T): T {\r\n return value\r\n}\r\n\r\n/**\r\n * Creates a function that invokes `fn` only once. Subsequent calls return\r\n * the result of the first invocation.\r\n *\r\n * @param fn - The function to wrap.\r\n * @returns A function that runs only once.\r\n */\r\nexport function once<T extends (...args: unknown[]) => unknown>(\r\n fn: T\r\n): (...args: Parameters<T>) => ReturnType<T> {\r\n let called = false\r\n let result: ReturnType<T>\r\n\r\n return function (this: unknown, ...args: Parameters<T>): ReturnType<T> {\r\n if (!called) {\r\n called = true\r\n result = fn.apply(this, args) as ReturnType<T>\r\n }\r\n return result\r\n }\r\n}\r\n","/**\r\n * Error thrown when attempting to divide by zero.\r\n */\r\nexport class DivisionByZeroError extends Error {\r\n constructor() {\r\n super('Division by zero')\r\n this.name = 'DivisionByZeroError'\r\n }\r\n}\r\n\r\nfunction getPrecision(value: number): number {\r\n if (!isFinite(value)) return 0\r\n const eIndex = String(value).indexOf('e')\r\n if (eIndex > -1) {\r\n const exp = parseInt(String(value).slice(eIndex + 1), 10)\r\n if (exp < 0) return Math.abs(exp)\r\n return 0\r\n }\r\n const str = String(value)\r\n const dot = str.indexOf('.')\r\n return dot === -1 ? 0 : str.length - dot - 1\r\n}\r\n\r\nfunction toPrecisionFactor(a: number, b: number): number {\r\n return Math.pow(10, Math.max(getPrecision(a), getPrecision(b)))\r\n}\r\n\r\n/**\r\n * Safely adds two numbers, handling floating-point precision.\r\n *\r\n * @param a - First number.\r\n * @param b - Second number.\r\n * @returns The sum.\r\n */\r\nexport function add(a: number, b: number): number {\r\n const factor = toPrecisionFactor(a, b)\r\n return (Math.round(a * factor) + Math.round(b * factor)) / factor\r\n}\r\n\r\n/**\r\n * Safely subtracts two numbers, handling floating-point precision.\r\n *\r\n * @param a - First number.\r\n * @param b - Second number.\r\n * @returns The difference.\r\n */\r\nexport function sub(a: number, b: number): number {\r\n const factor = toPrecisionFactor(a, b)\r\n return (Math.round(a * factor) - Math.round(b * factor)) / factor\r\n}\r\n\r\n/**\r\n * Safely multiplies two numbers, handling floating-point precision.\r\n *\r\n * @param a - First number.\r\n * @param b - Second number.\r\n * @returns The product.\r\n */\r\nexport function mul(a: number, b: number): number {\r\n const factorA = toPrecisionFactor(a, 1)\r\n const factorB = toPrecisionFactor(1, b)\r\n const result = (Math.round(a * factorA) * Math.round(b * factorB)) / (factorA * factorB)\r\n return result\r\n}\r\n\r\n/**\r\n * Safely divides two numbers.\r\n *\r\n * @param a - The dividend.\r\n * @param b - The divisor.\r\n * @returns The quotient.\r\n * @throws {DivisionByZeroError} If `b` is zero.\r\n */\r\nexport function div(a: number, b: number): number {\r\n if (b === 0) throw new DivisionByZeroError()\r\n const factor = toPrecisionFactor(a, b)\r\n return Math.round(a * factor) / Math.round(b * factor)\r\n}\r\n\r\n/**\r\n * Rounds a number to the given precision.\r\n *\r\n * @param value - The number to round.\r\n * @param precision - Number of decimal places (default 0).\r\n * @returns The rounded value.\r\n */\r\nexport function round(value: number, precision: number = 0): number {\r\n const factor = Math.pow(10, precision)\r\n // Use toPrecision to avoid floating-point multiplication errors\r\n // e.g. 1.005 * 100 = 100.49999999999999 without this fix\r\n const shifted = Number((value * factor).toPrecision(15))\r\n return Math.round(shifted) / factor\r\n}\r\n\r\n/**\r\n * Floors a number to the given precision.\r\n *\r\n * @param value - The number to floor.\r\n * @param precision - Number of decimal places (default 0).\r\n * @returns The floored value.\r\n */\r\nexport function floor(value: number, precision: number = 0): number {\r\n const factor = Math.pow(10, precision)\r\n return Math.floor(value * factor) / factor\r\n}\r\n\r\n/**\r\n * Ceils a number to the given precision.\r\n *\r\n * @param value - The number to ceil.\r\n * @param precision - Number of decimal places (default 0).\r\n * @returns The ceiled value.\r\n */\r\nexport function ceil(value: number, precision: number = 0): number {\r\n const factor = Math.pow(10, precision)\r\n return Math.ceil(value * factor) / factor\r\n}\r\n\r\n/**\r\n * Checks if two numbers are approximately equal within a tolerance.\r\n *\r\n * @param a - First number.\r\n * @param b - Second number.\r\n * @param tolerance - Maximum difference (default `Number.EPSILON`).\r\n * @returns Whether the numbers are approximately equal.\r\n */\r\nexport function approxEqual(a: number, b: number, tolerance: number = Number.EPSILON): boolean {\r\n return Math.abs(a - b) <= tolerance\r\n}\r\n\r\n/**\r\n * Clamps a value within the inclusive range [min, max].\r\n *\r\n * @param value - The value to clamp.\r\n * @param min - The lower bound.\r\n * @param max - The upper bound.\r\n * @returns The clamped value.\r\n * @throws {RangeError} If `min` exceeds `max`.\r\n */\r\nexport function clamp(value: number, min: number, max: number): number {\r\n if (min > max) {\r\n throw new RangeError('Minimum value cannot exceed maximum value')\r\n }\r\n return Math.min(Math.max(value, min), max)\r\n}\r\n\r\n/**\r\n * Computes the sum of an array of numbers.\r\n *\r\n * @param values - Array of numbers.\r\n * @returns The total sum.\r\n */\r\nexport function sum(values: number[]): number {\r\n let total = 0\r\n for (let i = 0; i < values.length; i++) {\r\n total += values[i]!\r\n }\r\n return total\r\n}\r\n\r\n/**\r\n * Computes the average (mean) of an array of numbers.\r\n *\r\n * @param values - Array of numbers.\r\n * @returns The average.\r\n * @throws {RangeError} If the array is empty.\r\n */\r\nexport function average(values: number[]): number {\r\n if (values.length === 0) {\r\n throw new RangeError('Cannot compute average of an empty array')\r\n }\r\n return sum(values) / values.length\r\n}\r\n\r\n/**\r\n * Generates a random integer between `min` and `max` (inclusive).\r\n *\r\n * @param min - The minimum integer.\r\n * @param max - The maximum integer.\r\n * @returns A random integer.\r\n * @throws {RangeError} If arguments are not integers or `min > max`.\r\n */\r\nexport function randomInt(min: number, max: number): number {\r\n if (!Number.isInteger(min) || !Number.isInteger(max)) {\r\n throw new RangeError('Arguments must be integers')\r\n }\r\n if (min > max) {\r\n throw new RangeError('Minimum value cannot exceed maximum value')\r\n }\r\n return Math.floor(Math.random() * (max - min + 1)) + min\r\n}\r\n\r\n/**\r\n * Checks if a number is within the inclusive range [min, max].\r\n *\r\n * @param value - The number to check.\r\n * @param min - The lower bound.\r\n * @param max - The upper bound.\r\n * @returns Whether the value is in range.\r\n */\r\nexport function inRange(value: number, min: number, max: number): boolean {\r\n return value >= min && value <= max\r\n}\r\n","/**\r\n * Error thrown when a date value is invalid.\r\n */\r\nexport class InvalidDateError extends Error {\r\n constructor(input: unknown) {\r\n super(`Invalid date: ${String(input)}`)\r\n this.name = 'InvalidDateError'\r\n }\r\n}\r\n\r\nexport interface DateDiff {\r\n years: number\r\n months: number\r\n days: number\r\n hours: number\r\n minutes: number\r\n seconds: number\r\n}\r\n\r\nconst MONTH_NAMES_SHORT = [\r\n 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\r\n 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',\r\n] as const\r\n\r\nconst MONTH_NAMES_FULL = [\r\n 'January', 'February', 'March', 'April', 'May', 'June',\r\n 'July', 'August', 'September', 'October', 'November', 'December',\r\n] as const\r\n\r\nconst MONTH_MAP: Record<string, number> = {\r\n jan: 0, january: 0,\r\n feb: 1, february: 1,\r\n mar: 2, march: 2,\r\n apr: 3, april: 3,\r\n may: 4,\r\n jun: 5, june: 5,\r\n jul: 6, july: 6,\r\n aug: 7, august: 7,\r\n sep: 8, september: 8,\r\n oct: 9, october: 9,\r\n nov: 10, november: 10,\r\n dec: 11, december: 11,\r\n}\r\n\r\n/**\r\n * Formats a Date to a string using the given format pattern.\r\n *\r\n * Supported tokens:\r\n * - `YYYY` — 4-digit year\r\n * - `YY` — 2-digit year\r\n * - `MMMM` — full month name\r\n * - `MMM` — abbreviated month name\r\n * - `MM` — 2-digit month (01–12)\r\n * - `DD` — 2-digit day (01–31)\r\n * - `HH` — 2-digit hours (00–23)\r\n * - `mm` — 2-digit minutes\r\n * - `ss` — 2-digit seconds\r\n * - `SSS` — milliseconds\r\n *\r\n * @param date - The date to format.\r\n * @param format - The format string (default `'YYYY-MM-DD'`).\r\n * @returns The formatted date string.\r\n */\r\nexport function formatDate(date: Date, format: string = 'YYYY-MM-DD'): string {\r\n const year = date.getFullYear()\r\n const month = date.getMonth()\r\n const day = date.getDate()\r\n const hours = date.getHours()\r\n const minutes = date.getMinutes()\r\n const seconds = date.getSeconds()\r\n const ms = date.getMilliseconds()\r\n\r\n const pad = (n: number, len: number = 2): string => String(n).padStart(len, '0')\r\n\r\n return format\r\n .replace(/YYYY/g, String(year))\r\n .replace(/YY/g, String(year).slice(-2))\r\n .replace(/MMMM/g, MONTH_NAMES_FULL[month]!)\r\n .replace(/MMM/g, MONTH_NAMES_SHORT[month]!)\r\n .replace(/MM/g, pad(month + 1))\r\n .replace(/DD/g, pad(day))\r\n .replace(/HH/g, pad(hours))\r\n .replace(/mm/g, pad(minutes))\r\n .replace(/ss/g, pad(seconds))\r\n .replace(/SSS/g, pad(ms, 3))\r\n}\r\n\r\n/**\r\n * Parses a date from a string, number (timestamp in ms), or Date object.\r\n *\r\n * Supported string formats:\r\n * - ISO (`YYYY-MM-DD`, `YYYY-MM-DDTHH:mm:ss`)\r\n * - `DD/MM/YYYY` or `DD-MM-YYYY`\r\n * - `DD MMM YYYY` or `DD MMMM YYYY`\r\n * - Unix timestamp (milliseconds)\r\n *\r\n * @param input - The value to parse.\r\n * @returns A valid Date object.\r\n * @throws {InvalidDateError} If the input cannot be parsed.\r\n */\r\nexport function parseDate(input: string | number | Date): Date {\r\n if (input instanceof Date) {\r\n if (isNaN(input.getTime())) throw new InvalidDateError(input)\r\n return new Date(input.getTime())\r\n }\r\n\r\n if (typeof input === 'number') {\r\n const d = new Date(input)\r\n if (isNaN(d.getTime())) throw new InvalidDateError(input)\r\n return d\r\n }\r\n\r\n const trimmed = input.trim()\r\n\r\n // ISO format: YYYY-MM-DD or YYYY-MM-DDTHH:mm:ss\r\n const isoMatch = trimmed.match(/^(\\d{4})-(\\d{2})-(\\d{2})(?:T(\\d{2}):(\\d{2}):(\\d{2})(?:\\.(\\d+))?)?(?:Z|[+-]\\d{2}:?\\d{2})?$/)\r\n if (isoMatch) {\r\n const d = new Date(\r\n parseInt(isoMatch[1]!, 10),\r\n parseInt(isoMatch[2]!, 10) - 1,\r\n parseInt(isoMatch[3]!, 10),\r\n isoMatch[4] ? parseInt(isoMatch[4]!, 10) : 0,\r\n isoMatch[5] ? parseInt(isoMatch[5]!, 10) : 0,\r\n isoMatch[6] ? parseInt(isoMatch[6]!, 10) : 0,\r\n isoMatch[7] ? parseInt(isoMatch[7]!.padEnd(3, '0'), 10) : 0\r\n )\r\n if (!isNaN(d.getTime())) return d\r\n }\r\n\r\n // DD/MM/YYYY or DD-MM-YYYY\r\n const dmyMatch = trimmed.match(/^(\\d{1,2})[\\/-](\\d{1,2})[\\/-](\\d{4})$/)\r\n if (dmyMatch) {\r\n const year = parseInt(dmyMatch[3]!, 10)\r\n const month = parseInt(dmyMatch[2]!, 10) - 1\r\n const day = parseInt(dmyMatch[1]!, 10)\r\n const d = new Date(year, month, day)\r\n // Validate that the date didn't overflow (e.g. Feb 29 in non-leap year)\r\n if (!isNaN(d.getTime()) && d.getMonth() === month && d.getDate() === day) return d\r\n }\r\n\r\n // DD MMM YYYY or DD MMMM YYYY\r\n const textMatch = trimmed.match(/^(\\d{1,2})\\s+([a-zA-Z]+)\\s+(\\d{4})$/)\r\n if (textMatch) {\r\n const monthIndex = MONTH_MAP[textMatch[2]!.toLowerCase()]\r\n if (monthIndex !== undefined) {\r\n const year = parseInt(textMatch[3]!, 10)\r\n const day = parseInt(textMatch[1]!, 10)\r\n const d = new Date(year, monthIndex, day)\r\n if (!isNaN(d.getTime()) && d.getMonth() === monthIndex && d.getDate() === day) return d\r\n }\r\n }\r\n\r\n // Unix timestamp (milliseconds) as string\r\n const numMatch = trimmed.match(/^-?\\d+$/)\r\n if (numMatch) {\r\n const d = new Date(parseInt(numMatch[0], 10))\r\n if (!isNaN(d.getTime())) return d\r\n }\r\n\r\n // Fallback: let Date.parse try\r\n const fallback = new Date(trimmed)\r\n if (!isNaN(fallback.getTime())) return fallback\r\n\r\n throw new InvalidDateError(input)\r\n}\r\n\r\nfunction isValidDate(d: Date): boolean {\r\n return d instanceof Date && !isNaN(d.getTime())\r\n}\r\n\r\nconst MS_IN_SECOND = 1000\r\nconst MS_IN_MINUTE = 60 * MS_IN_SECOND\r\nconst MS_IN_HOUR = 60 * MS_IN_MINUTE\r\nconst MS_IN_DAY = 24 * MS_IN_HOUR\r\n\r\n/**\r\n * Computes the difference between two dates.\r\n *\r\n * @param date1 - Start date.\r\n * @param date2 - End date.\r\n * @returns An object with years, months, days, hours, minutes, seconds.\r\n * @throws {InvalidDateError} If either date is invalid.\r\n */\r\nexport function dateDiff(date1: Date, date2: Date): DateDiff {\r\n if (!isValidDate(date1) || !isValidDate(date2)) {\r\n throw new InvalidDateError('Invalid date provided to dateDiff')\r\n }\r\n\r\n let years = date2.getFullYear() - date1.getFullYear()\r\n let months = date2.getMonth() - date1.getMonth()\r\n let days = date2.getDate() - date1.getDate()\r\n\r\n if (days < 0) {\r\n months -= 1\r\n const prevMonth = new Date(date2.getFullYear(), date2.getMonth(), 0)\r\n days += prevMonth.getDate()\r\n }\r\n\r\n if (months < 0) {\r\n years -= 1\r\n months += 12\r\n }\r\n\r\n const msDiff = Math.abs(date2.getTime() - date1.getTime())\r\n const totalSeconds = Math.floor(msDiff / MS_IN_SECOND)\r\n const hours = Math.floor((msDiff % MS_IN_DAY) / MS_IN_HOUR)\r\n const minutes = Math.floor((msDiff % MS_IN_HOUR) / MS_IN_MINUTE)\r\n const seconds = totalSeconds % 60\r\n\r\n return { years, months, days, hours, minutes, seconds }\r\n}\r\n\r\n/**\r\n * Adds days to a date.\r\n *\r\n * @param date - The original date.\r\n * @param days - Number of days to add (negative to subtract).\r\n * @returns A new Date.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function addDays(date: Date, days: number): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n const result = new Date(date.getTime())\r\n result.setDate(result.getDate() + days)\r\n return result\r\n}\r\n\r\n/**\r\n * Adds months to a date. Handles month-end overflow (e.g., Jan 31 + 1 month\r\n * becomes Feb 28).\r\n *\r\n * @param date - The original date.\r\n * @param months - Number of months to add (negative to subtract).\r\n * @returns A new Date.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function addMonths(date: Date, months: number): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n const result = new Date(date.getTime())\r\n const targetMonth = result.getMonth() + months\r\n result.setMonth(targetMonth)\r\n\r\n if (result.getMonth() !== ((targetMonth % 12) + 12) % 12) {\r\n result.setDate(0)\r\n }\r\n\r\n return result\r\n}\r\n\r\n/**\r\n * Adds years to a date. Handles leap-year overflow (e.g., Feb 29 + 1 year\r\n * becomes Feb 28).\r\n *\r\n * @param date - The original date.\r\n * @param years - Number of years to add (negative to subtract).\r\n * @returns A new Date.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function addYears(date: Date, years: number): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n const result = new Date(date.getTime())\r\n const targetYear = result.getFullYear() + years\r\n result.setFullYear(targetYear)\r\n\r\n if (result.getFullYear() !== targetYear) {\r\n result.setDate(0)\r\n }\r\n\r\n return result\r\n}\r\n\r\n/**\r\n * Returns the start of the day (00:00:00.000) for the given date.\r\n *\r\n * @param date - The date.\r\n * @returns A new Date set to midnight.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function startOfDay(date: Date): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0, 0)\r\n}\r\n\r\n/**\r\n * Returns the end of the day (23:59:59.999) for the given date.\r\n *\r\n * @param date - The date.\r\n * @returns A new Date set to the last millisecond of the day.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function endOfDay(date: Date): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59, 999)\r\n}\r\n\r\n/**\r\n * Returns the first moment of the month for the given date.\r\n *\r\n * @param date - The date.\r\n * @returns A new Date set to the start of the month.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function startOfMonth(date: Date): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n return new Date(date.getFullYear(), date.getMonth(), 1, 0, 0, 0, 0)\r\n}\r\n\r\n/**\r\n * Returns the last moment of the month for the given date.\r\n *\r\n * @param date - The date.\r\n * @returns A new Date set to the end of the month.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function endOfMonth(date: Date): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n return new Date(date.getFullYear(), date.getMonth() + 1, 0, 23, 59, 59, 999)\r\n}\r\n\r\n/**\r\n * Returns the first moment of the year for the given date.\r\n *\r\n * @param date - The date.\r\n * @returns A new Date set to Jan 1 00:00:00.000.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function startOfYear(date: Date): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n return new Date(date.getFullYear(), 0, 1, 0, 0, 0, 0)\r\n}\r\n\r\n/**\r\n * Returns the last moment of the year for the given date.\r\n *\r\n * @param date - The date.\r\n * @returns A new Date set to Dec 31 23:59:59.999.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function endOfYear(date: Date): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n return new Date(date.getFullYear(), 12, 0, 23, 59, 59, 999)\r\n}\r\n\r\n/**\r\n * Checks if the date falls on a weekend (Saturday or Sunday).\r\n *\r\n * @param date - The date to check.\r\n * @returns Whether the date is a weekend.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function isWeekend(date: Date): boolean {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n const day = date.getDay()\r\n return day === 0 || day === 6\r\n}\r\n\r\n/**\r\n * Checks if a year is a leap year.\r\n *\r\n * @param year - The year to check.\r\n * @returns Whether the year is a leap year.\r\n */\r\nexport function isLeapYear(year: number): boolean {\r\n return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0\r\n}\r\n\r\n/**\r\n * Checks if `date1` is before `date2`.\r\n *\r\n * @param date1 - First date.\r\n * @param date2 - Second date.\r\n * @returns Whether `date1` is before `date2`.\r\n * @throws {InvalidDateError} If either date is invalid.\r\n */\r\nexport function isBefore(date1: Date, date2: Date): boolean {\r\n if (!isValidDate(date1) || !isValidDate(date2)) {\r\n throw new InvalidDateError('Invalid date provided to isBefore')\r\n }\r\n return date1.getTime() < date2.getTime()\r\n}\r\n\r\n/**\r\n * Checks if `date1` is after `date2`.\r\n *\r\n * @param date1 - First date.\r\n * @param date2 - Second date.\r\n * @returns Whether `date1` is after `date2`.\r\n * @throws {InvalidDateError} If either date is invalid.\r\n */\r\nexport function isAfter(date1: Date, date2: Date): boolean {\r\n if (!isValidDate(date1) || !isValidDate(date2)) {\r\n throw new InvalidDateError('Invalid date provided to isAfter')\r\n }\r\n return date1.getTime() > date2.getTime()\r\n}\r\n\r\n/**\r\n * Checks if a date is within the inclusive range [start, end].\r\n *\r\n * @param date - The date to check.\r\n * @param start - Start of the range.\r\n * @param end - End of the range.\r\n * @returns Whether the date is between start and end.\r\n * @throws {InvalidDateError} If any date is invalid.\r\n */\r\nexport function isBetween(date: Date, start: Date, end: Date): boolean {\r\n if (!isValidDate(date) || !isValidDate(start) || !isValidDate(end)) {\r\n throw new InvalidDateError('Invalid date provided to isBetween')\r\n }\r\n return date.getTime() >= start.getTime() && date.getTime() <= end.getTime()\r\n}\r\n\r\n/**\r\n * Checks if a date is a business day (Monday to Friday).\r\n *\r\n * @param date - The date to check.\r\n * @returns Whether the date is a business day.\r\n */\r\nexport function isBusinessDay(date: Date): boolean {\r\n return isValidDate(date) && !isWeekend(date)\r\n}\r\n\r\n/**\r\n * Adds business days (skipping weekends) to a date.\r\n *\r\n * @param date - The starting date.\r\n * @param days - Number of business days to add (negative to subtract).\r\n * @returns A new Date.\r\n * @throws {InvalidDateError} If the input date is invalid.\r\n */\r\nexport function addBusinessDays(date: Date, days: number): Date {\r\n if (!isValidDate(date)) throw new InvalidDateError(date)\r\n\r\n const result = new Date(date.getTime())\r\n let remaining = Math.abs(days)\r\n const step = days >= 0 ? 1 : -1\r\n\r\n while (remaining > 0) {\r\n result.setDate(result.getDate() + step)\r\n const day = result.getDay()\r\n if (day !== 0 && day !== 6) {\r\n remaining--\r\n }\r\n }\r\n\r\n return result\r\n}\r\n\r\n/**\r\n * Calculates age in years from a birth date.\r\n *\r\n * @param birthDate - The date of birth.\r\n * @returns The age in years.\r\n * @throws {InvalidDateError} If the birth date is invalid.\r\n */\r\nexport function calculateAge(birthDate: Date): number {\r\n if (!isValidDate(birthDate)) throw new InvalidDateError(birthDate)\r\n\r\n const today = new Date()\r\n let age = today.getFullYear() - birthDate.getFullYear()\r\n const monthDiff = today.getMonth() - birthDate.getMonth()\r\n\r\n if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {\r\n age--\r\n }\r\n\r\n return age\r\n}\r\n","/**\r\n * Simple hash function using the djb2 algorithm.\r\n * Fast, non-cryptographic — suitable for hashtables, not security.\r\n *\r\n * @param str - The string to hash.\r\n * @returns A 32-bit integer hash.\r\n */\r\nexport function hash(str: string): number {\r\n let h = 5381\r\n for (let i = 0; i < str.length; i++) {\r\n h = ((h << 5) + h + str.charCodeAt(i)) | 0\r\n }\r\n return h >>> 0\r\n}\r\n\r\n/**\r\n * Produces a deterministic hex hash from a string.\r\n * NOT actual MD5 — use for cache keys / deterministic IDs.\r\n *\r\n * @param str - The string to hash.\r\n * @returns A 32-character hex string.\r\n */\r\nexport function simpleHash(str: string): string {\r\n let h1 = 0x67452301\r\n let h2 = 0xefcdab89\r\n let h3 = 0x98badcfe\r\n let h4 = 0x10325476\r\n\r\n for (let i = 0; i < str.length; i++) {\r\n const c = str.charCodeAt(i)\r\n h1 = (h1 + c) | 0\r\n h2 = (h2 + (c << 3) + i) | 0\r\n h3 = (h3 ^ c) | 0\r\n h4 = (h4 + (c << 5) + (c << 1)) | 0\r\n }\r\n\r\n const toHex = (n: number): string => (n >>> 0).toString(16).padStart(8, '0')\r\n return toHex(h1) + toHex(h2) + toHex(h3) + toHex(h4)\r\n}\r\n\r\nfunction getRandomBytes(size: number): Uint8Array {\r\n const bytes = new Uint8Array(size)\r\n if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') {\r\n crypto.getRandomValues(bytes)\r\n } else {\r\n for (let i = 0; i < size; i++) {\r\n bytes[i] = Math.floor(Math.random() * 256)\r\n }\r\n }\r\n return bytes\r\n}\r\n\r\n/**\r\n * Generates random bytes as a hex string.\r\n *\r\n * @param size - Number of random bytes (default 16).\r\n * @returns A hex string of length `size * 2`.\r\n */\r\nexport function randomHex(size: number = 16): string {\r\n const bytes = getRandomBytes(size)\r\n let result = ''\r\n for (let i = 0; i < bytes.length; i++) {\r\n result += bytes[i]!.toString(16).padStart(2, '0')\r\n }\r\n return result\r\n}\r\n\r\nfunction utf8ToBytes(str: string): Uint8Array {\r\n if (typeof TextEncoder !== 'undefined') {\r\n return new TextEncoder().encode(str)\r\n }\r\n const bytes = new Uint8Array(str.length)\r\n for (let i = 0; i < str.length; i++) {\r\n bytes[i] = str.charCodeAt(i)\r\n }\r\n return bytes\r\n}\r\n\r\nfunction bytesToUtf8(bytes: Uint8Array): string {\r\n if (typeof TextDecoder !== 'undefined') {\r\n return new TextDecoder().decode(bytes)\r\n }\r\n let result = ''\r\n for (let i = 0; i < bytes.length; i++) {\r\n result += String.fromCharCode(bytes[i]!)\r\n }\r\n return result\r\n}\r\n\r\nfunction bytesToBase64(bytes: Uint8Array): string {\r\n let binary = ''\r\n for (let i = 0; i < bytes.length; i++) {\r\n binary += String.fromCharCode(bytes[i]!)\r\n }\r\n if (typeof btoa === 'function') {\r\n return btoa(binary)\r\n }\r\n return Buffer.from(binary, 'latin1').toString('base64')\r\n}\r\n\r\nfunction base64ToBytes(str: string): Uint8Array {\r\n let binary: string\r\n if (typeof atob === 'function') {\r\n binary = atob(str)\r\n } else {\r\n binary = Buffer.from(str, 'base64').toString('latin1')\r\n }\r\n const bytes = new Uint8Array(binary.length)\r\n for (let i = 0; i < binary.length; i++) {\r\n bytes[i] = binary.charCodeAt(i)\r\n }\r\n return bytes\r\n}\r\n\r\n/**\r\n * Encodes a string to base64. Works in both Node.js and browser.\r\n * Handles UTF-8 characters correctly.\r\n *\r\n * @param str - The string to encode.\r\n * @returns The base64-encoded string.\r\n */\r\nexport function base64Encode(str: string): string {\r\n const bytes = utf8ToBytes(str)\r\n return bytesToBase64(bytes)\r\n}\r\n\r\n/**\r\n * Decodes a base64-encoded string. Works in both Node.js and browser.\r\n *\r\n * @param str - The base64 string to decode.\r\n * @returns The decoded string.\r\n */\r\nexport function base64Decode(str: string): string {\r\n const bytes = base64ToBytes(str)\r\n return bytesToUtf8(bytes)\r\n}\r\n\r\n/**\r\n * Generates a cryptographically random token string.\r\n *\r\n * @param bytes - Number of random bytes (default 32 → 64-char hex).\r\n * @returns A hex string suitable for API keys, reset tokens, etc.\r\n */\r\nexport function generateToken(bytes: number = 32): string {\r\n return randomHex(bytes)\r\n}\r\n\r\n/**\r\n * Generates a numeric OTP of the given length.\r\n *\r\n * @param length - Number of digits (default 6).\r\n * @returns A numeric string of the specified length.\r\n */\r\nexport function generateOTP(length: number = 6): string {\r\n const bytes = getRandomBytes(length)\r\n let otp = ''\r\n for (let i = 0; i < length; i++) {\r\n otp += (bytes[i]! % 10).toString()\r\n }\r\n return otp\r\n}\r\n\r\n/**\r\n * Simple XOR cipher — symmetrical, for light obfuscation only.\r\n *\r\n * ⚠️ WARNING: This is NOT encryption. XOR cipher provides zero security\r\n * against any attacker. Do NOT use this for passwords, API keys, personal\r\n * data, or any sensitive information. It can be trivially reversed.\r\n * For real encryption, use native `crypto.subtle` (Web) or `node:crypto`.\r\n *\r\n * Suitable only for: basic data masking, simple anti-scraping, educational purposes.\r\n *\r\n * @param str - The input string (will be transformed).\r\n * @param key - The cipher key.\r\n * @returns The XOR-transformed string.\r\n */\r\nexport function xorCipher(str: string, key: string): string {\r\n let result = ''\r\n for (let i = 0; i < str.length; i++) {\r\n const code = str.charCodeAt(i) ^ key.charCodeAt(i % key.length)\r\n result += String.fromCharCode(code)\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Computes a simple checksum (CRC-like) for file integrity checks.\r\n *\r\n * @param input - The input string.\r\n * @returns An 8-character hex checksum.\r\n */\r\nexport function checksum(input: string): string {\r\n let crc = 0xffffffff\r\n for (let i = 0; i < input.length; i++) {\r\n crc ^= input.charCodeAt(i)\r\n for (let j = 0; j < 8; j++) {\r\n if (crc & 1) {\r\n crc = (crc >>> 1) ^ 0xedb88320\r\n } else {\r\n crc = crc >>> 1\r\n }\r\n }\r\n }\r\n return ((crc ^ 0xffffffff) >>> 0).toString(16).padStart(8, '0')\r\n}\r\n\r\n/**\r\n * Constant-time string comparison to prevent timing attacks.\r\n *\r\n * @param a - First string.\r\n * @param b - Second string.\r\n * @returns Whether the strings are equal.\r\n */\r\nexport function constantTimeEqual(a: string, b: string): boolean {\r\n if (a.length !== b.length) return false\r\n let result = 0\r\n for (let i = 0; i < a.length; i++) {\r\n result |= a.charCodeAt(i) ^ b.charCodeAt(i)\r\n }\r\n return result === 0\r\n}\r\n","const SEP = '/'\r\n\r\n/**\r\n * Joins path segments with the proper separator.\r\n *\r\n * @param segments - Path segments to join.\r\n * @returns The joined path.\r\n */\r\nexport function join(...segments: string[]): string {\r\n const parts: string[] = []\r\n for (const seg of segments) {\r\n if (seg === '') continue\r\n const split = seg.split(/[\\\\/]/)\r\n for (const part of split) {\r\n if (part === '' || part === '.') continue\r\n if (part === '..') {\r\n if (parts.length > 0 && parts[parts.length - 1] !== '..') {\r\n parts.pop()\r\n } else {\r\n parts.push('..')\r\n }\r\n } else {\r\n parts.push(part)\r\n }\r\n }\r\n }\r\n if (parts.length === 0) return '.'\r\n const result = parts.join(SEP)\r\n if (segments.length > 0 && segments[0]!.startsWith('/')) {\r\n return SEP + result\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Resolves path segments to an absolute path.\r\n *\r\n * @param segments - Path segments to resolve.\r\n * @returns The resolved absolute path.\r\n */\r\nexport function resolve(...segments: string[]): string {\r\n let resolved = ''\r\n let isAbs = false\r\n\r\n for (const seg of segments) {\r\n if (seg.startsWith('/')) {\r\n resolved = seg\r\n isAbs = true\r\n } else if (isAbs) {\r\n resolved = join(resolved, seg)\r\n } else {\r\n resolved = resolved ? join(resolved, seg) : seg\r\n }\r\n }\r\n\r\n if (!isAbs) {\r\n resolved = join(SEP, resolved)\r\n }\r\n\r\n return normalize(resolved)\r\n}\r\n\r\n/**\r\n * Returns the filename from a path.\r\n *\r\n * @param p - The path.\r\n * @param ext - Optional extension to strip.\r\n * @returns The filename.\r\n */\r\nexport function basename(p: string, ext?: string): string {\r\n const normalized = p.replace(/[\\\\/]+$/, '')\r\n const idx = normalized.lastIndexOf(SEP)\r\n let base = idx === -1 ? normalized : normalized.slice(idx + 1)\r\n if (ext && base.endsWith(ext)) {\r\n base = base.slice(0, -ext.length)\r\n }\r\n return base\r\n}\r\n\r\n/**\r\n * Returns the directory portion of a path.\r\n *\r\n * @param p - The path.\r\n * @returns The directory path.\r\n */\r\nexport function dirname(p: string): string {\r\n if (p === SEP) return SEP\r\n const normalized = p.replace(/[\\\\/]+$/, '')\r\n if (normalized === '') return '.'\r\n const idx = normalized.lastIndexOf(SEP)\r\n if (idx === -1) return '.'\r\n if (idx === 0) return SEP\r\n return normalized.slice(0, idx)\r\n}\r\n\r\n/**\r\n * Returns the file extension from a path.\r\n *\r\n * @param p - The path.\r\n * @returns The extension including the dot, or empty string.\r\n */\r\nexport function extname(p: string): string {\r\n const base = basename(p)\r\n const idx = base.lastIndexOf('.')\r\n if (idx === -1 || idx === 0) return ''\r\n return base.slice(idx)\r\n}\r\n\r\n/**\r\n * Normalizes a path, resolving '..' and '.' segments.\r\n *\r\n * @param p - The path to normalize.\r\n * @returns The normalized path.\r\n */\r\nexport function normalize(p: string): string {\r\n const parts = p.split(/[\\\\/]+/)\r\n const stack: string[] = []\r\n let isAbs = p.startsWith('/')\r\n\r\n for (const part of parts) {\r\n if (part === '' || part === '.') continue\r\n if (part === '..') {\r\n if (stack.length > 0 && stack[stack.length - 1] !== '..') {\r\n stack.pop()\r\n } else if (!isAbs) {\r\n stack.push('..')\r\n }\r\n } else {\r\n stack.push(part)\r\n }\r\n }\r\n\r\n const result = stack.join(SEP)\r\n if (isAbs) return SEP + result\r\n if (result === '') return '.'\r\n return result\r\n}\r\n\r\n/**\r\n * Checks if a path is absolute.\r\n *\r\n * @param p - The path to check.\r\n * @returns Whether the path is absolute.\r\n */\r\nexport function isAbsolute(p: string): boolean {\r\n return p.startsWith('/')\r\n}\r\n\r\n/**\r\n * Computes the relative path from `from` to `to`.\r\n *\r\n * @param from - The base path.\r\n * @param to - The target path.\r\n * @returns The relative path.\r\n */\r\nexport function relative(from: string, to: string): string {\r\n const fromParts = normalize(from).split(SEP)\r\n const toParts = normalize(to).split(SEP)\r\n\r\n let i = 0\r\n while (i < fromParts.length && i < toParts.length && fromParts[i] === toParts[i]) {\r\n i++\r\n }\r\n\r\n const up = fromParts.slice(i).map(() => '..')\r\n const down = toParts.slice(i)\r\n const result = [...up, ...down].join(SEP)\r\n\r\n return result || '.'\r\n}\r\n\r\nexport interface ParsedPath {\r\n root: string\r\n dir: string\r\n base: string\r\n name: string\r\n ext: string\r\n}\r\n\r\n/**\r\n * Parses a path into its components.\r\n *\r\n * @param p - The path to parse.\r\n * @returns An object with root, dir, base, name, and ext.\r\n */\r\nexport function parse(p: string): ParsedPath {\r\n const root = p.startsWith(SEP) ? SEP : ''\r\n const base = basename(p)\r\n const ext = extname(base)\r\n const name = ext ? base.slice(0, -ext.length) : base\r\n const dir = root ? dirname(p) : (dirname(p) === '.' ? '' : dirname(p))\r\n\r\n return { root, dir, base, name, ext }\r\n}\r\n\r\n/**\r\n * Formats a parsed path object back into a path string.\r\n *\r\n * @param parsed - The parsed path components.\r\n * @returns The formatted path string.\r\n */\r\nexport function format(parsed: Partial<ParsedPath>): string {\r\n const { root = '', dir = '', base = '', name = '', ext = '' } = parsed\r\n const baseName = base || name + ext\r\n if (dir) {\r\n return dir + SEP + baseName\r\n }\r\n return root + baseName\r\n}\r\n","/**\r\n * Groups an array of items by a key extracted from each item.\r\n *\r\n * @example groupBy([{ type: 'a' }, { type: 'b' }, { type: 'a' }], x => x.type)\r\n * // => { a: [{ type: 'a' }, { type: 'a' }], b: [{ type: 'b' }] }\r\n */\r\nexport function groupBy<T, K extends string | number | symbol>(items: T[], keyFn: (item: T) => K): Record<K, T[]> {\r\n const result = {} as Record<K, T[]>\r\n for (const item of items) {\r\n const key = keyFn(item)\r\n if (!result[key]) result[key] = []\r\n result[key]!.push(item)\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Creates an object keyed by the result of keyFn for each item.\r\n *\r\n * @example keyBy([{ id: 1, name: 'a' }, { id: 2, name: 'b' }], x => x.id)\r\n * // => { 1: { id: 1, name: 'a' }, 2: { id: 2, name: 'b' } }\r\n */\r\nexport function keyBy<T, K extends string | number | symbol>(items: T[], keyFn: (item: T) => K): Record<K, T> {\r\n const result = {} as Record<K, T>\r\n for (const item of items) {\r\n const key = keyFn(item)\r\n result[key] = item\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Returns a copy of the object with the specified keys omitted.\r\n */\r\nexport function omit<T extends Record<string, unknown>, K extends keyof T>(obj: T, keys: K[]): Omit<T, K> {\r\n const result = { ...obj } as T\r\n for (const key of keys) {\r\n delete result[key]\r\n }\r\n return result as Omit<T, K>\r\n}\r\n\r\n/**\r\n * Returns a copy of the object with only the specified keys.\r\n */\r\nexport function pick<T extends Record<string, unknown>, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {\r\n const result = {} as Pick<T, K>\r\n for (const key of keys) {\r\n if (key in obj) {\r\n result[key] = obj[key]\r\n }\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Extracts a property value from each item in an array.\r\n */\r\nexport function pluck<T, K extends keyof T>(items: T[], key: K): T[K][] {\r\n return items.map(item => item[key])\r\n}\r\n\r\n/**\r\n * Randomizes array order in-place using the Fisher-Yates algorithm.\r\n */\r\nexport function shuffle<T>(items: T[]): T[] {\r\n const result = [...items]\r\n for (let i = result.length - 1; i > 0; i--) {\r\n const j = Math.floor(Math.random() * (i + 1))\r\n const temp = result[i]!\r\n result[i] = result[j]!\r\n result[j] = temp\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Returns a random element from the array, or undefined if empty.\r\n */\r\nexport function sample<T>(items: T[]): T | undefined {\r\n return items.length > 0 ? items[Math.floor(Math.random() * items.length)] : undefined\r\n}\r\n\r\n/**\r\n * Returns an array of `size` random elements (without duplicates).\r\n */\r\nexport function sampleSize<T>(items: T[], size: number): T[] {\r\n if (size <= 0 || items.length === 0) return []\r\n const pool = shuffle(items)\r\n return pool.slice(0, Math.min(size, items.length))\r\n}\r\n\r\n/**\r\n * Splits an array into chunks of the specified size.\r\n */\r\nexport function chunk<T>(items: T[], size: number): T[][] {\r\n if (size <= 0 || items.length === 0) return []\r\n const result: T[][] = []\r\n for (let i = 0; i < items.length; i += size) {\r\n result.push(items.slice(i, i + size))\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Returns a sorted copy of the array using the provided criteria functions.\r\n * Earlier criteria take precedence.\r\n */\r\nfunction compareValues(a: unknown, b: unknown): number {\r\n if (a === b) return 0\r\n if (a == null) return -1\r\n if (b == null) return 1\r\n if (typeof a === 'string' && typeof b === 'string') return a < b ? -1 : 1\r\n if (typeof a === 'number' && typeof b === 'number') return a < b ? -1 : 1\r\n return String(a) < String(b) ? -1 : 1\r\n}\r\n\r\nexport function sortBy<T>(items: T[], ...criteria: Array<(item: T) => unknown>): T[] {\r\n return [...items].sort((a, b) => {\r\n for (const criterion of criteria) {\r\n const cmp = compareValues(criterion(a), criterion(b))\r\n if (cmp !== 0) return cmp\r\n }\r\n return 0\r\n })\r\n}\r\n\r\n/**\r\n * Returns a sorted copy of the array by a single key and direction.\r\n */\r\nexport function orderBy<T>(items: T[], key: (item: T) => unknown, direction: SortDirection = 'asc'): T[] {\r\n return [...items].sort((a, b) => {\r\n const cmp = compareValues(key(a), key(b))\r\n return direction === 'asc' ? cmp : -cmp\r\n })\r\n}\r\n\r\n/**\r\n * Returns unique elements based on the result of keyFn.\r\n */\r\nexport function uniqueBy<T>(items: T[], keyFn: (item: T) => unknown): T[] {\r\n const seen = new Set<unknown>()\r\n return items.filter(item => {\r\n const key = keyFn(item)\r\n if (seen.has(key)) return false\r\n seen.add(key)\r\n return true\r\n })\r\n}\r\n\r\n/**\r\n * Flattens an array of arrays one level.\r\n */\r\nexport function flatten<T>(items: T[][]): T[] {\r\n const result: T[] = []\r\n for (const sub of items) {\r\n for (const item of sub) {\r\n result.push(item)\r\n }\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Returns an array with unique primitive values.\r\n */\r\nexport function uniq<T>(items: T[]): T[] {\r\n return [...new Set(items)]\r\n}\r\n\r\n/**\r\n * Returns the first element, or undefined if empty.\r\n */\r\nexport function first<T>(items: T[]): T | undefined {\r\n return items[0]\r\n}\r\n\r\n/**\r\n * Returns the last element, or undefined if empty.\r\n */\r\nexport function last<T>(items: T[]): T | undefined {\r\n return items[items.length - 1]\r\n}\r\n\r\n/**\r\n * Checks if a value is empty.\r\n * Works for arrays, objects, strings, Map, and Set.\r\n */\r\nexport function isEmpty(value: unknown): boolean {\r\n if (Array.isArray(value)) return value.length === 0\r\n if (typeof value === 'string') return value.length === 0\r\n if (value instanceof Map || value instanceof Set) return value.size === 0\r\n if (value !== null && typeof value === 'object') return Object.keys(value as Record<string, unknown>).length === 0\r\n return false\r\n}\r\n\r\nexport type SortDirection = 'asc' | 'desc'\r\n","const WORD_SPLIT_RE = /[A-Z]?[a-z]+|[A-Z]+(?=[A-Z][a-z]|\\d|\\b)|\\d+/g\r\n\r\nfunction splitWords(str: string): string[] {\r\n return str.match(WORD_SPLIT_RE) ?? []\r\n}\r\n\r\n/**\r\n * Capitalizes the first character and lowercases the rest.\r\n */\r\nexport function capitalize(str: string): string {\r\n if (str.length === 0) return str\r\n return str[0]!.toUpperCase() + str.slice(1).toLowerCase()\r\n}\r\n\r\n/**\r\n * Converts a string to camelCase.\r\n */\r\nexport function camelCase(str: string): string {\r\n const words = splitWords(str)\r\n if (words.length === 0) return ''\r\n const [firstWord, ...rest] = words\r\n return firstWord!.toLowerCase() + rest.map(w => w[0]!.toUpperCase() + w.slice(1).toLowerCase()).join('')\r\n}\r\n\r\n/**\r\n * Converts a string to kebab-case.\r\n */\r\nexport function kebabCase(str: string): string {\r\n return splitWords(str).map(w => w.toLowerCase()).join('-')\r\n}\r\n\r\n/**\r\n * Converts a string to snake_case.\r\n */\r\nexport function snakeCase(str: string): string {\r\n return splitWords(str).map(w => w.toLowerCase()).join('_')\r\n}\r\n\r\n/**\r\n * Converts a string to PascalCase.\r\n */\r\nexport function pascalCase(str: string): string {\r\n return splitWords(str).map(w => w[0]!.toUpperCase() + w.slice(1).toLowerCase()).join('')\r\n}\r\n\r\n/**\r\n * Truncates a string to the specified length, appending a suffix (default \"...\").\r\n */\r\nexport function truncate(str: string, maxLength: number, suffix = '...'): string {\r\n if (str.length <= maxLength) return str\r\n return str.slice(0, Math.max(0, maxLength - suffix.length)) + suffix\r\n}\r\n\r\n/**\r\n * Simple string interpolation using {{key}} syntax.\r\n *\r\n * @example template(\"Hello {{name}}\", { name: \"world\" }) // => \"Hello world\"\r\n */\r\nexport function template(str: string, data: Record<string, string | number>): string {\r\n return str.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key: string) => {\r\n const value = data[key]\r\n return value !== undefined ? String(value) : `{{${key}}}`\r\n })\r\n}\r\n\r\n/**\r\n * Generates a UUID v4 string.\r\n * Uses crypto.randomUUID when available, falls back to manual implementation.\r\n */\r\nexport function uuid(): string {\r\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\r\n return crypto.randomUUID()\r\n }\r\n const hex = '0123456789abcdef'\r\n const chars: string[] = []\r\n for (let i = 0; i < 36; i++) {\r\n if (i === 8 || i === 13 || i === 18 || i === 23) {\r\n chars.push('-')\r\n } else if (i === 14) {\r\n chars.push('4')\r\n } else if (i === 19) {\r\n chars.push(hex[Math.floor(Math.random() * 4) + 8]!)\r\n } else {\r\n chars.push(hex[Math.floor(Math.random() * 16)]!)\r\n }\r\n }\r\n return chars.join('')\r\n}\r\n\r\n/**\r\n * Generates a short random ID with configurable length and alphabet.\r\n *\r\n * @default size = 21, alphabet = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-\"\r\n */\r\nexport function nanoid(size = 21, alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-'): string {\r\n const len = alphabet.length\r\n let result = ''\r\n for (let i = 0; i < size; i++) {\r\n result += alphabet[Math.floor(Math.random() * len)]!\r\n }\r\n return result\r\n}\r\n\r\nconst HTML_ESCAPE_MAP: Record<string, string> = {\r\n '&': '&',\r\n '<': '<',\r\n '>': '>',\r\n '\"': '"',\r\n \"'\": ''',\r\n}\r\n\r\nconst HTML_UNESCAPE_MAP: Record<string, string> = {\r\n '&': '&',\r\n '<': '<',\r\n '>': '>',\r\n '"': '\"',\r\n ''': \"'\",\r\n ''': \"'\",\r\n}\r\n\r\n/**\r\n * Escapes HTML special characters (&, <, >, \", ').\r\n */\r\nexport function escapeHtml(str: string): string {\r\n return str.replace(/[&<>\"']/g, ch => HTML_ESCAPE_MAP[ch] ?? ch)\r\n}\r\n\r\n/**\r\n * Unescapes common HTML entities.\r\n */\r\nexport function unescapeHtml(str: string): string {\r\n return str.replace(/&(?:amp|lt|gt|quot|#39|#x27);/g, entity => HTML_UNESCAPE_MAP[entity] ?? entity)\r\n}\r\n\r\n/**\r\n * Removes whitespace from both ends of a string.\r\n */\r\nexport function trim(str: string): string {\r\n return str.trim()\r\n}\r\n\r\n/**\r\n * Removes whitespace from the start of a string.\r\n */\r\nexport function trimStart(str: string): string {\r\n return str.trimStart()\r\n}\r\n\r\n/**\r\n * Removes whitespace from the end of a string.\r\n */\r\nexport function trimEnd(str: string): string {\r\n return str.trimEnd()\r\n}\r\n\r\n/**\r\n * Pads a string to the given length by adding characters to both sides.\r\n */\r\nexport function pad(str: string, length: number, char = ' '): string {\r\n const totalPadding = Math.max(0, length - str.length)\r\n const leftPad = Math.floor(totalPadding / 2)\r\n const rightPad = totalPadding - leftPad\r\n return char.repeat(leftPad) + str + char.repeat(rightPad)\r\n}\r\n\r\n/**\r\n * Pads the start of a string to the given length.\r\n */\r\nexport function padStart(str: string, length: number, char = ' '): string {\r\n return str.padStart(length, char)\r\n}\r\n\r\n/**\r\n * Pads the end of a string to the given length.\r\n */\r\nexport function padEnd(str: string, length: number, char = ' '): string {\r\n return str.padEnd(length, char)\r\n}\r\n\r\n/**\r\n * Reverses a string.\r\n */\r\nexport function reverse(str: string): string {\r\n return str.split('').reverse().join('')\r\n}\r\n\r\n/**\r\n * Splits a string into words.\r\n */\r\nexport function words(str: string): string[] {\r\n return splitWords(str)\r\n}\r\n\r\n/**\r\n * Converts a string to a URL-friendly slug.\r\n */\r\nexport function slugify(str: string): string {\r\n return str\r\n .toLowerCase()\r\n .replace(/[^\\w\\s-]/g, '')\r\n .replace(/[\\s_]+/g, '-')\r\n .replace(/-+/g, '-')\r\n .replace(/^-+/, '')\r\n .replace(/-+$/, '')\r\n}\r\n\r\n/**\r\n * Counts occurrences of a substring in a string.\r\n */\r\nexport function countOccurrences(str: string, substring: string): number {\r\n if (substring.length === 0 || str.length === 0) return 0\r\n let count = 0\r\n let pos = 0\r\n while ((pos = str.indexOf(substring, pos)) !== -1) {\r\n count++\r\n pos += substring.length\r\n }\r\n return count\r\n}\r\n","import type { RetryOptions } from '../core/index.js'\r\n\r\n/**\r\n * Delays execution for the given number of milliseconds.\r\n */\r\nexport function sleep(ms: number): Promise<void> {\r\n return new Promise(resolve => setTimeout(resolve, ms))\r\n}\r\n\r\n/**\r\n * Rejects a promise if it does not resolve within the specified timeout.\r\n */\r\nexport async function timeout<T>(promise: Promise<T>, ms: number, errorMessage?: string): Promise<T> {\r\n let timer: ReturnType<typeof setTimeout> | undefined\r\n const timeoutPromise = new Promise<never>((_, reject) => {\r\n timer = setTimeout(() => reject(new Error(errorMessage ?? `Promise timed out after ${ms}ms`)), ms)\r\n })\r\n try {\r\n return await Promise.race([promise, timeoutPromise])\r\n } finally {\r\n if (timer !== undefined) clearTimeout(timer)\r\n }\r\n}\r\n\r\n/**\r\n * Races a promise against a timeout, returning 'timeout' if the timer wins.\r\n */\r\nexport async function raceWithTimeout<T>(promise: Promise<T>, ms: number): Promise<T | 'timeout'> {\r\n let timer: ReturnType<typeof setTimeout> | undefined\r\n const timeoutPromise = new Promise<'timeout'>(resolve => {\r\n timer = setTimeout(() => resolve('timeout'), ms)\r\n })\r\n try {\r\n return await Promise.race([promise, timeoutPromise])\r\n } finally {\r\n if (timer !== undefined) clearTimeout(timer)\r\n }\r\n}\r\n\r\n/**\r\n * Maps over an array with an async function, using Promise.allSettled.\r\n * Returns an array of PromiseSettledResult.\r\n */\r\nexport async function allSettledMap<T, R>(\r\n items: T[],\r\n fn: (item: T) => Promise<R>,\r\n): Promise<PromiseSettledResult<R>[]> {\r\n return await Promise.allSettled(items.map(fn))\r\n}\r\n\r\n/**\r\n * Maps over an array with an async function, limiting concurrency.\r\n *\r\n * @param concurrency - Maximum number of concurrent operations (default Infinity)\r\n */\r\nexport async function parallelMap<T, R>(\r\n items: T[],\r\n fn: (item: T) => Promise<R>,\r\n concurrency = Number.POSITIVE_INFINITY,\r\n): Promise<R[]> {\r\n if (concurrency === Number.POSITIVE_INFINITY) {\r\n return await Promise.all(items.map(fn))\r\n }\r\n\r\n const results: R[] = []\r\n const queue = [...items]\r\n\r\n const worker = async (): Promise<void> => {\r\n while (queue.length > 0) {\r\n const item = queue.shift()!\r\n results.push(await fn(item))\r\n }\r\n }\r\n\r\n const workerCount = Math.min(concurrency, items.length)\r\n const workers = Array.from({ length: workerCount }, () => worker())\r\n await Promise.all(workers)\r\n return results\r\n}\r\n\r\n/**\r\n * Retries an async function with exponential backoff.\r\n */\r\nexport async function retryAsync<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T> {\r\n const { attempts = 3, baseDelay = 1000, maxDelay = 30000, shouldRetry = () => true } = options ?? {}\r\n let lastError: unknown\r\n for (let attempt = 0; attempt < attempts; attempt++) {\r\n try {\r\n return await fn()\r\n } catch (error) {\r\n lastError = error\r\n if (!shouldRetry(error) || attempt >= attempts - 1) break\r\n const delay = Math.min(baseDelay * 2 ** attempt + Math.random() * baseDelay, maxDelay)\r\n await sleep(delay)\r\n }\r\n }\r\n throw lastError\r\n}\r\n\r\n/**\r\n * Composes async functions, passing the result of each to the next.\r\n */\r\nexport async function pipeline<T>(initial: T, ...fns: Array<(arg: T) => Promise<T>>): Promise<T> {\r\n let result = initial\r\n for (const fn of fns) {\r\n result = await fn(result)\r\n }\r\n return result\r\n}\r\n\r\n/**\r\n * Creates a deferred promise with external resolve and reject methods.\r\n */\r\nexport function deferred<T>(): Deferred<T> {\r\n let resolve!: (value: T) => void\r\n let reject!: (reason: unknown) => void\r\n const promise = new Promise<T>((res, rej) => {\r\n resolve = res\r\n reject = rej\r\n })\r\n return { promise, resolve, reject }\r\n}\r\n\r\nexport interface Deferred<T> {\r\n promise: Promise<T>\r\n resolve: (value: T) => void\r\n reject: (reason: unknown) => void\r\n}\r\n","/**\r\n * Options for CSV parsing.\r\n */\r\nexport interface CsvOptions {\r\n delimiter?: string\r\n header?: boolean\r\n skipEmptyLines?: boolean\r\n}\r\n\r\n/**\r\n * Parses a CSV string into an array of records (objects).\r\n *\r\n * @param input - CSV string\r\n * @param options - Optional parsing options\r\n */\r\nexport function parseCsv(input: string, options?: CsvOptions): Record<string, string>[] {\r\n const { delimiter = ',', header = true, skipEmptyLines = true } = options ?? {}\r\n\r\n const lines = input.split(/\\r?\\n/)\r\n const rows: string[][] = []\r\n\r\n for (const line of lines) {\r\n const trimmed = line.trim()\r\n if (skipEmptyLines && trimmed.length === 0) continue\r\n const values = parseCsvLine(trimmed, delimiter)\r\n rows.push(values)\r\n }\r\n\r\n if (rows.length === 0) return []\r\n\r\n if (header) {\r\n const [head, ...body] = rows\r\n if (head === undefined) return []\r\n return body.map(row => {\r\n const record: Record<string, string> = {}\r\n for (let i = 0; i < head.length; i++) {\r\n record[head[i]!] = row[i] ?? ''\r\n }\r\n return record\r\n })\r\n }\r\n\r\n return rows.map(row => {\r\n const record: Record<string, string> = {}\r\n for (let i = 0; i < row.length; i++) {\r\n record[String(i)] = row[i]!\r\n }\r\n return record\r\n })\r\n}\r\n\r\nfunction parseCsvLine(line: string, delimiter: string): string[] {\r\n const result: string[] = []\r\n let current = ''\r\n let inQuotes = false\r\n\r\n for (let i = 0; i < line.length; i++) {\r\n const ch = line[i]!\r\n if (inQuotes) {\r\n if (ch === '\"') {\r\n if (line[i + 1] === '\"') {\r\n current += '\"'\r\n i++\r\n } else {\r\n inQuotes = false\r\n }\r\n } else {\r\n current += ch\r\n }\r\n } else {\r\n if (ch === '\"') {\r\n inQuotes = true\r\n } else if (ch === delimiter) {\r\n result.push(current)\r\n current = ''\r\n } else {\r\n current += ch\r\n }\r\n }\r\n }\r\n result.push(current)\r\n return result\r\n}\r\n\r\n/**\r\n * Converts an array of records to a CSV string.\r\n */\r\nexport function stringifyCsv(data: Record<string, unknown>[], options?: { delimiter?: string }): string {\r\n const { delimiter = ',' } = options ?? {}\r\n if (data.length === 0) return ''\r\n\r\n const headers = Object.keys(data[0]!)\r\n const lines: string[] = [headers.map(v => escapeCsvField(v, delimiter)).join(delimiter)]\r\n\r\n for (const record of data) {\r\n const row = headers.map(h => escapeCsvField(String(record[h] ?? ''), delimiter))\r\n lines.push(row.join(delimiter))\r\n }\r\n\r\n return lines.join('\\n')\r\n}\r\n\r\nfunction escapeCsvField(value: string, delimiter: string): string {\r\n if (value.includes('\"') || value.includes(delimiter) || value.includes('\\n') || value.includes('\\r')) {\r\n return '\"' + value.replace(/\"/g, '\"\"') + '\"'\r\n }\r\n return value\r\n}\r\n\r\n/**\r\n * Safely parses a JSON string, returning the default value or null on failure.\r\n */\r\nexport function safeJsonParse<T>(input: string, default_?: T): T | null {\r\n try {\r\n return JSON.parse(input) as T\r\n } catch {\r\n return default_ ?? null\r\n }\r\n}\r\n\r\n/**\r\n * Reads an environment variable with optional default.\r\n */\r\nexport function env(name: string, default_?: string): string {\r\n const value = process.env[name]\r\n return value ?? default_ ?? ''\r\n}\r\n\r\n/**\r\n * Reads an environment variable as an integer.\r\n */\r\nexport function envInt(name: string, default_?: number): number {\r\n const value = process.env[name]\r\n if (value === undefined || value === '') return default_ ?? 0\r\n const parsed = Number.parseInt(value, 10)\r\n return Number.isNaN(parsed) ? (default_ ?? 0) : parsed\r\n}\r\n\r\n/**\r\n * Reads an environment variable as a boolean.\r\n */\r\nexport function envBool(name: string, default_?: boolean): boolean {\r\n const value = process.env[name]\r\n if (value === undefined || value === '') return default_ ?? false\r\n return value === 'true' || value === '1' || value === 'yes'\r\n}\r\n","/**\r\n * Checks if a value is a string.\r\n */\r\nexport function isString(value: unknown): value is string {\r\n return typeof value === 'string'\r\n}\r\n\r\n/**\r\n * Checks if a value is a number (not NaN, not Infinity).\r\n */\r\nexport function isNumber(value: unknown): value is number {\r\n return typeof value === 'number' && Number.isFinite(value)\r\n}\r\n\r\n/**\r\n * Checks if a value is a boolean.\r\n */\r\nexport function isBoolean(value: unknown): value is boolean {\r\n return typeof value === 'boolean'\r\n}\r\n\r\n/**\r\n * Checks if a value is a plain object (not null, not array, typeof 'object').\r\n */\r\nexport function isObject(value: unknown): value is Record<string, unknown> {\r\n return value !== null && typeof value === 'object' && !Array.isArray(value)\r\n}\r\n\r\n/**\r\n * Checks if a value is an array.\r\n */\r\nexport function isArray(value: unknown): value is unknown[] {\r\n return Array.isArray(value)\r\n}\r\n\r\n/**\r\n * Checks if a value is a function.\r\n */\r\nexport function isFunction(value: unknown): value is (...args: unknown[]) => unknown {\r\n return typeof value === 'function'\r\n}\r\n\r\n/**\r\n * Checks if a value is a Date.\r\n */\r\nexport function isDate(value: unknown): value is Date {\r\n return value instanceof Date && !Number.isNaN(value.getTime())\r\n}\r\n\r\n/**\r\n * Checks if a value is a RegExp.\r\n */\r\nexport function isRegExp(value: unknown): value is RegExp {\r\n return value instanceof RegExp\r\n}\r\n\r\n/**\r\n * Checks if a value is a Map.\r\n */\r\nexport function isMap(value: unknown): value is Map<unknown, unknown> {\r\n return value instanceof Map\r\n}\r\n\r\n/**\r\n * Checks if a value is a Set.\r\n */\r\nexport function isSet(value: unknown): value is Set<unknown> {\r\n return value instanceof Set\r\n}\r\n\r\n/**\r\n * Checks if a value is a Promise.\r\n */\r\nexport function isPromise(value: unknown): value is Promise<unknown> {\r\n return value instanceof Promise\r\n}\r\n\r\n/**\r\n * Checks if a value is null.\r\n */\r\nexport function isNull(value: unknown): value is null {\r\n return value === null\r\n}\r\n\r\n/**\r\n * Checks if a value is undefined.\r\n */\r\nexport function isUndefined(value: unknown): value is undefined {\r\n return value === undefined\r\n}\r\n\r\n/**\r\n * Checks if a value is null or undefined.\r\n */\r\nexport function isNil(value: unknown): value is null | undefined {\r\n return value === null || value === undefined\r\n}\r\n\r\n/**\r\n * Checks if a value is empty.\r\n * Works for strings, arrays, objects, Map, and Set.\r\n */\r\nexport function isEmpty(value: unknown): boolean {\r\n if (value === null || value === undefined) return true\r\n if (typeof value === 'string') return value.length === 0\r\n if (Array.isArray(value)) return value.length === 0\r\n if (value instanceof Map || value instanceof Set) return value.size === 0\r\n if (typeof value === 'object') return Object.keys(value as Record<string, unknown>).length === 0\r\n return false\r\n}\r\n\r\n/**\r\n * Asserts that a value is defined (not null or undefined).\r\n * Throws if the value is null or undefined.\r\n */\r\nexport function assertDefined<T>(value: T, message?: string): asserts value is NonNullable<T> {\r\n if (value === null || value === undefined) {\r\n throw new Error(message ?? 'Expected value to be defined')\r\n }\r\n}\r\n\r\n/**\r\n * Asserts that a value matches a type guard. Throws if it doesn't.\r\n */\r\nexport function assertType<T>(value: unknown, guard: (v: unknown) => v is T, message?: string): asserts value is T {\r\n if (!guard(value)) {\r\n throw new Error(message ?? 'Value does not match expected type')\r\n }\r\n}\r\n\r\n/**\r\n * Wraps a value in an array if it is not already one.\r\n */\r\nexport function ensureArray<T>(value: T | T[]): T[] {\r\n return Array.isArray(value) ? value : [value]\r\n}\r\n\r\n/**\r\n * Alias for ensureArray.\r\n */\r\nexport function castArray<T>(value: T | T[]): T[] {\r\n return ensureArray(value)\r\n}\r\n\r\n/**\r\n * Returns a string representation of the value's type.\r\n *\r\n * Possible values: \"string\", \"number\", \"boolean\", \"array\", \"object\", \"function\",\r\n * \"date\", \"regexp\", \"map\", \"set\", \"promise\", \"null\", \"undefined\", \"nan\", \"infinity\"\r\n */\r\nexport function getType(value: unknown): string {\r\n if (value === null) return 'null'\r\n if (value === undefined) return 'undefined'\r\n if (typeof value === 'string') return 'string'\r\n if (typeof value === 'boolean') return 'boolean'\r\n if (typeof value === 'function') return 'function'\r\n if (typeof value === 'number') {\r\n if (Number.isNaN(value)) return 'nan'\r\n if (!Number.isFinite(value)) return 'infinity'\r\n return 'number'\r\n }\r\n if (Array.isArray(value)) return 'array'\r\n if (value instanceof Date) return 'date'\r\n if (value instanceof RegExp) return 'regexp'\r\n if (value instanceof Map) return 'map'\r\n if (value instanceof Set) return 'set'\r\n if (value instanceof Promise) return 'promise'\r\n return 'object'\r\n}\r\n","import { readFileSync, readdirSync, existsSync } from 'node:fs'\r\nimport { join, basename } from 'node:path'\r\nimport type { ScanResult, ReplacementSuggestion, SecurityIssue, ScannerConfig } from '../types.js'\r\nimport { KNOWN_MAPPINGS, KNOWN_CVES, type PackageMapping } from '../known-mappings.js'\r\n\r\ninterface LockfilePackages {\r\n [key: string]: { version?: string; dependencies?: Record<string, string> } | undefined\r\n}\r\n\r\ninterface LockfileData {\r\n packages: LockfilePackages\r\n}\r\n\r\nfunction parsePackageJson(path: string): { name: string; dependencies: Record<string, string>; devDependencies: Record<string, string> } {\r\n const raw = readFileSync(path, 'utf-8')\r\n const json = JSON.parse(raw)\r\n return {\r\n name: json.name ?? basename(join(path, '..')),\r\n dependencies: (json.dependencies as Record<string, string>) ?? {},\r\n devDependencies: (json.devDependencies as Record<string, string>) ?? {},\r\n }\r\n}\r\n\r\nfunction parseLockfile(projectPath: string): LockfileData | null {\r\n const lockPath = join(projectPath, 'package-lock.json')\r\n if (!existsSync(lockPath)) return null\r\n try {\r\n const raw = readFileSync(lockPath, 'utf-8')\r\n const json = JSON.parse(raw)\r\n const packages: LockfilePackages = {}\r\n\r\n if (json.packages) {\r\n for (const [key, val] of Object.entries(json.packages as Record<string, { version?: string }>)) {\r\n if (key) {\r\n packages[key] = val\r\n }\r\n }\r\n }\r\n\r\n if (json.dependencies && Object.keys(packages).length === 0) {\r\n for (const [key, val] of Object.entries(json.dependencies as Record<string, { version?: string; requires?: Record<string, string> }>)) {\r\n packages[key] = { version: val.version, dependencies: val.requires }\r\n }\r\n }\r\n\r\n return { packages }\r\n } catch {\r\n return null\r\n }\r\n}\r\n\r\nfunction detectImportInFile(filePath: string, regex: RegExp): boolean {\r\n try {\r\n const content = readFileSync(filePath, 'utf-8')\r\n return regex.test(content)\r\n } catch {\r\n return false\r\n }\r\n}\r\n\r\nfunction detectImportsInSrc(projectPath: string, mapping: PackageMapping): boolean {\r\n const regex = new RegExp(mapping.detectionPattern)\r\n const srcDir = join(projectPath, 'src')\r\n if (!existsSync(srcDir)) return false\r\n\r\n try {\r\n const files = collectSourceFiles(srcDir)\r\n for (const file of files) {\r\n if (detectImportInFile(file, regex)) return true\r\n }\r\n } catch {\r\n return false\r\n }\r\n return false\r\n}\r\n\r\nfunction collectSourceFiles(dir: string): string[] {\r\n const results: string[] = []\r\n try {\r\n const entries = readdirSync(dir, { withFileTypes: true })\r\n for (const entry of entries) {\r\n if (entry.name === 'node_modules' || entry.name === 'dist' || entry.name === '.git' || entry.name === 'coverage' || entry.name === '.tsup') {\r\n continue\r\n }\r\n const full = join(dir, entry.name)\r\n if (entry.isDirectory()) {\r\n results.push(...collectSourceFiles(full))\r\n } else if (entry.isFile()) {\r\n const ext = entry.name.split('.').pop()\r\n if (ext === 'ts' || ext === 'tsx' || ext === 'js' || ext === 'jsx' || ext === 'mjs' || ext === 'cjs') {\r\n results.push(full)\r\n }\r\n }\r\n }\r\n } catch {\r\n // skip inaccessible dirs\r\n }\r\n return results\r\n}\r\n\r\nfunction estimateTransitiveCount(lockfile: LockfileData | null, directNames: Set<string>): number {\r\n if (!lockfile) return 0\r\n let count = 0\r\n for (const key of Object.keys(lockfile.packages)) {\r\n if (!key || key === '') continue\r\n const name = key.startsWith('node_modules/') ? key.slice('node_modules/'.length) : key\r\n const rootName = name.startsWith('@') ? `${name.split('/')[0]}/${name.split('/')[1]}` : name.split('/')[0]\r\n if (rootName && !directNames.has(rootName)) {\r\n count++\r\n }\r\n }\r\n return count\r\n}\r\n\r\nfunction parseSize(value: string): number {\r\n const cleaned = value.replace(/\\(.*?\\)/g, '').trim()\r\n const match = cleaned.match(/^([\\d.]+)\\s*(KB|MB)/i)\r\n if (!match) return 0\r\n const num = Number.parseFloat(match[1]!)\r\n if (!match[2]) return 0\r\n if (match[2].toUpperCase() === 'MB') return num * 1024\r\n return num\r\n}\r\n\r\nexport async function scanProject(config: ScannerConfig): Promise<ScanResult> {\r\n const projectPath = config.path ?? '.'\r\n const pkgPath = join(projectPath, 'package.json')\r\n\r\n if (!existsSync(pkgPath)) {\r\n throw new Error(`No package.json found at ${projectPath}. Run dep-exray in a JavaScript/TypeScript project directory.`)\r\n }\r\n\r\n const pkg = parsePackageJson(pkgPath)\r\n const lockfile = parseLockfile(projectPath)\r\n\r\n const allDeps: Record<string, string> = { ...pkg.dependencies, ...pkg.devDependencies }\r\n const directNames = new Set(Object.keys(allDeps))\r\n\r\n const transitiveCount = estimateTransitiveCount(lockfile, directNames)\r\n\r\n const highImpactReplacements: ReplacementSuggestion[] = []\r\n const mediumImpactReplacements: ReplacementSuggestion[] = []\r\n const securityIssues: SecurityIssue[] = []\r\n\r\n const sizeMap: Record<string, string> = {}\r\n for (const m of KNOWN_MAPPINGS) {\r\n sizeMap[m.name] = m.size\r\n }\r\n\r\n for (const mapping of KNOWN_MAPPINGS) {\r\n const isDirect = directNames.has(mapping.name)\r\n if (!isDirect) continue\r\n\r\n const isUsed = detectImportsInSrc(projectPath, mapping)\r\n if (!isUsed && !config.verbose) continue\r\n\r\n const mappingSize = parseSize(sizeMap[mapping.name] ?? '0 KB')\r\n const replacementSize = mapping.replacement.startsWith('native') ? 0 : 5\r\n const reductionStr = mappingSize > 1024\r\n ? `${(mappingSize / 1024).toFixed(1)} MB → ${replacementSize} KB`\r\n : `${mappingSize.toFixed(0)} KB → ${replacementSize} KB`\r\n\r\n const suggestion: ReplacementSuggestion = {\r\n packageName: mapping.name,\r\n reason: mapping.reason,\r\n replacement: mapping.replacement,\r\n estimatedSizeReduction: reductionStr,\r\n confidence: mapping.confidence,\r\n autoPrReady: mapping.autoPrReady,\r\n }\r\n\r\n if (mapping.confidence === 'high') {\r\n highImpactReplacements.push(suggestion)\r\n } else {\r\n mediumImpactReplacements.push(suggestion)\r\n }\r\n }\r\n\r\n for (const [name, cves] of Object.entries(KNOWN_CVES)) {\r\n if (directNames.has(name)) {\r\n for (const cveItem of cves) {\r\n securityIssues.push({\r\n packageName: name,\r\n cveId: cveItem.cve,\r\n severity: cveItem.severity as SecurityIssue['severity'],\r\n fix: cveItem.fix,\r\n })\r\n }\r\n }\r\n }\r\n\r\n let totalSizeKB = 0\r\n for (const depName of directNames) {\r\n const sizeStr = sizeMap[depName]\r\n if (sizeStr) {\r\n totalSizeKB += parseSize(sizeStr)\r\n } else {\r\n totalSizeKB += 50\r\n }\r\n }\r\n totalSizeKB += transitiveCount * 30\r\n\r\n const totalSizeStr = totalSizeKB > 1024\r\n ? `${(totalSizeKB / 1024).toFixed(1)} MB`\r\n : `${totalSizeKB.toFixed(0)} KB`\r\n\r\n return {\r\n projectName: pkg.name,\r\n directDeps: directNames.size,\r\n transitiveDeps: transitiveCount,\r\n totalEstimatedSize: totalSizeStr,\r\n highImpactReplacements,\r\n mediumImpactReplacements,\r\n securityIssues,\r\n }\r\n}\r\n","\r\n\r\nexport interface PackageMapping {\r\n name: string\r\n size: string\r\n replacement: string\r\n confidence: 'high' | 'medium' | 'low'\r\n autoPrReady: boolean\r\n reason: string\r\n detectionPattern: string\r\n}\r\n\r\nexport const KNOWN_MAPPINGS: PackageMapping[] = [\r\n {\r\n name: 'lodash',\r\n size: '4.2 MB',\r\n replacement: 'jscore-core',\r\n confidence: 'high',\r\n autoPrReady: true,\r\n reason: 'Most lodash functions have direct replacements in jscore-core with 99% API compatibility',\r\n detectionPattern: 'from [\\'\"]lodash[\\'\"]|require\\\\([\\'\"]lodash[\\'\"]\\\\)',\r\n },\r\n {\r\n name: 'moment',\r\n size: '2.5 MB',\r\n replacement: 'jscore-core/date',\r\n confidence: 'high',\r\n autoPrReady: true,\r\n reason: 'date utilities in jscore-core cover 95% of common moment use cases',\r\n detectionPattern: 'from [\\'\"]moment[\\'\"]|require\\\\([\\'\"]moment[\\'\"]\\\\)',\r\n },\r\n {\r\n name: 'date-fns',\r\n size: '1.2 MB (tree-shaked ~50KB)',\r\n replacement: 'jscore-core/date',\r\n confidence: 'medium',\r\n autoPrReady: false,\r\n reason: 'Partially overlapping — jscore-core covers basic date ops but not all locale support',\r\n detectionPattern: 'from [\\'\"]date-fns[\\'\"]|require\\\\([\\'\"]date-fns[\\'\"]\\\\)',\r\n },\r\n {\r\n name: 'axios',\r\n size: '1.6 MB',\r\n replacement: 'native fetch + jscore-core/async/retry',\r\n confidence: 'medium',\r\n autoPrReady: false,\r\n reason: 'Native fetch covers most use cases; needs manual review for interceptors',\r\n detectionPattern: 'from [\\'\"]axios[\\'\"]|require\\\\([\\'\"]axios[\\'\"]\\\\)',\r\n },\r\n {\r\n name: 'uuid',\r\n size: '30 KB',\r\n replacement: 'crypto.randomUUID() (native)',\r\n confidence: 'high',\r\n autoPrReady: true,\r\n reason: 'crypto.randomUUID() is available in all modern Node.js and browsers',\r\n detectionPattern: 'from [\\'\"]uuid[\\'\"]|require\\\\([\\'\"]uuid[\\'\"]\\\\)',\r\n },\r\n {\r\n name: 'deepmerge',\r\n size: '15 KB',\r\n replacement: 'jscore-core',\r\n confidence: 'high',\r\n autoPrReady: true,\r\n reason: 'jscore-core provides deepMerge out of the box',\r\n detectionPattern: 'from [\\'\"]deepmerge[\\'\"]|require\\\\([\\'\"]deepmerge[\\'\"]\\\\)',\r\n },\r\n {\r\n name: 'lodash.merge',\r\n size: '25 KB',\r\n replacement: 'jscore-core',\r\n confidence: 'high',\r\n autoPrReady: true,\r\n reason: 'jscore-core provides deepMerge out of the box',\r\n detectionPattern: 'from [\\'\"]lodash\\\\.(merge|clone|pick|omit|get|set)[\\'\"]',\r\n },\r\n {\r\n name: 'chalk',\r\n size: '45 KB',\r\n replacement: 'picocolors',\r\n confidence: 'medium',\r\n autoPrReady: false,\r\n reason: \"picocolors is 3KB vs chalk's 45KB with same API\",\r\n detectionPattern: 'from [\\'\"]chalk[\\'\"]|require\\\\([\\'\"]chalk[\\'\"]\\\\)',\r\n },\r\n {\r\n name: 'nanoid',\r\n size: '8 KB',\r\n replacement: 'jscore-core/string (nanoid)',\r\n confidence: 'high',\r\n autoPrReady: true,\r\n reason: 'jscore-core provides nanoid with same API',\r\n detectionPattern: 'from [\\'\"]nanoid[\\'\"]|require\\\\([\\'\"]nanoid[\\'\"]\\\\)',\r\n },\r\n {\r\n name: 'dayjs',\r\n size: '50 KB',\r\n replacement: 'jscore-core/date',\r\n confidence: 'medium',\r\n autoPrReady: false,\r\n reason: 'Partially overlapping — covers basics but not all plugins',\r\n detectionPattern: 'from [\\'\"]dayjs[\\'\"]|require\\\\([\\'\"]dayjs[\\'\"]\\\\)',\r\n },\r\n {\r\n name: 'clsx',\r\n size: '5 KB',\r\n replacement: 'native template literals',\r\n confidence: 'high',\r\n autoPrReady: true,\r\n reason: 'Can be replaced with simple template literal conditional pattern',\r\n detectionPattern: 'from [\\'\"]clsx[\\'\"]|require\\\\([\\'\"]clsx[\\'\"]\\\\)',\r\n },\r\n]\r\n\r\nexport const KNOWN_CVES: Record<string, { cve: string; severity: string; fix: string }[]> = {\r\n 'ansi-regex': [\r\n { cve: 'CVE-2021-3807', severity: 'high', fix: 'Update to ansi-regex@6.0.1 or later' },\r\n ],\r\n 'semver': [\r\n { cve: 'CVE-2022-25883', severity: 'medium', fix: 'Update to semver@7.5.2 or later' },\r\n ],\r\n 'json5': [\r\n { cve: 'CVE-2022-46175', severity: 'high', fix: 'Update to json5@2.2.3 or later' },\r\n ],\r\n 'lodash': [\r\n { cve: 'CVE-2020-28502', severity: 'high', fix: 'Update to lodash@4.17.21 or later' },\r\n { cve: 'CVE-2020-8203', severity: 'medium', fix: 'Update to lodash@4.17.21 or later' },\r\n ],\r\n}\r\n","import pc from 'picocolors'\r\nimport type { ScanResult, ReplacementSuggestion, SecurityIssue } from '../types.js'\r\n\r\nfunction severityColor(severity: SecurityIssue['severity']): string {\r\n switch (severity) {\r\n case 'critical': return pc.bold(pc.red(severity.toUpperCase()))\r\n case 'high': return pc.red(severity.toUpperCase())\r\n case 'medium': return pc.yellow(severity.toUpperCase())\r\n case 'low': return pc.dim(severity.toUpperCase())\r\n }\r\n}\r\n\r\nfunction confidenceIcon(confidence: ReplacementSuggestion['confidence']): string {\r\n switch (confidence) {\r\n case 'high': return pc.green('●')\r\n case 'medium': return pc.yellow('●')\r\n case 'low': return pc.red('●')\r\n }\r\n}\r\n\r\nexport function generateReport(result: ScanResult, jsonOutput?: boolean): string {\r\n if (jsonOutput) {\r\n return JSON.stringify(result, null, 2)\r\n }\r\n\r\n const lines: string[] = []\r\n\r\n // ┌─┐│└┘─\r\n lines.push(pc.bold(pc.cyan(`┌${'─'.repeat(58)}┐`)))\r\n lines.push(pc.bold(pc.cyan(`│${' '.repeat(18)}dep-exray Report${' '.repeat(21)}│`)))\r\n lines.push(pc.bold(pc.cyan(`├${'─'.repeat(58)}┤`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.white('📦 PROJECT:')} ${pc.bold(result.projectName)}${' '.repeat(Math.max(1, 47 - result.projectName.length))}│`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.white('📊 DEPENDENCIES:')} ${pc.bold(String(result.directDeps))} direct + ${pc.bold(String(result.transitiveDeps))} transitive${' '.repeat(Math.max(1, 27 - String(result.transitiveDeps).length))}│`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.white('💾 TOTAL SIZE:')} ${pc.bold(result.totalEstimatedSize)}${' '.repeat(Math.max(1, 42 - result.totalEstimatedSize.length))}│`)))\r\n lines.push(pc.bold(pc.cyan(`├${'─'.repeat(58)}┤`)))\r\n\r\n if (result.highImpactReplacements.length > 0) {\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.green('🟢')} ${pc.bold(pc.green('HIGH IMPACT REPLACEMENTS'))}${' '.repeat(23)}│`)))\r\n for (const item of result.highImpactReplacements) {\r\n const autoPr = item.autoPrReady ? pc.green('✓ Auto-PR ready') : pc.dim('Manual review needed')\r\n const confIcon = confidenceIcon(item.confidence)\r\n lines.push(pc.bold(pc.cyan(`├${'─'.repeat(58)}┤`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.red('✗')} ${pc.bold(item.packageName)} (${item.estimatedSizeReduction})${' '.repeat(Math.max(1, 38 - item.estimatedSizeReduction.length))}│`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.dim('→')} ${pc.cyan(item.replacement)}${' '.repeat(Math.max(1, 51 - item.replacement.length))}│`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.dim('└─')} ${autoPr} ${confIcon} ${item.confidence}${' '.repeat(Math.max(1, 35))}│`)))\r\n }\r\n }\r\n\r\n if (result.mediumImpactReplacements.length > 0) {\r\n lines.push(pc.bold(pc.cyan(`├${'─'.repeat(58)}┤`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.yellow('🟡')} ${pc.bold(pc.yellow('MEDIUM IMPACT REPLACEMENTS'))}${' '.repeat(20)}│`)))\r\n for (const item of result.mediumImpactReplacements) {\r\n const autoPr = item.autoPrReady ? pc.green('✓ Auto-PR ready') : pc.dim('Manual review needed')\r\n const confIcon = confidenceIcon(item.confidence)\r\n lines.push(pc.bold(pc.cyan(`├${'─'.repeat(58)}┤`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.red('✗')} ${pc.bold(item.packageName)} (${item.estimatedSizeReduction})${' '.repeat(Math.max(1, 38 - item.estimatedSizeReduction.length))}│`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.dim('→')} ${pc.cyan(item.replacement)}${' '.repeat(Math.max(1, 51 - item.replacement.length))}│`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.dim('└─')} ${autoPr} ${confIcon} ${item.confidence}${' '.repeat(Math.max(1, 35))}│`)))\r\n }\r\n }\r\n\r\n if (result.securityIssues.length > 0) {\r\n lines.push(pc.bold(pc.cyan(`├${'─'.repeat(58)}┤`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.red('🔴')} ${pc.bold(pc.red('SECURITY ISSUES'))}${' '.repeat(33)}│`)))\r\n for (const issue of result.securityIssues) {\r\n lines.push(pc.bold(pc.cyan(`├${'─'.repeat(58)}┤`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${severityColor(issue.severity)} ${pc.bold(issue.cveId)} in ${issue.packageName}${' '.repeat(Math.max(1, 40 - issue.packageName.length))}│`)))\r\n lines.push(pc.bold(pc.cyan(`│ ${pc.dim('→')} ${issue.fix}${' '.repeat(Math.max(1, 52 - issue.fix.length))}│`)))\r\n }\r\n }\r\n\r\n lines.push(pc.bold(pc.cyan(`└${'─'.repeat(58)}┘`)))\r\n\r\n return lines.join('\\n')\r\n}\r\n","import { readFileSync } from 'node:fs'\r\nimport { readdirSync, statSync } from 'node:fs'\r\nimport { join, extname } from 'node:path'\r\n\r\nconst SOURCE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'])\r\n\r\nfunction isSourceFile(file: string): boolean {\r\n return SOURCE_EXTENSIONS.has(extname(file))\r\n}\r\n\r\nfunction collectSourceFiles(dir: string): string[] {\r\n const results: string[] = []\r\n try {\r\n const entries = readdirSync(dir, { withFileTypes: true })\r\n for (const entry of entries) {\r\n const fullPath = join(dir, entry.name)\r\n if (entry.name === 'node_modules' || entry.name === 'dist' || entry.name === '.git' || entry.name === 'coverage' || entry.name === '.tsup') {\r\n continue\r\n }\r\n if (entry.isDirectory()) {\r\n results.push(...collectSourceFiles(fullPath))\r\n } else if (entry.isFile() && isSourceFile(entry.name)) {\r\n results.push(fullPath)\r\n }\r\n }\r\n } catch {\r\n // skip directories we can't read\r\n }\r\n return results\r\n}\r\n\r\nfunction escapeRegex(str: string): string {\r\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\r\n}\r\n\r\nexport async function analyzeUsage(\r\n projectPath: string,\r\n packageName: string,\r\n): Promise<{\r\n isUsed: boolean\r\n importCount: number\r\n importLocations: string[]\r\n}> {\r\n const importLocations: string[] = []\r\n const escaped = escapeRegex(packageName)\r\n const importRegex = new RegExp(\r\n `(?:from\\\\s+['\"]${escaped}(?:/['\"]|['\"])|require\\\\(\\\\s*['\"]${escaped}(?:/|['\"]))`,\r\n 'g',\r\n )\r\n\r\n const srcDir = join(projectPath, 'src')\r\n let files: string[]\r\n try {\r\n if (statSync(srcDir).isDirectory()) {\r\n files = collectSourceFiles(srcDir)\r\n } else {\r\n files = collectSourceFiles(projectPath)\r\n }\r\n } catch {\r\n files = collectSourceFiles(projectPath)\r\n }\r\n\r\n for (const file of files) {\r\n try {\r\n const content = readFileSync(file, 'utf-8')\r\n importRegex.lastIndex = 0\r\n if (importRegex.test(content)) {\r\n importLocations.push(file)\r\n }\r\n } catch {\r\n // skip unreadable files\r\n }\r\n }\r\n\r\n return {\r\n isUsed: importLocations.length > 0,\r\n importCount: importLocations.length,\r\n importLocations,\r\n }\r\n}\r\n"],"mappings":"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","names":["resolve","format","pad","sub","words","resolve","getType","join","basename","basename","join","readFileSync","readdirSync","join","extname","collectSourceFiles"]}
|
package/dist/math/index.js
CHANGED
|
@@ -41,7 +41,8 @@ function div(a, b) {
|
|
|
41
41
|
}
|
|
42
42
|
function round(value, precision = 0) {
|
|
43
43
|
const factor = Math.pow(10, precision);
|
|
44
|
-
|
|
44
|
+
const shifted = Number((value * factor).toPrecision(15));
|
|
45
|
+
return Math.round(shifted) / factor;
|
|
45
46
|
}
|
|
46
47
|
function floor(value, precision = 0) {
|
|
47
48
|
const factor = Math.pow(10, precision);
|
package/dist/math/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/math/index.ts"],"sourcesContent":["/**\r\n * Error thrown when attempting to divide by zero.\r\n */\r\nexport class DivisionByZeroError extends Error {\r\n constructor() {\r\n super('Division by zero')\r\n this.name = 'DivisionByZeroError'\r\n }\r\n}\r\n\r\nfunction getPrecision(value: number): number {\r\n if (!isFinite(value)) return 0\r\n const eIndex = String(value).indexOf('e')\r\n if (eIndex > -1) {\r\n const exp = parseInt(String(value).slice(eIndex + 1), 10)\r\n if (exp < 0) return Math.abs(exp)\r\n return 0\r\n }\r\n const str = String(value)\r\n const dot = str.indexOf('.')\r\n return dot === -1 ? 0 : str.length - dot - 1\r\n}\r\n\r\nfunction toPrecisionFactor(a: number, b: number): number {\r\n return Math.pow(10, Math.max(getPrecision(a), getPrecision(b)))\r\n}\r\n\r\n/**\r\n * Safely adds two numbers, handling floating-point precision.\r\n *\r\n * @param a - First number.\r\n * @param b - Second number.\r\n * @returns The sum.\r\n */\r\nexport function add(a: number, b: number): number {\r\n const factor = toPrecisionFactor(a, b)\r\n return (Math.round(a * factor) + Math.round(b * factor)) / factor\r\n}\r\n\r\n/**\r\n * Safely subtracts two numbers, handling floating-point precision.\r\n *\r\n * @param a - First number.\r\n * @param b - Second number.\r\n * @returns The difference.\r\n */\r\nexport function sub(a: number, b: number): number {\r\n const factor = toPrecisionFactor(a, b)\r\n return (Math.round(a * factor) - Math.round(b * factor)) / factor\r\n}\r\n\r\n/**\r\n * Safely multiplies two numbers, handling floating-point precision.\r\n *\r\n * @param a - First number.\r\n * @param b - Second number.\r\n * @returns The product.\r\n */\r\nexport function mul(a: number, b: number): number {\r\n const factorA = toPrecisionFactor(a, 1)\r\n const factorB = toPrecisionFactor(1, b)\r\n const result = (Math.round(a * factorA) * Math.round(b * factorB)) / (factorA * factorB)\r\n return result\r\n}\r\n\r\n/**\r\n * Safely divides two numbers.\r\n *\r\n * @param a - The dividend.\r\n * @param b - The divisor.\r\n * @returns The quotient.\r\n * @throws {DivisionByZeroError} If `b` is zero.\r\n */\r\nexport function div(a: number, b: number): number {\r\n if (b === 0) throw new DivisionByZeroError()\r\n const factor = toPrecisionFactor(a, b)\r\n return Math.round(a * factor) / Math.round(b * factor)\r\n}\r\n\r\n/**\r\n * Rounds a number to the given precision.\r\n *\r\n * @param value - The number to round.\r\n * @param precision - Number of decimal places (default 0).\r\n * @returns The rounded value.\r\n */\r\nexport function round(value: number, precision: number = 0): number {\r\n const factor = Math.pow(10, precision)\r\n
|
|
1
|
+
{"version":3,"sources":["../../src/math/index.ts"],"sourcesContent":["/**\r\n * Error thrown when attempting to divide by zero.\r\n */\r\nexport class DivisionByZeroError extends Error {\r\n constructor() {\r\n super('Division by zero')\r\n this.name = 'DivisionByZeroError'\r\n }\r\n}\r\n\r\nfunction getPrecision(value: number): number {\r\n if (!isFinite(value)) return 0\r\n const eIndex = String(value).indexOf('e')\r\n if (eIndex > -1) {\r\n const exp = parseInt(String(value).slice(eIndex + 1), 10)\r\n if (exp < 0) return Math.abs(exp)\r\n return 0\r\n }\r\n const str = String(value)\r\n const dot = str.indexOf('.')\r\n return dot === -1 ? 0 : str.length - dot - 1\r\n}\r\n\r\nfunction toPrecisionFactor(a: number, b: number): number {\r\n return Math.pow(10, Math.max(getPrecision(a), getPrecision(b)))\r\n}\r\n\r\n/**\r\n * Safely adds two numbers, handling floating-point precision.\r\n *\r\n * @param a - First number.\r\n * @param b - Second number.\r\n * @returns The sum.\r\n */\r\nexport function add(a: number, b: number): number {\r\n const factor = toPrecisionFactor(a, b)\r\n return (Math.round(a * factor) + Math.round(b * factor)) / factor\r\n}\r\n\r\n/**\r\n * Safely subtracts two numbers, handling floating-point precision.\r\n *\r\n * @param a - First number.\r\n * @param b - Second number.\r\n * @returns The difference.\r\n */\r\nexport function sub(a: number, b: number): number {\r\n const factor = toPrecisionFactor(a, b)\r\n return (Math.round(a * factor) - Math.round(b * factor)) / factor\r\n}\r\n\r\n/**\r\n * Safely multiplies two numbers, handling floating-point precision.\r\n *\r\n * @param a - First number.\r\n * @param b - Second number.\r\n * @returns The product.\r\n */\r\nexport function mul(a: number, b: number): number {\r\n const factorA = toPrecisionFactor(a, 1)\r\n const factorB = toPrecisionFactor(1, b)\r\n const result = (Math.round(a * factorA) * Math.round(b * factorB)) / (factorA * factorB)\r\n return result\r\n}\r\n\r\n/**\r\n * Safely divides two numbers.\r\n *\r\n * @param a - The dividend.\r\n * @param b - The divisor.\r\n * @returns The quotient.\r\n * @throws {DivisionByZeroError} If `b` is zero.\r\n */\r\nexport function div(a: number, b: number): number {\r\n if (b === 0) throw new DivisionByZeroError()\r\n const factor = toPrecisionFactor(a, b)\r\n return Math.round(a * factor) / Math.round(b * factor)\r\n}\r\n\r\n/**\r\n * Rounds a number to the given precision.\r\n *\r\n * @param value - The number to round.\r\n * @param precision - Number of decimal places (default 0).\r\n * @returns The rounded value.\r\n */\r\nexport function round(value: number, precision: number = 0): number {\r\n const factor = Math.pow(10, precision)\r\n // Use toPrecision to avoid floating-point multiplication errors\r\n // e.g. 1.005 * 100 = 100.49999999999999 without this fix\r\n const shifted = Number((value * factor).toPrecision(15))\r\n return Math.round(shifted) / factor\r\n}\r\n\r\n/**\r\n * Floors a number to the given precision.\r\n *\r\n * @param value - The number to floor.\r\n * @param precision - Number of decimal places (default 0).\r\n * @returns The floored value.\r\n */\r\nexport function floor(value: number, precision: number = 0): number {\r\n const factor = Math.pow(10, precision)\r\n return Math.floor(value * factor) / factor\r\n}\r\n\r\n/**\r\n * Ceils a number to the given precision.\r\n *\r\n * @param value - The number to ceil.\r\n * @param precision - Number of decimal places (default 0).\r\n * @returns The ceiled value.\r\n */\r\nexport function ceil(value: number, precision: number = 0): number {\r\n const factor = Math.pow(10, precision)\r\n return Math.ceil(value * factor) / factor\r\n}\r\n\r\n/**\r\n * Checks if two numbers are approximately equal within a tolerance.\r\n *\r\n * @param a - First number.\r\n * @param b - Second number.\r\n * @param tolerance - Maximum difference (default `Number.EPSILON`).\r\n * @returns Whether the numbers are approximately equal.\r\n */\r\nexport function approxEqual(a: number, b: number, tolerance: number = Number.EPSILON): boolean {\r\n return Math.abs(a - b) <= tolerance\r\n}\r\n\r\n/**\r\n * Clamps a value within the inclusive range [min, max].\r\n *\r\n * @param value - The value to clamp.\r\n * @param min - The lower bound.\r\n * @param max - The upper bound.\r\n * @returns The clamped value.\r\n * @throws {RangeError} If `min` exceeds `max`.\r\n */\r\nexport function clamp(value: number, min: number, max: number): number {\r\n if (min > max) {\r\n throw new RangeError('Minimum value cannot exceed maximum value')\r\n }\r\n return Math.min(Math.max(value, min), max)\r\n}\r\n\r\n/**\r\n * Computes the sum of an array of numbers.\r\n *\r\n * @param values - Array of numbers.\r\n * @returns The total sum.\r\n */\r\nexport function sum(values: number[]): number {\r\n let total = 0\r\n for (let i = 0; i < values.length; i++) {\r\n total += values[i]!\r\n }\r\n return total\r\n}\r\n\r\n/**\r\n * Computes the average (mean) of an array of numbers.\r\n *\r\n * @param values - Array of numbers.\r\n * @returns The average.\r\n * @throws {RangeError} If the array is empty.\r\n */\r\nexport function average(values: number[]): number {\r\n if (values.length === 0) {\r\n throw new RangeError('Cannot compute average of an empty array')\r\n }\r\n return sum(values) / values.length\r\n}\r\n\r\n/**\r\n * Generates a random integer between `min` and `max` (inclusive).\r\n *\r\n * @param min - The minimum integer.\r\n * @param max - The maximum integer.\r\n * @returns A random integer.\r\n * @throws {RangeError} If arguments are not integers or `min > max`.\r\n */\r\nexport function randomInt(min: number, max: number): number {\r\n if (!Number.isInteger(min) || !Number.isInteger(max)) {\r\n throw new RangeError('Arguments must be integers')\r\n }\r\n if (min > max) {\r\n throw new RangeError('Minimum value cannot exceed maximum value')\r\n }\r\n return Math.floor(Math.random() * (max - min + 1)) + min\r\n}\r\n\r\n/**\r\n * Checks if a number is within the inclusive range [min, max].\r\n *\r\n * @param value - The number to check.\r\n * @param min - The lower bound.\r\n * @param max - The upper bound.\r\n * @returns Whether the value is in range.\r\n */\r\nexport function inRange(value: number, min: number, max: number): boolean {\r\n return value >= min && value <= max\r\n}\r\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "superjs-core",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "Zero-dependency JavaScript standard library + dependency health scanner — core, math, date, collection, string, async, io, type, crypto, path & dep-exray",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -83,6 +83,7 @@
|
|
|
83
83
|
"types": "./dist/dep-exray/cli.d.ts"
|
|
84
84
|
}
|
|
85
85
|
},
|
|
86
|
+
"sideEffects": false,
|
|
86
87
|
"files": [
|
|
87
88
|
"dist"
|
|
88
89
|
],
|