esbuild.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. const esbuild = require("esbuild")
  2. const fs = require("fs")
  3. const path = require("path")
  4. const production = process.argv.includes("--production")
  5. const watch = process.argv.includes("--watch")
  6. /**
  7. * @type {import('esbuild').Plugin}
  8. */
  9. const esbuildProblemMatcherPlugin = {
  10. name: "esbuild-problem-matcher",
  11. setup(build) {
  12. build.onStart(() => {
  13. console.log("[watch] build started")
  14. })
  15. build.onEnd((result) => {
  16. result.errors.forEach(({ text, location }) => {
  17. console.error(`✘ [ERROR] ${text}`)
  18. console.error(` ${location.file}:${location.line}:${location.column}:`)
  19. })
  20. console.log("[watch] build finished")
  21. })
  22. },
  23. }
  24. const copyWasmFiles = {
  25. name: "copy-wasm-files",
  26. setup(build) {
  27. build.onEnd(() => {
  28. const nodeModulesDir = path.join(__dirname, "node_modules")
  29. const distDir = path.join(__dirname, "dist")
  30. // tiktoken WASM file
  31. fs.copyFileSync(
  32. path.join(nodeModulesDir, "tiktoken", "tiktoken_bg.wasm"),
  33. path.join(distDir, "tiktoken_bg.wasm"),
  34. )
  35. // Main tree-sitter WASM file
  36. fs.copyFileSync(
  37. path.join(nodeModulesDir, "web-tree-sitter", "tree-sitter.wasm"),
  38. path.join(distDir, "tree-sitter.wasm"),
  39. )
  40. // Copy language-specific WASM files
  41. const languageWasmDir = path.join(__dirname, "node_modules", "tree-sitter-wasms", "out")
  42. // Dynamically read all WASM files from the directory instead of using a hardcoded list
  43. if (fs.existsSync(languageWasmDir)) {
  44. const wasmFiles = fs.readdirSync(languageWasmDir).filter((file) => file.endsWith(".wasm"))
  45. console.log(`Copying ${wasmFiles.length} tree-sitter WASM files to dist directory`)
  46. wasmFiles.forEach((filename) => {
  47. fs.copyFileSync(path.join(languageWasmDir, filename), path.join(distDir, filename))
  48. })
  49. } else {
  50. console.warn(`Tree-sitter WASM directory not found: ${languageWasmDir}`)
  51. }
  52. })
  53. },
  54. }
  55. // Simple function to copy locale files
  56. function copyLocaleFiles() {
  57. const srcDir = path.join(__dirname, "src", "i18n", "locales")
  58. const destDir = path.join(__dirname, "dist", "i18n", "locales")
  59. const outDir = path.join(__dirname, "out", "i18n", "locales")
  60. // Ensure source directory exists before proceeding
  61. if (!fs.existsSync(srcDir)) {
  62. console.warn(`Source locales directory does not exist: ${srcDir}`)
  63. return // Exit early if source directory doesn't exist
  64. }
  65. // Create destination directories
  66. fs.mkdirSync(destDir, { recursive: true })
  67. try {
  68. fs.mkdirSync(outDir, { recursive: true })
  69. } catch (e) {}
  70. // Function to copy directory recursively
  71. function copyDir(src, dest) {
  72. const entries = fs.readdirSync(src, { withFileTypes: true })
  73. for (const entry of entries) {
  74. const srcPath = path.join(src, entry.name)
  75. const destPath = path.join(dest, entry.name)
  76. if (entry.isDirectory()) {
  77. // Create directory and copy contents
  78. fs.mkdirSync(destPath, { recursive: true })
  79. copyDir(srcPath, destPath)
  80. } else {
  81. // Copy the file
  82. fs.copyFileSync(srcPath, destPath)
  83. }
  84. }
  85. }
  86. // Copy files to dist directory
  87. copyDir(srcDir, destDir)
  88. console.log("Copied locale files to dist/i18n/locales")
  89. // Copy to out directory for debugging
  90. try {
  91. copyDir(srcDir, outDir)
  92. console.log("Copied locale files to out/i18n/locales")
  93. } catch (e) {
  94. console.warn("Could not copy to out directory:", e.message)
  95. }
  96. }
  97. // Set up file watcher if in watch mode
  98. function setupLocaleWatcher() {
  99. if (!watch) return
  100. const localesDir = path.join(__dirname, "src", "i18n", "locales")
  101. // Ensure the locales directory exists before setting up watcher
  102. if (!fs.existsSync(localesDir)) {
  103. console.warn(`Cannot set up watcher: Source locales directory does not exist: ${localesDir}`)
  104. return
  105. }
  106. console.log(`Setting up watcher for locale files in ${localesDir}`)
  107. // Use a debounce mechanism
  108. let debounceTimer = null
  109. const debouncedCopy = () => {
  110. if (debounceTimer) clearTimeout(debounceTimer)
  111. debounceTimer = setTimeout(() => {
  112. console.log("Locale files changed, copying...")
  113. copyLocaleFiles()
  114. }, 300) // Wait 300ms after last change before copying
  115. }
  116. // Watch the locales directory
  117. try {
  118. fs.watch(localesDir, { recursive: true }, (eventType, filename) => {
  119. if (filename && filename.endsWith(".json")) {
  120. console.log(`Locale file ${filename} changed, triggering copy...`)
  121. debouncedCopy()
  122. }
  123. })
  124. console.log("Watcher for locale files is set up")
  125. } catch (error) {
  126. console.error(`Error setting up watcher for ${localesDir}:`, error.message)
  127. }
  128. }
  129. const copyLocalesFiles = {
  130. name: "copy-locales-files",
  131. setup(build) {
  132. build.onEnd(() => {
  133. copyLocaleFiles()
  134. })
  135. },
  136. }
  137. const extensionConfig = {
  138. bundle: true,
  139. minify: production,
  140. sourcemap: !production,
  141. logLevel: "silent",
  142. plugins: [
  143. copyWasmFiles,
  144. copyLocalesFiles,
  145. /* add to the end of plugins array */
  146. esbuildProblemMatcherPlugin,
  147. {
  148. name: "alias-plugin",
  149. setup(build) {
  150. build.onResolve({ filter: /^pkce-challenge$/ }, (_args) => {
  151. return { path: require.resolve("pkce-challenge/dist/index.browser.js") }
  152. })
  153. },
  154. },
  155. ],
  156. entryPoints: ["src/extension.ts"],
  157. format: "cjs",
  158. sourcesContent: false,
  159. platform: "node",
  160. outfile: "dist/extension.js",
  161. external: ["vscode"],
  162. }
  163. const workerConfig = {
  164. bundle: true,
  165. minify: production,
  166. sourcemap: !production,
  167. logLevel: "silent",
  168. entryPoints: ["src/workers/countTokens.ts"],
  169. format: "cjs",
  170. sourcesContent: false,
  171. platform: "node",
  172. outdir: "dist/workers",
  173. }
  174. async function main() {
  175. const [extensionCtx, workerCtx] = await Promise.all([
  176. esbuild.context(extensionConfig),
  177. esbuild.context(workerConfig),
  178. ])
  179. if (watch) {
  180. await Promise.all([extensionCtx.watch(), workerCtx.watch()])
  181. copyLocaleFiles()
  182. setupLocaleWatcher()
  183. } else {
  184. await Promise.all([extensionCtx.rebuild(), workerCtx.rebuild()])
  185. await Promise.all([extensionCtx.dispose(), workerCtx.dispose()])
  186. }
  187. }
  188. main().catch((e) => {
  189. console.error(e)
  190. process.exit(1)
  191. })