{"version":3,"file":"utils-7WDNT3Ca.cjs","names":["path","builtinModules"],"sources":["../src/build/utils.ts"],"sourcesContent":["import { execSync } from 'node:child_process';\nimport { existsSync, mkdirSync } from 'node:fs';\nimport { builtinModules } from 'node:module';\nimport { basename, join, relative } from 'node:path';\nimport type { RollupNodeResolveOptions } from '@rollup/plugin-node-resolve';\n\n/** The detected JavaScript runtime environment */\nexport type RuntimePlatform = 'node' | 'bun';\n\n/**\n * The esbuild/bundler platform setting.\n * - 'node': Assumes Node.js environment, externalizes built-in modules\n * - 'browser': Assumes browser environment, polyfills Node APIs\n * - 'neutral': Runtime-agnostic, preserves all globals as-is (used for Bun)\n */\nexport type BundlerPlatform = 'node' | 'browser' | 'neutral';\n\n/**\n * Get nodeResolve plugin options based on the target platform.\n *\n * For 'browser' platform (e.g., Cloudflare Workers), uses browser-compatible\n * export conditions so packages like the Cloudflare SDK resolve to their\n * web runtime instead of Node.js-specific code.\n *\n * For 'node' and 'neutral' (Bun) platforms, uses Node.js module resolution.\n */\nexport function getNodeResolveOptions(platform: BundlerPlatform): RollupNodeResolveOptions {\n  if (platform === 'browser') {\n    return {\n      preferBuiltins: false,\n      browser: true,\n      exportConditions: ['browser', 'worker', 'default'],\n    };\n  }\n  return {\n    preferBuiltins: true,\n    exportConditions: ['node'],\n  };\n}\n\n/**\n * Detect the current JavaScript runtime environment.\n *\n * This is used by the bundler to determine the appropriate esbuild platform\n * setting. When running under Bun, we need to use 'neutral' platform to\n * preserve Bun-specific globals (like Bun.s3).\n */\nexport function detectRuntime(): RuntimePlatform {\n  if (process.versions?.bun) {\n    return 'bun';\n  }\n  return 'node';\n}\n\n/**\n * Whether the deployer should skip installing dependencies (and lockfile\n * generation) in the build output directory. Enabled by setting\n * MASTRA_BUILD_SKIP_INSTALL to \"true\" or \"1\". Useful for hermetic build\n * systems (e.g. Bazel) that supply node_modules externally and run in a\n * network-less sandbox where the output install would be redundant and fatal.\n */\nexport function shouldSkipInstall(): boolean {\n  const value = process.env.MASTRA_BUILD_SKIP_INSTALL;\n  return value === 'true' || value === '1';\n}\n\nexport function upsertMastraDir({ dir = process.cwd() }: { dir?: string }) {\n  const dirPath = join(dir, '.mastra');\n\n  if (!existsSync(dirPath)) {\n    mkdirSync(dirPath, { recursive: true });\n    execSync(`echo \".mastra\" >> .gitignore`);\n  }\n}\n\nexport function isDependencyPartOfPackage(dep: string, packageName: string) {\n  if (dep === packageName) {\n    return true;\n  }\n\n  return dep.startsWith(`${packageName}/`);\n}\n\n/**\n * Get the package name from a module ID\n */\nexport function getPackageName(id: string) {\n  const parts = id.split('/');\n\n  if (id.startsWith('@')) {\n    return parts.slice(0, 2).join('/');\n  }\n\n  return parts[0];\n}\n\n/**\n * Check if an import specifier uses a protocol scheme rather than a package name.\n * Examples: `cloudflare:workers`, `data:text/javascript,...`, `node:fs`.\n */\nexport function hasImportProtocol(specifier: string): boolean {\n  // Avoid treating Windows absolute paths like `C:\\foo` as protocol imports.\n  if (/^[A-Za-z]:[\\\\/]/.test(specifier)) {\n    return false;\n  }\n\n  return /^[A-Za-z][A-Za-z\\d+.-]*:/.test(specifier);\n}\n\nconst DEFAULT_PROTOCOL_IMPORT_EXCLUDE_LIST = ['node:'] as const;\n\n/**\n * Check if a specifier uses a non-builtin protocol that should be preserved at\n * runtime instead of being treated as an installable dependency.\n */\nexport function isExternalProtocolImport(\n  specifier: string,\n  excludeList: readonly string[] = DEFAULT_PROTOCOL_IMPORT_EXCLUDE_LIST,\n): boolean {\n  if (!hasImportProtocol(specifier)) {\n    return false;\n  }\n\n  return !excludeList.some(prefix => specifier.startsWith(prefix));\n}\n\nfunction isRelativeImportSpecifier(specifier: string): boolean {\n  return specifier === '.' || specifier === '..' || specifier.startsWith('./') || specifier.startsWith('../');\n}\n\nfunction isAbsolutePathSpecifier(specifier: string): boolean {\n  return specifier.startsWith('/') || specifier.startsWith('\\\\\\\\') || /^[A-Za-z]:[\\\\/]/.test(specifier);\n}\n\n/**\n * During `mastra dev` we are compiling TS files to JS (inside workspaces) so that users can just their workspace packages.\n * We store these compiled files inside `node_modules/.cache` for each workspace package.\n */\nexport function getCompiledDepCachePath(rootPath: string, packageName: string) {\n  return slash(join(rootPath, 'node_modules', '.cache', packageName));\n}\n\n/**\n * Convert windows backslashes to posix slashes\n *\n * @example\n * ```ts\n * slash('C:\\\\Users\\\\user\\\\code\\\\mastra') // 'C:/Users/user/code/mastra'\n * ```\n */\nexport function slash(path: string) {\n  const isExtendedLengthPath = path.startsWith('\\\\\\\\?\\\\');\n\n  if (isExtendedLengthPath) {\n    return path;\n  }\n\n  return path.replaceAll('\\\\', '/');\n}\n\n/**\n * Make a Rollup-safe name: pathless, POSIX, and without parent/absolute segments\n */\nexport function rollupSafeName(name: string, rootDir: string) {\n  const rel = relative(rootDir, name);\n  let entry = slash(rel);\n  entry = entry.replace(/^(\\.\\.\\/)+/, '');\n  entry = entry.replace(/^\\/+/, '');\n  entry = entry.replace(/^[A-Za-z]:\\//, '');\n  if (!entry) {\n    entry = slash(basename(name));\n  }\n  return entry;\n}\n\n/**\n * Native binding loaders and infrastructure packages that should be ignored when identifying the actual package that requires native bindings\n */\nconst NATIVE_BINDING_LOADERS = [\n  'node-gyp-build',\n  'prebuild-install',\n  'bindings',\n  'node-addon-api',\n  'node-pre-gyp',\n  'nan', // Native Abstractions for Node.js\n] as const;\n\n/**\n * Finds the first real package from node_modules that likely contains native bindings, filtering out virtual modules and native binding loader infrastructure.\n *\n * @param moduleIds - Array of module IDs from a Rollup chunk\n * @returns The module ID of the actual native package, or undefined if not found\n *\n * @example\n * const moduleIds = [\n *   '\\x00/path/node_modules/bcrypt/bcrypt.js?commonjs-module',\n *   '/path/node_modules/node-gyp-build/index.js',\n *   '/path/node_modules/bcrypt/bcrypt.js',\n * ];\n * findNativePackageModule(moduleIds); // Returns '/path/node_modules/bcrypt/bcrypt.js'\n */\nexport function findNativePackageModule(moduleIds: string[]): string | undefined {\n  return moduleIds.find(id => {\n    // Skip virtual modules (Rollup plugin-generated)\n    if (id.startsWith('\\x00')) {\n      return false;\n    }\n\n    // Must be from node_modules\n    if (!id.includes('/node_modules/')) {\n      return false;\n    }\n\n    // Skip native binding loader infrastructure\n    for (const loader of NATIVE_BINDING_LOADERS) {\n      if (id.includes(`/${loader}/`) || id.includes(`/${loader}@`)) {\n        return false;\n      }\n    }\n\n    return true;\n  });\n}\n\n/**\n * Ensures that server.studioBase is normalized:\n * - Adds leading slash if missing (e.g., 'admin' → '/admin')\n * - Removes trailing slashes (e.g., '/admin/' → '/admin')\n * - Normalizes multiple slashes to single slash (e.g., '//api' → '/api')\n * - Returns empty string for root paths ('/' or '')\n *\n * @param studioBase - The studioBase path to normalize\n * @returns Normalized studioBase path string\n * @throws Error if path contains invalid characters ('..', '?', '#')\n */\nexport function normalizeStudioBase(studioBase: string): string {\n  studioBase = studioBase.trim();\n\n  // Validate: no path traversal, no query params, no special chars\n  if (studioBase.includes('..') || studioBase.includes('?') || studioBase.includes('#')) {\n    throw new Error(`Invalid base path: \"${studioBase}\". Base path cannot contain '..', '?', or '#'`);\n  }\n\n  // Normalize multiple slashes to single slash\n  studioBase = studioBase.replace(/\\/+/g, '/');\n\n  // Handle default value cases\n  if (studioBase === '/' || studioBase === '') {\n    return '';\n  }\n\n  // Remove trailing slash\n  if (studioBase.endsWith('/')) {\n    studioBase = studioBase.slice(0, -1);\n  }\n\n  // Add leading slash if missing\n  if (!studioBase.startsWith('/')) {\n    studioBase = `/${studioBase}`;\n  }\n\n  return studioBase;\n}\n\n/**\n * Configuration values for Studio's index.html placeholder injection.\n *\n * Each value is the **exact JavaScript expression** that replaces the\n * corresponding `'%%PLACEHOLDER%%'` token (including surrounding quotes).\n *\n * For literal strings pass `\"'value'\"` (quoted).\n * For runtime expressions pass the raw JS, e.g. `\"window.location.hostname\"`.\n */\nexport interface StudioInjectionConfig {\n  host: string;\n  port: string;\n  protocol: string;\n  apiPrefix: string;\n  basePath: string;\n  hideCloudCta: string;\n  cloudApiEndpoint: string;\n  experimentalFeatures: string;\n  templates: string;\n  telemetryDisabled: string;\n  requestContextPresets: string;\n  experimentalUI: string;\n  agentSignals: string;\n  signalsUI: string;\n  organizationId: string;\n  platformProjectId: string;\n  platformObservabilityEndpoint: string;\n  autoDetectUrl?: string;\n  devServerInstanceId?: string;\n}\n\n/**\n * Replace all `%%MASTRA_*%%` placeholders in the Studio `index.html` with the\n * supplied configuration values.\n *\n * The `<base href>` tag and the `window.MASTRA_STUDIO_BASE_PATH` assignment\n * use `basePath` as a plain string (no surrounding quotes), while all other\n * placeholders replace `'%%TOKEN%%'` (with surrounding single-quotes in the\n * source HTML) with the provided expression verbatim.\n */\nexport function injectStudioHtmlConfig(html: string, config: StudioInjectionConfig): string {\n  // `String.prototype.replace`/`replaceAll` treat `$` sequences ($$, $&, $`,\n  // $', $n) in the replacement string as special patterns. Config values are\n  // dynamic (e.g. request context presets), so use a replacement function to\n  // insert them verbatim.\n  const replace = (token: string, value: string) => {\n    html = html.replace(token, () => value);\n  };\n\n  replace(`'%%MASTRA_DEV_SERVER_INSTANCE_ID%%'`, config.devServerInstanceId ?? \"''\");\n  replace(`'%%MASTRA_SERVER_HOST%%'`, config.host);\n  replace(`'%%MASTRA_SERVER_PORT%%'`, config.port);\n  replace(`'%%MASTRA_SERVER_PROTOCOL%%'`, config.protocol);\n  replace(`'%%MASTRA_API_PREFIX%%'`, config.apiPrefix);\n  replace(`'%%MASTRA_HIDE_CLOUD_CTA%%'`, config.hideCloudCta);\n  replace(`'%%MASTRA_CLOUD_API_ENDPOINT%%'`, config.cloudApiEndpoint);\n  replace(`'%%MASTRA_EXPERIMENTAL_FEATURES%%'`, config.experimentalFeatures);\n  replace(`'%%MASTRA_TEMPLATES%%'`, config.templates);\n  replace(`'%%MASTRA_TELEMETRY_DISABLED%%'`, config.telemetryDisabled);\n  replace(`'%%MASTRA_REQUEST_CONTEXT_PRESETS%%'`, config.requestContextPresets);\n  replace(`'%%MASTRA_EXPERIMENTAL_UI%%'`, config.experimentalUI);\n  replace(`'%%MASTRA_AGENT_SIGNALS%%'`, config.agentSignals);\n  replace(`'%%MASTRA_SIGNALS_UI%%'`, config.signalsUI);\n  replace(`'%%MASTRA_ORGANIZATION_ID%%'`, config.organizationId);\n  replace(`'%%MASTRA_PLATFORM_PROJECT_ID%%'`, config.platformProjectId);\n  replace(`'%%MASTRA_PLATFORM_OBSERVABILITY_ENDPOINT%%'`, config.platformObservabilityEndpoint);\n  if (config.autoDetectUrl) {\n    replace(`'%%MASTRA_AUTO_DETECT_URL%%'`, config.autoDetectUrl);\n  }\n  html = html.replaceAll('%%MASTRA_STUDIO_BASE_PATH%%', () => config.basePath);\n\n  return html;\n}\n\n/**\n * Escape a dynamic value for embedding inside a single-quoted JavaScript\n * string literal in the Studio `index.html` (e.g. `window.X = '<value>'`).\n * Without it, an env-derived value containing `'` or `</script>` breaks out\n * of the literal and corrupts (or injects into) the served page.\n */\nexport function escapeStudioHtmlValue(value: string): string {\n  return value\n    .replace(/\\\\/g, '\\\\\\\\')\n    .replace(/'/g, \"\\\\'\")\n    .replace(/\\n/g, '\\\\n')\n    .replace(/\\r/g, '\\\\r')\n    .replace(/</g, '\\\\u003c')\n    .replace(/>/g, '\\\\u003e')\n    .replace(/\\u2028/g, '\\\\u2028')\n    .replace(/\\u2029/g, '\\\\u2029');\n}\n\n/**\n * Check if a module is a Node.js builtin module\n * @param specifier - Module specifier\n * @returns True if it's a builtin module\n */\nexport function isBuiltinModule(specifier: string): boolean {\n  return (\n    builtinModules.includes(specifier) ||\n    specifier.startsWith('node:') ||\n    builtinModules.includes(specifier.replace(/^node:/, ''))\n  );\n}\n\n/**\n * Check whether a module specifier is a bare module import rather than a path,\n * virtual module, or Node builtin.\n */\nexport function isBareModuleSpecifier(specifier: string): boolean {\n  if (!specifier || specifier.startsWith('#')) {\n    return false;\n  }\n\n  if (isRelativeImportSpecifier(specifier) || isAbsolutePathSpecifier(specifier)) {\n    return false;\n  }\n\n  if (isBuiltinModule(specifier)) {\n    return false;\n  }\n\n  if (isExternalProtocolImport(specifier)) {\n    return false;\n  }\n\n  return true;\n}\n"],"mappings":"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"}