Skip to content

Instantly share code, notes, and snippets.

View jeremy-code's full-sized avatar

Jeremy Nguyen jeremy-code

View GitHub Profile
@jeremy-code
jeremy-code / README.md
Last active February 14, 2025 22:38
eslint-plugin-react-refresh/next.js

I needed a place to put this and it didn't feel deserving of its own package or repo, hence here it is.

eslint-plugin-react-refresh settings for Next.js for rule "react-refresh/only-export-components" exports in Next.js.

For more information, see Next.js: Introduction > Architecture > Fast Refresh#How It Works

FYI some other exports that are not here because they shouldn't be alongside JSX are:

[

Some brief explorations of getStaticValue() from @eslint-community/eslint-utils (or in this case, the typed version from @typescript-eslint/utils". Intending to update this later with better examples (and code) once I get more time.

@jeremy-code
jeremy-code / _Importexport Raycast preferences with GIt history.md
Last active March 13, 2025 04:05
Import/export Raycast preferences with GIt history

Raycast has a feature to import/export preferences in a .rayconfig file format. This isn't ideal for use in a dotfiles-esque Git repository since it would be difficult to compare changes with a compressed file. Also, unfortunately, syncing is only possible on a pro subscription and only through Raycast's cloud service.

To get a more useful JSON file from the .rayconfig (example shown in example.rayconfig.json), you will have to first have to export a decrypted version. Go to Settings > Extensions > Raycast > Export Settings & Data and under "Export Password," which by default is 12345678, you will want to delete that.

After that, run the "Export Settings & Data" command. You should be able to export all of the preferences (Settings, Extensions, Floating Notes, Script Directories, Snippets) except Quicklinks without setting a password.

Then, in terminal, run gzip --decompress --keep --suffix .rayconfig NAME_OF_FILE.rayconfig and you should get a JSON file similar to example.rayconfig.json.

After that,

@jeremy-code
jeremy-code / tsconfig.json
Created April 20, 2024 23:32
TSConfig Cheat Sheet with Comments
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Projects */
"target": "ES2022",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"moduleDetection": "force",
/* Modules */
@jeremy-code
jeremy-code / getUser.ts
Created March 6, 2024 03:48
getUser.ts for react-oidc-context
import { User } from "oidc-client-ts";
const { VITE_OIDC_AUTHORITY, VITE_OIDC_CLIENT_ID } = import.meta.env;
const AUTH_KEY = `oidc.user:${VITE_OIDC_AUTHORITY}:${VITE_OIDC_CLIENT_ID}`;
// Get the user from local storage (used for API requests where hooks are not available)
export const getUser = () => {
const storageString = localStorage.getItem(AUTH_KEY);
if (!storageString) return null;
@jeremy-code
jeremy-code / colors.ts
Created March 6, 2024 03:30
colors (RGB, hexToRgb, rgbToHex)
type RGB = {
r: number;
g: number;
b: number;
};
export const hexToRgb = (hex: string): RGB => {
const bigint = parseInt(hex.slice(1), 16);
return {
@jeremy-code
jeremy-code / debounce.ts
Created March 6, 2024 03:08
debounce.ts
export function debounce<T extends (...args: Parameters<T>) => ReturnType<T>>(
callback: T,
wait: number,
immediate?: boolean
): (...args: Parameters<T>) => void {
let timeout: NodeJS.Timeout | undefined;
return function (this: ThisParameterType<T>, ...args: Parameters<T>): void {
const later = () => {
timeout = undefined;
@jeremy-code
jeremy-code / parseFormData.ts
Created March 6, 2024 03:06
parseFormData.ts
export const parseFormData = (formData: FormData) =>
Array.from(formData.entries()).reduce(
(acc, [k, v]) => {
if (!acc[k]) {
const values = formData.getAll(k);
acc[k] = values.length > 1 ? values : v;
}
return acc;
},
{} as Record<string, FormDataEntryValue | FormDataEntryValue[]>
@jeremy-code
jeremy-code / formatBytes.ts
Created March 6, 2024 03:03
formatBytes.ts, format bytes
export const formatBytes = (bytes: number, options?: Intl.NumberFormatOptions) => {
/**
* Per {@link https://tc39.es/ecma402/#table-sanctioned-single-unit-identifiers},
* these are the valid units for the "unit" style. Since each unit multiple is
* considered a separate unit, we have to manually determine the appropriate unit
* and corresponding value, otherwise we get formatting such as "1 BB" instead of
* "1 GB".
*/
const units = ["byte", "kilobyte", "megabyte", "gigabyte", "terabyte", "petabyte"];
if (!bytes || bytes <= 0) return `0 ${units[0]}s`;
@jeremy-code
jeremy-code / useProgressStore.tsx
Created March 6, 2024 02:58
useProgressStore hook, get progress from a ky event handler
// when you create ky instance, set onDownloadProgress: progressStore.setSnapshot,
import { useSyncExternalStore } from "react";
import type { DownloadProgress } from "ky";
export const shallowCompare = <T extends Record<string, unknown>>(obj1: T, obj2: T) => {
if (Object.is(obj1, obj2)) return true;
if (!(obj1 instanceof Object) || !(obj2 instanceof Object)) return false;