Skip to content

Instantly share code, notes, and snippets.

@renoirb
Last active February 7, 2023 19:58
Show Gist options
  • Save renoirb/16f391e0cbd4e4e04f368c06b396e650 to your computer and use it in GitHub Desktop.
Save renoirb/16f391e0cbd4e4e04f368c06b396e650 to your computer and use it in GitHub Desktop.
Some useful snippets

Some other useful snippets

Prettify

Found on Twitter

Imagine you've got some type that's got a bunch of intersections. When you hover over it, it gives you a bunch of gross intersections instead of displaying the resolved type

export type Flatten<T> = {
  [K in keyof T]: T[K];
} & {}

isObject

export const isObject = <T = Record<string, unknown>>(value: unknown): value is T => {
  // https://github.com/lodash/lodash/blob/4.17.21-es/isObject.js
  // https://github.com/DefinitelyTyped/DefinitelyTyped/blob/ca8d73db/types/lodash.isobject/index.d.ts
  const type = typeof value
  return value != null && (type == 'object' || type == 'function')
}

DOM user-defined Type Guards

export const isHtmlElement = (maybe: unknown): maybe is HTMLElement => {
  if (maybe && typeof maybe === 'function' && 'prototype' in maybe) {
    return 'title' in maybe || 'lang' in maybe || 'offsetParent' in maybe
  }
  return false
}

export const isElement = (maybe: unknown): maybe is Element => {
  if (isHtmlElement(maybe)) {
    return 'localName' in maybe || 'shadowRoot' in maybe
  }
  return false
}

export const isNode = (maybe: unknown): maybe is Node => {
  if (isElement(maybe)) {
    return 'ATTRIBUTE_NODE' in maybe || 'nodeName' in maybe || 'parentElement' in maybe || 'parentNode' in maybe
  }
  return false
}

Walking Record, anonymize one field

export const toAnonymizedCredentialMapString: (input: Record<string, unknown>) => string = input => {
  assert.equal(isObject(input), true, `Is not an HashMap object`)
  const copy: Record<string, string> = JSON.parse(JSON.stringify(input || {}))
  for (const [field, value] of Object.entries(copy)) {
    if (field === 'password' && value !== '') {
      copy[field] = '***'
    }
  }
 
  return JSON.stringify(copy)
}

Is Object

export const isObject = <T = Record<string, unknown>>(value: unknown): value is T => {
  // https://github.com/lodash/lodash/blob/4.17.21-es/isObject.js
  // https://github.com/DefinitelyTyped/DefinitelyTyped/blob/ca8d73db/types/lodash.isobject/index.d.ts
  const type = typeof value
  return value != null && (type == 'object' || type == 'function')
}

Record creation

export const TestUser = Object.freeze({
  /**
   * Account of someone who did upload their avatar photo
   */
  someUserAccountWithParticularRole: 'someUserAccountWithParticularRole',
} as const)
 
/**
 * Based on TestUser enum above, what are the acceptable keys.
 *
 * See:
 * - https://gist.github.com/renoirb/e8f48e4b54f16f9fb8f0bf38b6bc9c8d#using-read-only-array-of-strings-as-source-for-type
 * - https://gist.github.com/renoirb/d30e7edbe32d9c6b9c2006b13db7a016
 */
export const TEST_USERS_KEYS = Object.freeze(
  Object.entries(TestUser)
    .filter(i => 1 in i && typeof i[1] === 'string')
    .map(i => i[0])
    .sort(),
) as TestUserKeys[]

export type ITestUser = typeof TEST_USERS_KEYS[number]


export type ICredential {
  username: string
  password: string
}

export type ITestUserCredientialMap = Record<ITestUser, ICredential>

export const readCredentialMapFromProcessEnv = (
  input: ITestUserCredientialMap,
  env: NodeJS.ProcessEnv
): ITestUserCredientialMap => {
  const username = Reflect.has(env, input.username) ? Reflect.get(env, input.username) : null
  const password = Reflect.has(env, input.password) ? Reflect.get(env, input.password) : null
  const missing = Object.entries<Record<string, string | void>>({ username, password })
    .map(v => (v[1] === null ? `${v[0]}: ${Reflect.get(input, v[0])}` : undefined))
    .filter(Boolean)
  if (missing.length > 0) {
    const message = `We could not find process.env.<key> for: ${missing.join(', ')}`
    throw new Error(message)
  }
  const out: ITestUserCredientialMap = {
    username,
    password,
  }
  // assertIsTestUserCredientialMap(out)
  return out
}

export const TEST_USERS_CREDENTIAL_MAP: ITestUserCredientialMap = {
  someUserAccountWithParticularRole: {
    username: 'jdoe',
    password: 'password123!',
  },
}

NestedError

/**
 * Subclass of standard `Error` that eagerly collects the callstack of the error
 * that caused it. This way you can investigate the core problem that happened
 * by looking at the callstack from up to bottom (from higher level errors to
 * lower level).
 *
 * Bookmark:
 * - https://github.com/Veetaha/ts-nested-error/blob/2bb11d66/src/nested-error.ts#L7-L86
 */
export class NestedError extends Error {
  /**
   * Combined callstack of this error and the errors that it wraps.
   * If the JavaScript runtime doesn't support `Error::stack` property
   * this will contain only the concatenated messages.
   */
  readonly stack: string

  /**
   * The list of lower-level errors wrapped by this error.
   */
  readonly innerErrors: Error[]

  private static readonly getErrorReport =
    typeof new Error().stack === 'string' ? (err: Error) => err?.stack : (err: Error) => `${err.name}: ${err.message}`

  /**
   * Returns the function that accepts any value that was thrown as the first argument and
   * throws it wrapped into `NestedError` or class derived from `NestedError` (provided
   * this method was called directly in the context of that dervied class constructor)
   * with the given `message`.
   * Returned function will pass accepted `Error` object directly to `NestedError`
   * as `innerErrors` by invoking `toError(err)` on it.
   *
   * You'll most likely want to use this method with promises:
   *
   * ```ts
   * userService.getPage().then(
   *     data => console.log(`Hooray! data: ${data}`),
   *     NestedError.rethrow('failed to fetch users page')
   * );
   * ```
   *
   * @param message Message to attach `NestedError` created by the returned function.
   */
  static rethrow(message: string) {
    return (...errs: unknown[]) => {
      throw new this(message, ...errs)
    }
  }

  /**
   * Allocates an instance of `NestedError` with the given error `message` and
   * optional `innerError` (which will be automatically coerced using `toError()`).
   *
   * @param message     Laconic error message to attach to the created `NestedError`.
   * @param innerErrors Optional errors that will be wrapped by this higher level
   *                    error. This value will be automatically coerced using `toError()`.
   */
  constructor(message?: string, ...innerErrors: unknown[]) {
    super(message)
    const thisErrorReport = NestedError.getErrorReport(this)
    if (innerErrors.length === 1) {
      const innerError = toError(innerErrors[0])
      this.innerErrors = [innerError]
      const errReport = NestedError.getErrorReport(innerError)
      this.stack = `${thisErrorReport}\n\n======= INNER ERROR =======\n\n${errReport}`
      return
    }
    this.innerErrors = innerErrors.map(err => toError(err))
    const innerErrorReports = this.innerErrors
      .map((error, idx) => {
        const errReport = NestedError.getErrorReport(error)
        return `======= INNER ERROR (${idx + 1} of ${innerErrors.length}) =======\n\n${errReport}`
      })
      .join('\n\n')
    this.stack = `${thisErrorReport}\n\n${innerErrorReports}`
  }
}

/**
 * Returns `err` itself if `err instanceof Error === true`, otherwise attemts to
 * stringify it and wrap into `Error` object to be returned.
 *
 * **This function is guaranteed never to throw.**
 *
 * @param err Possbile `instanceof Error` to return or value of any type that will
 *            be wrapped into a fully-fledged `Error` object.
 *
 * Bookmark:
 * - https://github.com/Veetaha/ts-nested-error/blob/2bb11d66/src/nested-error.ts#L97-L120
 */
export function toError(err: unknown): Error

export function toError(err: unknown) {
  try {
    return err instanceof Error ? err : new Error(`Value that is not an instance of Error was thrown: ${err}`)
  } catch {
    return new Error(
      'Failed to stringify non-instance of Error that was thrown.' +
        'This is possibly due to the fact that toString() method of the value' +
        "doesn't return a primitive value.",
    )
  }
}

/**
 * Not Implemented Exception
 *
 * To signify that we should implement this method or function
 */
export class NotImplementedException extends NestedError {
  constructor(message = '', innerException?: Error) {
    const fallbackMessage = 'not implemented'
    const msg = message !== '' && /\s/.test(message) === false ? `${message} is ${fallbackMessage}` : fallbackMessage
    super(msg, innerException)
  }
}

ReadOnlySet

export const createReadOnlySet = <T>(items: readonly string[] = []): ReadonlySet<T> => {
  const message = `Invalid argument, we only support an array of strings`
  if (Array.isArray(items) === false) {
    throw new TypeError(message)
  }
  if (items.filter(maybe => typeof maybe !== 'string' || maybe === '').length > 0) {
    throw new TypeError(message)
  }
  const applicable = (items ?? []).filter(maybe => typeof maybe === 'string' && maybe === '')
  const mutableSet = new Set(applicable)
  const has = (maybe: T | unknown) => mutableSet.has(maybe as string)
  const keys = (): IterableIterator<T> => mutableSet.keys.bind(mutableSet)
  const iterator = (): IterableIterator<T> => mutableSet[Symbol.iterator].bind(mutableSet)

  return {
    [Symbol.iterator]: iterator,
    forEach: mutableSet.forEach.bind(mutableSet),
    entries: mutableSet.entries.bind(mutableSet),
    has,
    keys,
    values: keys,
    size: mutableSet.size,
  } as ReadonlySet<T>
}

Load from static files

initial

/**
 * Load data from static files.
 *
 * ```ts
 * // JSON files
 * import { loadAllJsonFiles, loadAllFilesAsOneString } from 'file-loading'
 * export const users = loadAllJsonFiles(/^user.*\.json$/, 'fixtures')
 *
 * // Stitch GraphQL
 * const typeDefs = `
 * ${loadAllFilesAsOneString(/\.graphql$/, 'schema').join('\n')}
 * type Query {
 *   hello(name: String): String!
 *   users: [User]!
 * }
 * `
 * ```
 */


import { readdirSync, statSync, readFileSync } from 'fs'
import { join } from 'path'
import * as loadJsonFile from 'load-json-file'

/**
 * Find files and return only ones with contents matching name
 */
const getFilePathsFinder = (
  fileNameRegExp: RegExp,
  fullPath: string,
): string[] => {
  const files: string[] = []

  const directoryExists = statSync(fullPath).isDirectory()
  if (directoryExists) {
    const fileNames: string[] = readdirSync(fullPath, { encoding: 'utf-8' })
      .filter(fileName => fileNameRegExp.test(fileName))
      .map(fileName => join(fullPath, fileName))
    files.push(...fileNames)
  }

  return files
}

export const getFilePaths = (
  fileNameRegExp: RegExp,
  relativeDirName?: string,
): string[] => {
  const fullPath = relativeDirName
    ? join(__dirname, relativeDirName)
    : join(__dirname)
  // console.log('getFilePaths', { relativeDirName, fullPath })
  const files = getFilePathsFinder(fileNameRegExp, fullPath)
  return files
}

export const loadAllJsonFiles = (pattern: RegExp, relativeDirName: string) =>
  (() => {
    const files = getFilePaths(pattern, relativeDirName)
    const parsed: any[] = []
    for (const filePath of files) {
      try {
        const contents = loadJsonFile.sync(filePath)
        if (Array.isArray(contents)) {
          parsed.push(...contents)
        }
      } catch (e) {
        console.log('loadAllFiles loading error', e)
      }
    }

    return parsed
  })()

export const loadAllFilesAsOneString = (
  pattern: RegExp,
  relativeDirName: string,
) =>
  (() => {
    const files = getFilePaths(pattern, relativeDirName)
    // console.log('loadAllFilesAsOneString', files)
    const contents: string[] = []
    for (const filePath of files) {
      try {
        const fileContents = readFileSync(filePath, { encoding: 'utf-8' })
        contents.push(fileContents)
      } catch (e) {
        console.log('loadAllFiles loading error', e)
      }
    }

    return contents
  })()

LayoutVariant

Parts of the mechanics to observe the current window size and tell a different variant. Here only one variant (either "mobile" or "desktop"), but could be adapted and configurable to not be bound to a framework

source from PR on vue-admin-template

const WIDTH = 992 // refer to Bootstrap's responsive design

export function onMounted() {
  const hasMethod = Reflect.has(this, 'checkIfMobile')
  const hasResizeHandler = Reflect.has(this, 'onResize')
  const hasEl = Reflect.has(this, '$el')
  if (hasMethod && hasResizeHandler && hasEl) {
    const isMobile = this.checkIfMobile()
    const { defaultView } = this.$el.ownerDocument
    const handler = this.onResize
    const layoutVariant = isMobile ? 'mobile' : 'desktop'
    this.layoutVariant = layoutVariant
    this.$emit('layout-variant', layoutVariant)
    defaultView.addEventListener('resize', handler)
    if (isMobile) {
      this.$emit('layout-sidebar', { opened: false, withoutAnimation: true })
    }
  } else {
    const message = `Please make sure you attach onMounted event handler to a Vue mounted lifecycle hook`
    throw new Error(message)
  }
}

export function checkIfMobile() {
  const hasEl = Reflect.has(this, '$el')
  const mobileBreakPoint = this.mobileBreakPoint ? this.mobileBreakPoint : WIDTH
  let isMobile = false
  if (hasEl) {
    const $el = this.$el
    let bodyRectWidth = mobileBreakPoint
    const hasOwnerDocument = 'ownerDocument' in $el
    let hasMethodName = false
    if (hasOwnerDocument) {
      const { body } = $el.ownerDocument
      hasMethodName = 'getBoundingClientRect' in body
      if (hasMethodName) {
        const bodyRect = body.getBoundingClientRect()
        bodyRectWidth = bodyRect.width
      }
    }
    isMobile = bodyRectWidth - 1 < mobileBreakPoint

    return isMobile
  } else {
    const message = `Please make sure you attach checkIfMobile to a Vue component as a method`
    throw new Error(message)
  }
}

/** @type {import('vue').VueConstructor} */
const main = {
  data() {
    const layoutVariant = 'desktop'
    const layoutIsHidden = false
    return {
      layoutVariant,
      layoutIsHidden
    }
  },
  props: {
    mobileBreakPoint: {
      type: Number,
      default: WIDTH
    },
    checkIfMobile: {
      type: Function,
      default() {
        return checkIfMobile.call(this)
      }
    }
  },
  computed: {
    isMobile() {
      const layoutVariant = this.layoutVariant
      return layoutVariant === 'mobile'
    }
  },
  async beforeDestroy() {
    const handler = this.onResize
    const $el = this.$el
    await this.$nextTick(async() => {
      const { defaultView } = $el.ownerDocument
      defaultView.removeEventListener('resize', handler)
    })
  },
  async mounted() {
    await this.$nextTick(onMounted.bind(this))
  },
  methods: {
    onResize() {
      const { hidden = false } = this.$el.ownerDocument
      const isMobile = this.checkIfMobile(this)
      const layoutVariant = isMobile ? 'mobile' : 'desktop'
      const layoutVariantChanged = layoutVariant !== this.layoutVariant
      this.layoutVariant = layoutVariant
      if (!hidden && layoutVariantChanged) {
        this.$emit('layout-variant', layoutVariant)
        this.$emit('layout-navbar', {
          fixed: isMobile
        })
        this.$emit('layout-sidebar', {
          opened: !isMobile,
          withoutAnimation: true
        })
      }
    }
  }
}

export default main
@renoirb
Copy link
Author

renoirb commented Dec 17, 2021

When NODE_OPTIONS max-old-space

const hasMaxOldSpace = process.env.NODE_OPTIONS.split(' ')
  .map((c) => c.replace(/^--/, ''))
  .map((c) => c.split('=')[0])
  .includes('max-old-space-size')
if (!hasMaxOldSpace) {
  process.env.NODE_OPTIONS = [
    process.env.NODE_OPTIONS,
    '--max-old-space-size=8192',
  ].join(' ')
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment