addons/isl/src/utils.tsblame
View source
b69ab311/**
b69ab312 * Copyright (c) Meta Platforms, Inc. and affiliates.
b69ab313 *
b69ab314 * This source code is licensed under the MIT license found in the
b69ab315 * LICENSE file in the root directory of this source tree.
b69ab316 */
b69ab317
b69ab318import type {ViteHotContext} from 'vite/types/hot';
b69ab319import type {CommitInfo, Disposable, Hash} from './types';
b69ab3110
b69ab3111export function firstOfIterable<T>(it: IterableIterator<T>): T | undefined {
b69ab3112 return it.next().value;
b69ab3113}
b69ab3114
b69ab3115/** Get the short 12-character hash from a full hash. */
b69ab3116export function short(hash: Hash): string {
b69ab3117 return hash.slice(0, 12);
b69ab3118}
b69ab3119
b69ab3120export function assert(shouldBeTrue: boolean, error: string): asserts shouldBeTrue {
b69ab3121 if (!shouldBeTrue) {
b69ab3122 throw new Error(error);
b69ab3123 }
b69ab3124}
b69ab3125
b69ab3126export function arraysEqual<T>(a: Array<T>, b: Array<T>): boolean {
b69ab3127 if (a.length !== b.length) {
b69ab3128 return false;
b69ab3129 }
b69ab3130 return a.every((val, i) => b[i] === val);
b69ab3131}
b69ab3132
b69ab3133export type NonNullReactElement = React.ReactElement | React.ReactFragment;
b69ab3134
b69ab3135export function getWindowWidthInPixels(): number {
b69ab3136 if (isTest) {
b69ab3137 return 1000;
b69ab3138 }
b69ab3139 // Use client width and not screen width to handle embedding as an iframe.
b69ab3140 return document.body.clientWidth;
b69ab3141}
b69ab3142
b69ab3143export function leftPad(val: string | number, len: number, char: string) {
b69ab3144 const str = val.toString();
b69ab3145 return `${Array(len - str.length + 1).join(char)}${str}`;
b69ab3146}
b69ab3147
b69ab3148/** Whether running in a test environment. */
b69ab3149export const isTest = typeof process !== 'undefined' && process.env.NODE_ENV === 'test';
b69ab3150
b69ab3151export const isDev = process.env.NODE_ENV === 'development';
b69ab3152
b69ab3153const cleanUpRegister = new FinalizationRegistry<() => void>((cleanUp: () => void) => {
b69ab3154 cleanUp();
b69ab3155});
b69ab3156
b69ab3157/**
b69ab3158 * Register a clean up callback or a disposable when `obj` is GC-ed.
b69ab3159 *
b69ab3160 * If `hot` is set (`import.meta.hot`), the `cleanUp` is registered with the
b69ab3161 * hot reload API instead. Note the `import.meta` depends on where it lives.
b69ab3162 * So we cannot use `import.meta` here (which will affect this `utils.ts` hot
b69ab3163 * reloading behavior, not the callsite module).
b69ab3164 */
b69ab3165export function registerCleanup(obj: object, cleanUp: () => void, hot?: ViteHotContext): void {
b69ab3166 if (hot != null) {
b69ab3167 hot.dispose(() => {
b69ab3168 cleanUp();
b69ab3169 });
b69ab3170 } else {
b69ab3171 cleanUpRegister.register(obj, cleanUp);
b69ab3172 }
b69ab3173}
b69ab3174
b69ab3175/** Similar to `registerCleanup`, but takes a `Disposable` */
b69ab3176export function registerDisposable(
b69ab3177 obj: object,
b69ab3178 disposable: Disposable,
b69ab3179 hot?: ViteHotContext,
b69ab3180): void {
b69ab3181 registerCleanup(obj, () => disposable.dispose(), hot);
b69ab3182}
b69ab3183
b69ab3184/** Calculate hour difference between two dates (date1 - date2) */
b69ab3185export function calculateHourDifference(date1: Date, date2: Date): number {
b69ab3186 const msDifference = date1.getTime() - date2.getTime();
b69ab3187 const hoursDifference = msDifference / (1000 * 60 * 60);
b69ab3188 return hoursDifference;
b69ab3189}
b69ab3190
b69ab3191/**
b69ab3192 * Check if a commit is on the master branch
b69ab3193 */
b69ab3194export function isCommitMaster(commit: CommitInfo): boolean {
b69ab3195 if (commit.remoteBookmarks == null) {
b69ab3196 return false;
b69ab3197 }
b69ab3198 return commit.remoteBookmarks.some(bookmark => bookmark.includes('master'));
b69ab3199}