Snippets

  • Git

    | Command                                          | Description                                                                                   |
    |--------------------------------------------------|-----------------------------------------------------------------------------------------------|
    | `git blame -L 28,43 path/to/file`                | Shows who modified each line in a specific range of a file.                                   |
    | `git blame -L :'class LocalFile' filepath`       | Blames a block of code in a file matching a specific pattern.                                 |
    | `git log -L28,43:filepath`                       | Lists commits that last touched a specified region of a file.                                 |
    | `git blame -w`                                   | Ignores whitespace changes in `git blame`.                                                    |
    | `git blame -C`                                   | Follows code movement across files in `git blame`. Can be used up to three times.              |
    | `git diff --word-diff`                           | Shows word-level differences in `git diff` output.                                            |
    | `git config --global rerere.enabled true`        | Enables reuse of recorded resolution of conflicts.                                            |
    | `git config --global rerere.autoUpdate true`     | Automatically updates the index with the result of rerere resolution.                         |
    | `git config --global branch.sort -committerdate` | Sorts branches by last commit date in descending order.                                       |
    | `git push --force-with-lease`                    | Safely force-pushes, ensuring no updates were pushed to the branch since your last fetch.     |
    | `git maintenance start`                          | Starts Git maintenance tasks to optimize repository performance.                              |
    
  • Usefull bash commands

    # Delete node_modules using fd (github.com/sharkdp/fd)
    fd -HI node_modules -X rm -rf
  • Typescript tips and tricks. This is update whenever I come across something cool

    // Credits to Matt Pocock
    
    type CreateAPIMethod = <
      TInput extends Record<string, string>, // The input 
      TOutput // The output
    >(opts: {
          url: string;
          method: "GET" | "POST"
          }) = (input: TInput) = Promise<TOutput>;
        declare const createAPIMethod: CreateAPIMethod;
    /**
    * You can reuse this function as many times as you
    * like to create all your API methods!
    */
    const getUser = createAPIMethod<
          { id: string }, 
          { name: string }
    >({
      method: "GET", url: "/user",
    })
    
    getUser({ id: 123 }); //
    // Loose autocomplete -> after 5.3 not needed anymore 'string' is sufficient
    type IconSize =
      | "small"
      | "medium"
      | "large"
      | (string & {});
    
    // Remove the prefix property
    type RemovePrefix<T, Prefix extends string> = {
        [K in keyof T as K extends `${Prefix}_${infer _}` ? never : K]: T[K]
    };
    /**
     * Throttle a function call, allowing it to be called at most once every `wait` milliseconds.
     * @param fn - The function to be throttled.
     * @param wait - The time in milliseconds to wait before allowing the next invocation.
     * @returns A throttled version of the input function.
     */
    function throttle<T extends (...args: any[]) => any>(fn: T, wait: number): (...funcArgs: Parameters<T>) => void {
      let isThrottling: boolean = false;
      let lastArgs: Parameters<T> | null = null;
      let lastThis: ThisParameterType<T> | null = null;
    
      const call = () => {
        if (lastArgs === null || lastThis === null) {
          isThrottling = false;
          return;
        }
        fn.apply(lastThis, lastArgs);
        lastArgs = null;
        lastThis = null;
        setTimeout(call, wait);
      };
    
      return function(this: ThisParameterType<T>, ...args: Parameters<T>): void {
        if (isThrottling) {
          lastArgs = args;
          lastThis = this;
          return;
        }
    
        fn.apply(this, args);
        isThrottling = true;
        setTimeout(() => {
          isThrottling = false;
          call();
        }, wait);
      };
    }
  • The CSS property to prevent scrollbar pushing the layout

    /* The scrollbar-gutter CSS property allows authors to reserve space for the scrollbar, preventing unwanted layout changes as the content grows while also avoiding unnecessary visuals when scrolling isn't needed. */
    /* https://developer.mozilla.org/en-US/docs/Web/CSS/scrollbar-gutter */
    
    .scrollbar {
      scrollbar-gutter: stable;
    }
  • A simple HTTP service to wrap fetch services with abstraction to handle errors

    /**
     * A strategy for fetching data from the server.
     *
     * @callback FetchStrategy
     * @param {string} url - The URL to fetch data from.
     * @param {RequestInit} [options] - Additional options for the fetch request.
     * @returns {Promise<Response>} A promise that resolves to the fetch response.
     */
    export type FetchStrategy = (
      url: string,
      options?: RequestInit
    ) => Promise<Response>;
    
    /**
     * A service for sending HTTP requests.
     * @class HttpService
     * @param {FetchStrategy} [fetchStrategy=fetch] - A strategy for fetching data from the server.
     * @returns {HttpService} An instance of the HttpService class.
     * @example
     * const httpService = new HttpService(customFetch);
     * const data = await httpService.get("https://example.com");
     * console.log(data);
     */
    export default class HttpService {
      private fetchStrategy: FetchStrategy;
    
      constructor(fetchStrategy: FetchStrategy = fetch) {
        this.fetchStrategy = fetchStrategy;
      }
    
      async fetchHandler<T = unknown>(
        url: string,
        options?: RequestInit
      ): Promise<T> {
        try {
          const response = await this.fetchStrategy(url, options);
    
          if (!response.ok) {
            throw new HttpError(
              `HTTP Error: ${response.status} - ${response.statusText}`,
              response.status
            );
          }
    
          const data = (await response.json()) as T;
    
          return data;
        } catch (error) {
          throw new RequestError(`Request failed: ${error.message}`);
        }
      }
    
      /**
       * Sends an HTTP GET request.
       *
       * @template T
       * @param {string} url - The URL to send the GET request to.
       * @param {RequestInit} [options] - Additional options for the request.
       * @returns {Promise<T>} A promise that resolves to the parsed response data.
       */
      async get<T = unknown>(url: string, options?: RequestInit): Promise<T> {
        return this.fetchHandler<T>(url, options);
      }
    
      /**
       * Sends an HTTP POST request.
       *
       * @template T
       * @param {string} url - The URL to send the POST request to.
       * @param {Record<string, unknown> | BodyInit | null} [body=null] - The request body.
       * @param {Omit<RequestInit, "method" | "body">} [options] - Additional options for the request.
       * @returns {Promise<T>} A promise that resolves to the parsed response data.
       */
      async post<T = unknown>(
        url: string,
        body: Record<string, unknown> | BodyInit | null = null,
        options?: Omit<RequestInit, "method" | "body">
      ): Promise<T> {
        return this.fetchHandler<T>(url, {
          method: "POST",
          body: body ? JSON.stringify(body) : null,
          ...options
        });
      }
    }
    
    class HttpError extends Error {
      constructor(message: string, public statusCode: number) {
        super(message);
        this.name = "HttpError";
      }
    }
    
    class RequestError extends Error {
      constructor(message: string) {
        super(message);
        this.name = "RequestError";
      }
    }
    
    /**
     * A service for sending HTTP requests.
     * We use globalThis.fetch and rebind the context to the globalThis object because
     * `fetch` is reliant on this being referenced to the window
     *
     * @type {HttpService}
     * @example
     * const data = await FetchService.get("https://example.com");
     * console.log(data);
     */
    export const FetchService: HttpService = new HttpService(
      globalThis.fetch.bind(globalThis)
    );
    
       
    // Or a custom strategy with different options
    const authFetch: FetchStrategy = async (url, options) => {
      return fetch(`${baseUrl}${url}`, {
        credentials: "include",
        headers: {
          Accept: "application/json",
          "Content-Type": "application/json",
          ...headers
        },
        ...options
      });
    };
    
    export const AuthService = new HttpService(authFetch);
    
  • A simple way for error handling in Typescript

    enum ResultKind {
      OK = "Ok",
      ERR = "Err",
    }
    
    export type Result<T, E> = Ok<T> | Err<E>;
    
    interface ResultBase<A, E> {
      kind: ResultKind;
      map<B>(fn: (_: A) => B): Result<B, E>;
      bind<B>(fn: (_: A) => Result<B, E>): Result<B, E>;
      match<B>(obj: { ok: (_: A) => B; err: (_: E) => B }): B;
    }
    
    export type Ok<A> = Readonly<ResultBase<A, never> & { kind: ResultKind.OK; value: A }>;
    
    export function ok<A>(a: A): Ok<A> {
      return {
        kind: ResultKind.OK,
        value: a,
        map(fn) {
          return ok(fn(this.value));
        },
        bind(fn) {
          return fn(this.value);
        },
        match({ ok }) {
          return ok(this.value);
        },
      };
    }
    
    export type Err<E> = Readonly<ResultBase<never, E> & { kind: ResultKind.ERR; error: E }>;
    
    export function err<E>(e: E): Err<E> {
      return {
        kind: ResultKind.ERR,
        error: e,
        map() {
          return this;
        },
        bind() {
          return this;
        },
        match({ err }) {
          return err(this.error);
        },
      };
    }
    
  • ZOD

    import { zodResolver } from "@hookform/resolvers/zod";
    import { type UseFormProps, useForm } from "react-hook-form";
    import { type z } from "zod";
    
    /**
     * A wrapper around `useForm` that uses `zodResolver` as the resolver.
     *
     * @example
     *
     * const schema = z.object({
     *  email: z.string().email(),
     *  password: z.string().min(8),
     * })
     * const form = useZodForm({ schema })
     *
     *
     */
    export default function useZodForm<TSchema extends z.ZodType>(
      props: Omit<UseFormProps<TSchema["_input"]>, "resolver"> & {
        schema: TSchema;
      },
    ) {
      const form = useForm<TSchema["_input"]>({
        ...props,
        resolver: zodResolver(props.schema, undefined, {
          // This makes it so we can use `.transform()`s on the schema without same transform getting applied again when it reaches the server
          raw: true,
        }),
      });
    
      return form;
    }
    
    /**
     * @description
     * This function is used to create a safe loader function.
     * It takes in a loader function and a zod schema.
     * The loader function is expected to return an object.
     * The zod schema is used to validate the output of the loader function.
     * If the output of the loader function is not valid, an error is thrown.
     * If the output of the loader function is valid, it is returned.
     * @param outputValidation - a zod schema used to validate the output of the loader function
     * @param loader - a function that returns an object
     * @returns a function that returns the output of the loader function if it is validate
     * @example
     * const getUsers = safeLoader({
     *  outputValidation: z.object({
     *    name: z.string(),
     *  }),
     *  loader: async () => {
     *    return {
     *      name: "John Doe",
     *    };
     *  },
     * })
     */
    export function safeLoader<
      LoaderInputs extends any[],
      OutputValidation extends ZodTypeAny,
    >({
      outputValidation,
      loader,
    }: {
      outputValidation: OutputValidation;
      loader: (...argsList: LoaderInputs) => any;
    }) {
      return async function (
        ...args: LoaderInputs
      ): Promise<z.infer<OutputValidation>> {
        const outputs = await loader.apply(null, args);
        const parsedOutput = outputValidation.parse(outputs);
        return parsedOutput;
      };
    }