UNPKG

sanity

Version:

Sanity is a real-time content infrastructure with a scalable, hosted backend featuring a Graph Oriented Query Language (GROQ), asset pipelines and fast edge caches

1 lines • 15.8 kB
{"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","import {createRequire} from 'node:module'\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'\nimport {setupImportErrorHandler} from './importErrorHandler'\n\nconst require = createRequire(import.meta.url)\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 },\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 (err) {\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","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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"}