starling-devex 0.1.2

Starling: a local dev orchestrator with a central daemon, shared named-URL proxy, and a k9s-style TUI (a Rust port of Tilt + portless)
import React, { useContext } from "react"

// A little helper class for building paths relative to the root of the app.
class PathBuilder {
  private protocol: string
  private host: string
  private snapId: string = ""

  static forTesting(host: string, pathname: string) {
    return new PathBuilder({
      protocol: "http:",
      host: host,
      pathname: pathname,
    })
  }

  constructor(loc: { protocol: string; host: string; pathname: string }) {
    this.host = loc.host
    this.protocol = loc.protocol

    const snapshotRe = new RegExp("^/snapshot/([^/]+)")
    let snapMatch = snapshotRe.exec(loc.pathname)
    if (snapMatch) {
      this.snapId = snapMatch[1]
    }
  }

  getDataUrl() {
    if (this.isSnapshot()) {
      return this.snapshotDataUrl()
    }
    return this.isSecure()
      ? `wss://${this.host}/ws/view`
      : `ws://${this.host}/ws/view`
  }

  isSecure(): boolean {
    return this.protocol === "https:"
  }

  isSnapshot(): boolean {
    return this.snapId !== ""
  }

  private snapshotDataUrl(): string {
    return `/api/snapshot/${this.snapId}`
  }

  private snapshotPathBase(): string {
    return `/snapshot/${this.snapId}`
  }

  rootPath() {
    if (this.isSnapshot()) {
      return this.snapshotPathBase()
    }
    return ""
  }

  path(relPath: string): string {
    if (relPath[0] !== "/") {
      throw new Error('relPath should start with "/", actual:' + relPath)
    }
    return this.rootPath() + relPath
  }

  // A template literal function for encoding paths.
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
  encpath(strings: TemplateStringsArray, ...values: string[]): string {
    let result = [strings[0]]
    for (let i = 0; i < values.length; i++) {
      result.push(encodeURIComponent(values[i]), strings[i + 1])
    }
    return this.path(result.join(""))
  }
}

export default PathBuilder

const pathBuilderContext = React.createContext<PathBuilder>(
  new PathBuilder(window.location)
)

export function usePathBuilder(): PathBuilder {
  return useContext(pathBuilderContext)
}
export const PathBuilderProvider = pathBuilderContext.Provider