@oazmi/kitchensink - v0.9.13
    Preparing search index...

    Function parsePackageUrl

    • this function parses npm and jsr package strings, and returns a pseudo URL-like object.

      the regex we use for parsing the input href string is quoted below:

      /^(?jsr:|npm:|node:)(/(@(?[^/\s]+)/)?(?[^@/\s]+)(@(?[^/\r\n\t\f\v]+))?)?(?/.)?$/

      see the regex in action with the test cases on regex101 link: regex101.com/r/mX3v1z/2

      Parameters

      • url_href: string | URL

      Returns PackagePseudoUrl

      Error an error will be thrown if either the package name (pkg), or the protocol cannot be deduced by the regex.

      import { assertEquals, assertThrows } from "jsr:@std/assert"

      // aliasing our functions for brevity
      const eq = assertEquals, err = assertThrows, fn = parsePackageUrl

      // basic breakdown of a package's resource uri
      eq(fn("jsr:@scope/package@version/pathname/file.ts"), {
      href: "jsr:/@scope/package@version/pathname/file.ts",
      protocol: "jsr:",
      scope: "scope",
      pkg: "package",
      version: "version",
      pathname: "/pathname/file.ts",
      host: "@scope/package@version",
      })

      // showing that jsr package uri's without a scope are perfectly permitted.
      // even though it isn't actually possible to do so on "jsr.io".
      // thus it is left up to the end-user to make of it what they will.
      eq(fn("jsr:package@version/pathname/"), {
      href: "jsr:/package@version/pathname/",
      protocol: "jsr:",
      scope: undefined,
      pkg: "package",
      version: "version",
      pathname: "/pathname/",
      host: "package@version",
      })

      // testing a case with multiple slashes ("/") after the protocol colon (":"), and no trailing slash after the version
      eq(fn("npm:///@scope/package@version"), {
      href: "npm:/@scope/package@version/",
      protocol: "npm:",
      scope: "scope",
      pkg: "package",
      version: "version",
      pathname: "/",
      host: "@scope/package@version",
      })

      // testing a no-scope and no-version case
      eq(fn("npm:package"), {
      href: "npm:/package/",
      protocol: "npm:",
      scope: undefined,
      pkg: "package",
      version: undefined,
      pathname: "/",
      host: "package",
      })

      // testing the "node:" protocol
      eq(fn("node:fs"), {
      href: "node:/fs/",
      protocol: "node:",
      scope: undefined,
      pkg: "fs",
      version: undefined,
      pathname: "/",
      host: "fs",
      })

      // testing the "node:" protocol with a certain pathname
      eq(fn("node:fs/promises"), {
      href: "node:/fs/promises",
      protocol: "node:",
      scope: undefined,
      pkg: "fs",
      version: undefined,
      pathname: "/promises",
      host: "fs",
      })

      // testing a `version` query string that contains whitespaces and url-encoded characters.
      // NOTE: the url-encoded characters in vs-code's doc popup appear decoded, so don't be fooled!
      // but the `host` is always a url-decoded string.
      eq(fn("jsr:@scope/package@1.0.0 - 1.2.0/pathname/file.ts"), {
      href: "jsr:/@scope/package@1.0.0%20-%201.2.0/pathname/file.ts",
      protocol: "jsr:",
      scope: "scope",
      pkg: "package",
      version: "1.0.0 - 1.2.0",
      pathname: "/pathname/file.ts",
      host: "@scope/package@1.0.0 - 1.2.0",
      })

      // testing a `version` query string that has its some of its characters (such as whitespaces) url-encoded.
      // NOTE: the url-encoded characters in vs-code's doc popup appear decoded, so don't be fooled!
      // but the `host` is always a url-decoded string.
      eq(fn("jsr:@scope/package@^2%20<2.2%20||%20>%202.3/pathname/file.ts"), {
      href: "jsr:/@scope/package@%5E2%20%3C2.2%20%7C%7C%20%3E%202.3/pathname/file.ts",
      protocol: "jsr:",
      scope: "scope",
      pkg: "package",
      version: "^2 <2.2 || > 2.3",
      pathname: "/pathname/file.ts",
      host: "@scope/package@^2 <2.2 || > 2.3",
      })

      // testing cases where an error should be invoked
      err(() => fn("npm:@scope/")) // missing a package name
      err(() => fn("npm:@scope//package")) // more than one slash after scope
      err(() => fn("pnpm:@scope/package@version")) // only "node:", "npm:", and "jsr:" protocols are recognized