61 lines
2.0 KiB
TypeScript
61 lines
2.0 KiB
TypeScript
import type { Clock } from "@suaveplan/types";
|
|
import { MS_PER_DAY } from "../constants/constants.js";
|
|
import { TimeEncodingType } from "../types/license.js";
|
|
|
|
const defaultClock: Clock = () => Date.now();
|
|
|
|
/**
|
|
* Convert a `Date` (or now) to days since the Unix epoch. The 18-bit
|
|
* `timeValue` field can hold ~718 years of day numbers.
|
|
*/
|
|
export function getDayNumber(date?: Date, clock: Clock = defaultClock): number {
|
|
const ms = date !== undefined ? date.getTime() : clock();
|
|
return Math.floor(ms / MS_PER_DAY);
|
|
}
|
|
|
|
/** Inverse of {@link getDayNumber}. */
|
|
export function dayNumberToDate(dayNumber: number): Date {
|
|
return new Date(dayNumber * MS_PER_DAY);
|
|
}
|
|
|
|
/**
|
|
* Determine whether a license is expired given its time-encoding metadata.
|
|
* The optional `clock` defaults to `Date.now()` and is read only when
|
|
* `referenceDate` is omitted.
|
|
*/
|
|
export function checkExpiration(
|
|
timeEncodingType: TimeEncodingType,
|
|
timeValue: number,
|
|
referenceDate?: Date,
|
|
creationDate?: Date,
|
|
clock: Clock = defaultClock
|
|
): { isExpired: boolean; expirationDate?: Date } {
|
|
const ref = referenceDate ?? new Date(clock());
|
|
|
|
switch (timeEncodingType) {
|
|
case TimeEncodingType.NONE:
|
|
return { isExpired: false };
|
|
|
|
case TimeEncodingType.ABSOLUTE_DAYS: {
|
|
const expirationDate = dayNumberToDate(timeValue);
|
|
return { isExpired: ref > expirationDate, expirationDate };
|
|
}
|
|
|
|
case TimeEncodingType.RELATIVE_DAYS: {
|
|
const creation = creationDate ?? ref;
|
|
const expirationDate = new Date(
|
|
creation.getTime() + timeValue * MS_PER_DAY
|
|
);
|
|
return { isExpired: ref > expirationDate, expirationDate };
|
|
}
|
|
|
|
case TimeEncodingType.ABSOLUTE_TIMESTAMP: {
|
|
const expirationDate = new Date(timeValue * 1000);
|
|
return { isExpired: ref > expirationDate, expirationDate };
|
|
}
|
|
|
|
default:
|
|
return { isExpired: false };
|
|
}
|
|
}
|