{"version":3,"file":"npm.mjs","sourceRoot":"","sources":["../../../src/snaps/location/npm.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SnapManifest } from '@metamask/snaps-utils';\nimport {\n  createSnapManifest,\n  DEFAULT_REQUESTED_SNAP_VERSION,\n  getTargetVersion,\n  isValidUrl,\n  NpmSnapIdStruct,\n  VirtualFile,\n  normalizeRelative,\n  parseJson,\n} from '@metamask/snaps-utils';\nimport type { SemVerRange, SemVerVersion } from '@metamask/utils';\nimport {\n  assert,\n  assertIsSemVerVersion,\n  assertStruct,\n  isObject,\n  isValidSemVerVersion,\n} from '@metamask/utils';\nimport concat from 'concat-stream';\nimport getNpmTarballUrl from 'get-npm-tarball-url';\nimport { pipeline } from 'readable-stream';\nimport type { Readable, Writable } from 'readable-stream';\nimport { ReadableWebToNodeStream } from 'readable-web-to-node-stream';\nimport { extract as tarExtract } from 'tar-stream';\n\nimport type { DetectSnapLocationOptions, SnapLocation } from './location';\n\nexport const DEFAULT_NPM_REGISTRY = new URL('https://registry.npmjs.org');\n\nexport const NPM_REGISTRY_PROXY = new URL('https://npm-ota.api.cx.metamask.io');\n\ntype NpmMeta = {\n  registry: URL;\n  packageName: string;\n  requestedRange: SemVerRange;\n  version?: string;\n  fetch: typeof fetch;\n  resolveVersion: (range: SemVerRange) => Promise<SemVerRange>;\n};\n\nexport type NpmOptions = {\n  /**\n   * @default DEFAULT_REQUESTED_SNAP_VERSION\n   */\n  versionRange?: SemVerRange;\n  /**\n   * Whether to allow custom NPM registries outside of {@link DEFAULT_NPM_REGISTRY}.\n   *\n   * @default false\n   */\n  allowCustomRegistries?: boolean;\n  /**\n   * Whether to use a MetaMask-owned proxy when sending requests to NPM.\n   *\n   * @default false\n   */\n  useNpmProxy?: boolean;\n};\n\n// Base class for NPM implementation, useful for extending with custom NPM fetching logic\nexport abstract class BaseNpmLocation implements SnapLocation {\n  protected readonly meta: NpmMeta;\n\n  #validatedManifest?: VirtualFile<SnapManifest>;\n\n  #files?: Map<string, VirtualFile>;\n\n  constructor(url: URL, opts: DetectSnapLocationOptions = {}) {\n    const allowCustomRegistries = opts.allowCustomRegistries ?? false;\n    const fetchFunction = opts.fetch ?? globalThis.fetch.bind(undefined);\n    const requestedRange = opts.versionRange ?? DEFAULT_REQUESTED_SNAP_VERSION;\n    const defaultResolve = async (range: SemVerRange) => range;\n    const resolveVersion = opts.resolveVersion ?? defaultResolve;\n\n    assertStruct(url.toString(), NpmSnapIdStruct, 'Invalid Snap Id: ');\n\n    let registry: string | URL;\n    if (\n      url.host === '' &&\n      url.port === '' &&\n      url.username === '' &&\n      url.password === ''\n    ) {\n      registry = opts.useNpmProxy ? NPM_REGISTRY_PROXY : DEFAULT_NPM_REGISTRY;\n    } else {\n      registry = 'https://';\n      if (url.username) {\n        registry += url.username;\n        if (url.password) {\n          registry += `:${url.password}`;\n        }\n        registry += '@';\n      }\n      registry += url.host;\n      registry = new URL(registry);\n      assert(\n        allowCustomRegistries,\n        new TypeError(\n          `Custom NPM registries are disabled, tried to use \"${registry.toString()}\".`,\n        ),\n      );\n    }\n\n    assert(\n      registry.pathname === '/' &&\n        registry.search === '' &&\n        registry.hash === '',\n    );\n\n    assert(\n      url.pathname !== '' && url.pathname !== '/',\n      new TypeError('The package name in NPM location is empty.'),\n    );\n    let packageName = url.pathname;\n    if (packageName.startsWith('/')) {\n      packageName = packageName.slice(1);\n    }\n\n    this.meta = {\n      requestedRange,\n      registry,\n      packageName,\n      fetch: fetchFunction,\n      resolveVersion,\n    };\n  }\n\n  async manifest(): Promise<VirtualFile<SnapManifest>> {\n    if (this.#validatedManifest) {\n      return this.#validatedManifest.clone();\n    }\n\n    const vfile = await this.fetch('snap.manifest.json');\n    const result = parseJson(vfile.toString());\n    vfile.result = createSnapManifest(result);\n    this.#validatedManifest = vfile as VirtualFile<SnapManifest>;\n\n    return this.manifest();\n  }\n\n  async fetch(path: string): Promise<VirtualFile> {\n    const relativePath = normalizeRelative(path);\n    if (!this.#files) {\n      await this.#lazyInit();\n      assert(this.#files !== undefined);\n    }\n    const vfile = this.#files.get(relativePath);\n    assert(\n      vfile !== undefined,\n      new TypeError(`File \"${path}\" not found in package.`),\n    );\n    return vfile.clone();\n  }\n\n  get packageName(): string {\n    return this.meta.packageName;\n  }\n\n  get version(): string {\n    assert(\n      this.meta.version !== undefined,\n      'Tried to access version without first fetching NPM package.',\n    );\n    return this.meta.version;\n  }\n\n  get registry(): URL {\n    return this.meta.registry;\n  }\n\n  get versionRange(): SemVerRange {\n    return this.meta.requestedRange;\n  }\n\n  async #lazyInit() {\n    assert(this.#files === undefined);\n    const resolvedVersion = await this.meta.resolveVersion(\n      this.meta.requestedRange,\n    );\n\n    const { tarballURL, targetVersion } = await resolveNpmVersion(\n      this.meta.packageName,\n      resolvedVersion,\n      this.meta.registry,\n      this.meta.fetch,\n    );\n\n    if (!isValidUrl(tarballURL) || !tarballURL.toString().endsWith('.tgz')) {\n      throw new Error(\n        `Failed to find valid tarball URL in NPM metadata for package \"${this.meta.packageName}\".`,\n      );\n    }\n\n    // Override the tarball hostname/protocol with registryUrl hostname/protocol\n    const newTarballUrl = new URL(tarballURL);\n    newTarballUrl.hostname = this.meta.registry.hostname;\n    newTarballUrl.protocol = this.meta.registry.protocol;\n\n    const files = await this.fetchNpmTarball(newTarballUrl);\n\n    this.#files = files;\n    this.meta.version = targetVersion;\n  }\n\n  /**\n   * Fetches and unpacks the tarball (`.tgz` file) from the specified URL.\n   *\n   * @param tarballUrl - The tarball URL to fetch and unpack.\n   * @returns A the files for the package tarball.\n   * @throws If fetching the tarball fails.\n   */\n  abstract fetchNpmTarball(tarballUrl: URL): Promise<Map<string, VirtualFile>>;\n}\n\n// Safety limit for tarballs, 250 MB in bytes\nexport const TARBALL_SIZE_SAFETY_LIMIT = 262144000;\n\n// Main NPM implementation, contains a browser tarball fetching implementation.\nexport class NpmLocation extends BaseNpmLocation {\n  /**\n   * Fetches and unpacks the tarball (`.tgz` file) from the specified URL.\n   *\n   * @param tarballUrl - The tarball URL to fetch and unpack.\n   * @returns A the files for the package tarball.\n   * @throws If fetching the tarball fails.\n   */\n  async fetchNpmTarball(tarballUrl: URL): Promise<Map<string, VirtualFile>> {\n    // Perform a raw fetch because we want the Response object itself.\n    const tarballResponse = await this.meta.fetch(tarballUrl.toString());\n\n    assert(\n      tarballResponse.status !== 404,\n      `\"${this.meta.packageName}\" was not found in the NPM registry`,\n    );\n    assert(\n      tarballResponse.ok && tarballResponse.body,\n      `Failed to fetch tarball for package \"${this.meta.packageName}\"`,\n    );\n\n    // We assume that NPM is a good actor and provides us with a valid `content-length` header.\n    const tarballSizeString = tarballResponse.headers.get('content-length');\n    assert(tarballSizeString, 'Snap tarball has invalid content-length');\n    const tarballSize = parseInt(tarballSizeString, 10);\n    assert(\n      tarballSize <= TARBALL_SIZE_SAFETY_LIMIT,\n      'Snap tarball exceeds size limit',\n    );\n\n    return new Promise((resolve, reject) => {\n      const files = new Map();\n\n      const tarballStream = createTarballStream(\n        getNpmCanonicalBasePath(this.meta.registry, this.meta.packageName),\n        files,\n      );\n\n      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n      const body = tarballResponse.body!;\n\n      // The \"gz\" in \"tgz\" stands for \"gzip\". The tarball needs to be decompressed\n      // before we can actually grab any files from it.\n      // To prevent recursion-based zip bombs, we should not allow recursion here.\n      const decompressionStream = new DecompressionStream('gzip');\n      const decompressedStream = body.pipeThrough(decompressionStream);\n\n      pipeline(\n        getNodeStream(decompressedStream),\n        tarballStream,\n        (error: unknown) => {\n          error ? reject(error) : resolve(files);\n        },\n      );\n    });\n  }\n}\n\n// Incomplete type\nexport type PartialNpmMetadata = {\n  versions: Record<string, { dist: { tarball: string } }>;\n};\n\n/**\n * Fetches the NPM metadata of the specified package from\n * the public npm registry.\n *\n * @param packageName - The name of the package whose metadata to fetch.\n * @param registryUrl - The URL of the npm registry to fetch the metadata from.\n * @param fetchFunction - The fetch function to use. Defaults to the global\n * {@link fetch}. Useful for Node.js compatibility.\n * @returns The NPM metadata object.\n * @throws If fetching the metadata fails.\n */\nexport async function fetchNpmMetadata(\n  packageName: string,\n  registryUrl: URL,\n  fetchFunction: typeof fetch,\n): Promise<PartialNpmMetadata> {\n  const packageResponse = await fetchFunction(\n    new URL(packageName, registryUrl).toString(),\n    {\n      headers: {\n        // Corgi format is slightly smaller: https://github.com/npm/pacote/blob/main/lib/registry.js#L71\n        accept: isNPM(registryUrl)\n          ? 'application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*'\n          : 'application/json',\n      },\n    },\n  );\n  if (!packageResponse.ok) {\n    throw new Error(\n      `Failed to fetch NPM registry entry. Status code: ${packageResponse.status}.`,\n    );\n  }\n  const packageMetadata = await packageResponse.json();\n\n  if (!isObject(packageMetadata)) {\n    throw new Error(\n      `Failed to fetch package \"${packageName}\" metadata from npm.`,\n    );\n  }\n\n  return packageMetadata as PartialNpmMetadata;\n}\n\n/**\n * Gets the canonical base path for an NPM snap.\n *\n * @param registryUrl - A registry URL.\n * @param packageName - A package name.\n * @returns The canonical base path.\n */\nexport function getNpmCanonicalBasePath(registryUrl: URL, packageName: string) {\n  let canonicalBase = 'npm://';\n  if (registryUrl.username !== '') {\n    canonicalBase += registryUrl.username;\n    if (registryUrl.password !== '') {\n      canonicalBase += `:${registryUrl.password}`;\n    }\n    canonicalBase += '@';\n  }\n  return `${canonicalBase}${registryUrl.host}/${packageName}/`;\n}\n\n/**\n * Determine if a registry URL is NPM.\n *\n * @param registryUrl - A registry url.\n * @returns True if the registry is the NPM registry, otherwise false.\n */\nfunction isNPM(registryUrl: URL) {\n  const registryUrlString = registryUrl.toString();\n  return (\n    registryUrlString === DEFAULT_NPM_REGISTRY.toString() ||\n    registryUrlString === NPM_REGISTRY_PROXY.toString()\n  );\n}\n\n/**\n * Resolves a version range to a version using the NPM registry.\n *\n * Unless the version range is already a version, then the NPM registry is skipped.\n *\n * @param packageName - The name of the package whose metadata to fetch.\n * @param versionRange - The version range of the package.\n * @param registryUrl - The URL of the npm registry to fetch the metadata from.\n * @param fetchFunction - The fetch function to use. Defaults to the global\n * {@link fetch}. Useful for Node.js compatibility.\n * @returns An object containing the resolved version and a URL for its tarball.\n * @throws If fetching the metadata fails.\n */\nasync function resolveNpmVersion(\n  packageName: string,\n  versionRange: SemVerRange,\n  registryUrl: URL,\n  fetchFunction: typeof fetch,\n): Promise<{ tarballURL: string; targetVersion: SemVerVersion }> {\n  // If the version range is already a static version we don't need to look for the metadata.\n  if (isNPM(registryUrl) && isValidSemVerVersion(versionRange)) {\n    return {\n      tarballURL: getNpmTarballUrl(packageName, versionRange),\n      targetVersion: versionRange,\n    };\n  }\n\n  const packageMetadata = await fetchNpmMetadata(\n    packageName,\n    registryUrl,\n    fetchFunction,\n  );\n\n  const versions = Object.keys(packageMetadata?.versions ?? {}).map(\n    (version) => {\n      assertIsSemVerVersion(version);\n      return version;\n    },\n  );\n\n  const targetVersion = getTargetVersion(versions, versionRange);\n\n  if (targetVersion === null) {\n    throw new Error(\n      `Failed to find a matching version in npm metadata for package \"${packageName}\" and requested semver range \"${versionRange}\".`,\n    );\n  }\n\n  const tarballURL = packageMetadata?.versions?.[targetVersion]?.dist?.tarball;\n\n  return { tarballURL, targetVersion };\n}\n\n/**\n * The paths of files within npm tarballs appear to always be prefixed with\n * \"package/\".\n */\nconst NPM_TARBALL_PATH_PREFIX = /^package\\//u;\n\n/**\n * Converts a {@link ReadableStream} to a Node.js {@link Readable}\n * stream. Returns the stream directly if it is already a Node.js stream.\n * We can't use the native Web {@link ReadableStream} directly because the\n * other stream libraries we use expect Node.js streams.\n *\n * @param stream - The stream to convert.\n * @returns The given stream as a Node.js Readable stream.\n */\n// eslint-disable-next-line no-restricted-globals\nfunction getNodeStream(stream: ReadableStream): Readable {\n  if (typeof stream.getReader !== 'function') {\n    return stream as unknown as Readable;\n  }\n\n  return new ReadableWebToNodeStream(stream);\n}\n\n/**\n * Creates a `tar-stream` that will get the necessary files from an npm Snap\n * package tarball (`.tgz` file).\n *\n * @param canonicalBase - A base URI as specified in {@link https://github.com/MetaMask/SIPs/blob/main/SIPS/sip-8.md SIP-8}. Starting with 'npm:'. Will be used for canonicalPath vfile argument.\n * @param files - An object to write target file contents to.\n * @returns The {@link Writable} tarball extraction stream.\n */\nfunction createTarballStream(\n  canonicalBase: string,\n  files: Map<string, VirtualFile>,\n): Writable {\n  assert(\n    canonicalBase.endsWith('/'),\n    \"Base needs to end with '/' for relative paths to be added as children instead of siblings.\",\n  );\n\n  assert(\n    canonicalBase.startsWith('npm:'),\n    'Protocol mismatch, expected \"npm:\".',\n  );\n  // `tar-stream` is pretty old-school, so we create it first and then\n  // instrument it by adding event listeners.\n  const extractStream = tarExtract();\n\n  let totalSize = 0;\n\n  // \"entry\" is fired for every discrete entity in the tarball. This includes\n  // files and folders.\n  extractStream.on('entry', (header, entryStream, next) => {\n    const { name: headerName, type: headerType } = header;\n    if (headerType === 'file') {\n      // The name is a path if the header type is \"file\".\n      const path = headerName.replace(NPM_TARBALL_PATH_PREFIX, '');\n      return entryStream.pipe(\n        concat({ encoding: 'uint8array' }, (data) => {\n          try {\n            totalSize += data.byteLength;\n            // To prevent zip bombs, we set a safety limit for the total size of tarballs.\n            assert(\n              totalSize < TARBALL_SIZE_SAFETY_LIMIT,\n              `Snap tarball exceeds limit of ${TARBALL_SIZE_SAFETY_LIMIT} bytes.`,\n            );\n            const vfile = new VirtualFile({\n              value: data,\n              path,\n              data: {\n                canonicalPath: new URL(path, canonicalBase).toString(),\n              },\n            });\n            // We disallow files having identical paths as it may confuse our checksum calculations.\n            assert(\n              !files.has(path),\n              'Malformed tarball, multiple files with the same path.',\n            );\n            files.set(path, vfile);\n            return next();\n          } catch (error) {\n            return extractStream.destroy(error);\n          }\n        }),\n      );\n    }\n\n    // If we get here, the entry is not a file, and we want to ignore. The entry\n    // stream must be drained, or the extractStream will stop reading. This is\n    // effectively a no-op for the current entry.\n    entryStream.on('end', () => next());\n    return entryStream.resume();\n  });\n  return extractStream as Writable;\n}\n"]}