{"version":3,"file":"mockBrowserEnvironment.cjs","sources":["../../src/_internal/cli/server/getStudioEnvironmentVariables.ts","../../src/_internal/cli/util/importErrorHandler.ts","../../src/_internal/cli/util/mockBrowserEnvironment.ts"],"sourcesContent":["import {loadEnv} from '@sanity/cli'\n\nconst envPrefix = 'SANITY_STUDIO_'\nconst appEnvPrefix = 'SANITY_APP_'\n\n/**\n * The params for the `getStudioEnvironmentVariables` function that gets Studio focused environment variables.\n *\n * @public\n */\nexport interface StudioEnvVariablesOptions {\n  /**\n   * When specified adds a prefix to the environment variable keys,\n   * eg: `getStudioEnvironmentVariables({prefix: 'process.env.'})`\n   */\n  prefix?: string\n  /**\n   * When specified includes environment variables from dotenv files (`.env`), in the same way the studio does.\n   * A `mode` must be specified, usually `development`\n   * or `production`, which will load the corresponding `.env.development` or `.env.production`.\n   * To specify where to look for the dotenv files, specify `options.envFile.envDir`.\n   */\n  envFile?: {mode: string; envDir?: string} | false\n  /**\n   * When specified, JSON-encodes the values, which is handy if you want to pass\n   * this to a bundlers hardcoded defines, such as Vite's `define` or Webpack's `DefinePlugin`.\n   */\n  jsonEncode?: boolean\n}\n\n/**\n * Get environment variables prefixed with SANITY_STUDIO_, as an object.\n *\n * @param options - Options for the environment variable loading\n *  {@link StudioEnvVariablesOptions}\n * @returns Object of studio environment variables\n *\n * @example\n * ```tsx\n * getStudioEnvironmentVariables({prefix: 'process.env.', jsonEncode: true})\n * ```\n *\n * @public\n */\nexport function getStudioEnvironmentVariables(\n  options: StudioEnvVariablesOptions = {},\n): Record<string, string> {\n  const {prefix = '', envFile = false, jsonEncode = false} = options\n  const fullEnv = envFile\n    ? {...process.env, ...loadEnv(envFile.mode, envFile.envDir || process.cwd(), [envPrefix])}\n    : process.env\n\n  const studioEnv: Record<string, string> = {}\n  for (const key in fullEnv) {\n    if (key.startsWith(envPrefix)) {\n      studioEnv[`${prefix}${key}`] = jsonEncode\n        ? JSON.stringify(fullEnv[key] || '')\n        : fullEnv[key] || ''\n    }\n  }\n  return studioEnv\n}\n\n/**\n * Get environment variables prefixed with SANITY_APP_, as an object.\n *\n * @param options - Options for the environment variable loading\n *  {@link StudioEnvVariablesOptions}\n * @returns Object of app environment variables\n *\n * @internal\n */\nexport function getAppEnvironmentVariables(\n  options: StudioEnvVariablesOptions = {},\n): Record<string, string> {\n  const {prefix = '', envFile = false, jsonEncode = false} = options\n  const fullEnv = envFile\n    ? {...process.env, ...loadEnv(envFile.mode, envFile.envDir || process.cwd(), [envPrefix])}\n    : process.env\n\n  const appEnv: Record<string, string> = {}\n  for (const key in fullEnv) {\n    if (key.startsWith(appEnvPrefix)) {\n      appEnv[`${prefix}${key}`] = jsonEncode\n        ? JSON.stringify(fullEnv[key] || '')\n        : fullEnv[key] || ''\n    }\n  }\n  return appEnv\n}\n","import Module from 'node:module'\n\nexport interface ImportErrorHandlerResult {\n  cleanup: () => void\n}\n\n// Module._load is an internal Node.js API not exposed in types\ninterface ModuleConstructor {\n  _load(request: string, parent: Module | undefined, isMain: boolean): any\n}\n\n/**\n * Return safe empty module with Proxy for deep property access. This ensures any property\n * access or function call returns a safe value\n */\nfunction getProxyHandler() {\n  const handler: ProxyHandler<object> = {\n    get: (_target, prop) => {\n      if (prop === '__esModule') return true\n      if (prop === 'default') return new Proxy({}, handler)\n      return new Proxy({}, handler)\n    },\n    apply: () => new Proxy({}, handler),\n  }\n  return new Proxy({}, handler)\n}\n\n/**\n * Sets up a Module._load wrapper to silently ignore imports from https://themer.sanity.build\n * This allows users to use themer URL imports in their config without breaking CLI commands.\n *\n * @returns Handler result with cleanup function\n * @internal\n */\nexport function setupImportErrorHandler(): ImportErrorHandlerResult {\n  // Store original Module._load\n  const ModuleConstructor = Module as unknown as ModuleConstructor\n  const originalLoad = ModuleConstructor._load\n\n  // Override Module._load to catch and handle themer.sanity.build imports\n  ModuleConstructor._load = function (\n    request: string,\n    parent: Module | undefined,\n    isMain: boolean,\n  ) {\n    try {\n      return originalLoad.call(this, request, parent, isMain)\n    } catch (error) {\n      // Check if this is a themer.sanity.build URL import\n      if (request.startsWith('https://themer.sanity.build/api/')) {\n        // Return a safe proxy object that can be used in place of the theme\n        return getProxyHandler()\n      }\n\n      // Re-throw all other errors\n      throw error\n    }\n  }\n\n  return {\n    cleanup: () => {\n      ModuleConstructor._load = originalLoad\n    },\n  }\n}\n","/* eslint-disable import/extensions */\nimport {createRequire, register} from 'node:module'\nimport {pathToFileURL} from 'node:url'\n\nimport {ResizeObserver} from '@juggle/resize-observer'\nimport {register as registerESBuild} from 'esbuild-register/dist/node'\nimport jsdomGlobal from 'jsdom-global'\nimport {addHook} from 'pirates'\nimport resolveFrom from 'resolve-from'\n\nimport {getStudioEnvironmentVariables} from '../server/getStudioEnvironmentVariables.ts'\nimport {setupImportErrorHandler} from './importErrorHandler.ts'\n\nconst require = createRequire(import.meta.url)\n\n// Handle require(esm) cases that breaks free from esbuild-register+pirates\nregister(\n  './mock-browser-env-stub-loader.mjs',\n  pathToFileURL(require.resolve('sanity/package.json')),\n)\n\nconst jsdomDefaultHtml = `<!doctype html>\n<html>\n  <head><meta charset=\"utf-8\"></head>\n  <body></body>\n</html>`\n\nexport function mockBrowserEnvironment(basePath: string): () => void {\n  // Guard against double-registering\n  if (global && global.window && '__mockedBySanity' in global.window) {\n    return () => {\n      /* intentional noop */\n    }\n  }\n\n  // Set up import error handler before esbuild-register to silently ignore themer.sanity.build URLs\n  const importErrorHandler = setupImportErrorHandler()\n\n  const btoa = global.btoa\n  const domCleanup = jsdomGlobal(jsdomDefaultHtml, {url: 'http://localhost:3333/'})\n\n  // Don't use jsdom's btoa as it's using the deprecatd `abab` package.\n  if (typeof btoa === 'function') global.btoa = btoa\n\n  const windowCleanup = () => global.window.close()\n  const globalCleanup = provideFakeGlobals(basePath)\n  const cleanupFileLoader = addHook(\n    (code, filename) => `module.exports = ${JSON.stringify(filename)}`,\n    {\n      ignoreNodeModules: false,\n      exts: getFileExtensions(),\n    },\n  )\n\n  const {unregister: unregisterESBuild} = registerESBuild({\n    target: 'node18',\n    supported: {'dynamic-import': true},\n    format: 'cjs',\n    extensions: ['.js', '.jsx', '.ts', '.tsx', '.mjs'],\n    jsx: 'automatic',\n    define: {\n      // define the `process.env` global\n      ...getStudioEnvironmentVariables({prefix: 'process.env.', jsonEncode: true}),\n      // define the `import.meta.env` global\n      ...getStudioEnvironmentVariables({prefix: 'import.meta.env.', jsonEncode: true}),\n      // define the `import.meta.hot` global, so we don't get `\"import.meta\" is not available with the \"cjs\" output format and will be empty` warnings\n      'import.meta.hot': 'false',\n    },\n  })\n\n  return function cleanupBrowserEnvironment() {\n    unregisterESBuild()\n    cleanupFileLoader()\n    globalCleanup()\n    windowCleanup()\n    domCleanup()\n    importErrorHandler.cleanup()\n  }\n}\n\nconst getFakeGlobals = (basePath: string) => ({\n  __mockedBySanity: true,\n  requestAnimationFrame: setImmediate,\n  cancelAnimationFrame: clearImmediate,\n  requestIdleCallback: setImmediate,\n  cancelIdleCallback: clearImmediate,\n  ace: tryGetAceGlobal(basePath),\n  InputEvent: global.window?.InputEvent,\n  customElements: global.window?.customElements,\n  ResizeObserver: global.window?.ResizeObserver || ResizeObserver,\n  matchMedia:\n    global.window?.matchMedia ||\n    (() => ({\n      matches: false,\n      media: '',\n      onchange: null,\n    })),\n})\n\nconst getFakeDocumentProps = () => ({\n  execCommand: function execCommand(\n    // Provide the right arity for the function, even if unused\n    _commandName: string,\n    _showDefaultUI: boolean,\n    _valueArgument: unknown,\n  ) {\n    // Return false to indicate \"unsupported\"\n    return false\n  },\n})\n\nfunction provideFakeGlobals(basePath: string): () => void {\n  const globalEnv = global as any as Record<string, unknown>\n  const globalWindow = global.window as Record<string, any>\n  const globalDocument = (global.document || document || {}) as Record<string, any>\n\n  const fakeGlobals = getFakeGlobals(basePath)\n  const fakeDocumentProps = getFakeDocumentProps()\n\n  const stubbedGlobalKeys: string[] = []\n  const stubbedWindowKeys: string[] = []\n  const stubbedDocumentKeys: string[] = []\n\n  for (const [rawKey, value] of Object.entries(fakeGlobals)) {\n    if (typeof value === 'undefined') {\n      continue\n    }\n\n    const key = rawKey as keyof typeof fakeGlobals\n\n    if (!(key in globalEnv)) {\n      globalEnv[key] = fakeGlobals[key]\n      stubbedGlobalKeys.push(key)\n    }\n\n    if (!(key in global.window)) {\n      globalWindow[key] = fakeGlobals[key]\n      stubbedWindowKeys.push(key)\n    }\n  }\n\n  for (const [rawKey, value] of Object.entries(fakeDocumentProps)) {\n    if (typeof value === 'undefined') {\n      continue\n    }\n\n    const key = rawKey as keyof typeof fakeDocumentProps\n    if (!(key in globalDocument)) {\n      globalDocument[key] = fakeDocumentProps[key]\n      stubbedDocumentKeys.push(key)\n    }\n  }\n\n  return () => {\n    stubbedGlobalKeys.forEach((key) => {\n      delete globalEnv[key]\n    })\n\n    stubbedWindowKeys.forEach((key) => {\n      delete globalWindow[key]\n    })\n\n    stubbedDocumentKeys.forEach((key) => {\n      delete globalDocument[key]\n    })\n  }\n}\n\nfunction tryGetAceGlobal(basePath: string) {\n  // Work around an issue where using the @sanity/code-input plugin would crash\n  // due to `ace` not being defined on the global due to odd bundling stategy.\n  const acePath = resolveFrom.silent(basePath, 'ace-builds')\n  if (!acePath) {\n    return undefined\n  }\n\n  try {\n    // eslint-disable-next-line import/no-dynamic-require\n    return require(acePath)\n  } catch {\n    return undefined\n  }\n}\n\nfunction getFileExtensions() {\n  return [\n    '.css',\n    '.eot',\n    '.gif',\n    '.jpeg',\n    '.jpg',\n    '.otf',\n    '.png',\n    '.sass',\n    '.scss',\n    '.svg',\n    '.ttf',\n    '.webp',\n    '.woff',\n    '.woff2',\n  ]\n}\n"],"names":["envPrefix","getStudioEnvironmentVariables","options","prefix","envFile","jsonEncode","fullEnv","process","env","loadEnv","mode","envDir","cwd","studioEnv","key","startsWith","JSON","stringify","getProxyHandler","handler","get","_target","prop","Proxy","apply","setupImportErrorHandler","ModuleConstructor","Module","originalLoad","_load","request","parent","isMain","call","error","cleanup","require","createRequire","register","pathToFileURL","resolve","jsdomDefaultHtml","mockBrowserEnvironment","basePath","global","window","importErrorHandler","btoa","domCleanup","jsdomGlobal","url","windowCleanup","close","globalCleanup","provideFakeGlobals","cleanupFileLoader","addHook","code","filename","ignoreNodeModules","exts","getFileExtensions","unregister","unregisterESBuild","registerESBuild","target","supported","format","extensions","jsx","define","getFakeGlobals","__mockedBySanity","requestAnimationFrame","setImmediate","cancelAnimationFrame","clearImmediate","requestIdleCallback","cancelIdleCallback","ace","tryGetAceGlobal","InputEvent","customElements","ResizeObserver","matchMedia","matches","media","onchange","getFakeDocumentProps","execCommand","_commandName","_showDefaultUI","_valueArgument","globalEnv","globalWindow","globalDocument","document","fakeGlobals","fakeDocumentProps","stubbedGlobalKeys","stubbedWindowKeys","stubbedDocumentKeys","rawKey","value","Object","entries","push","forEach","acePath","resolveFrom","silent"],"mappings":"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"}