generateExports.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. const fs = require('fs');
  2. const path = require('path');
  3. /**
  4. * 扫描目录,找到所有需要导出的文件
  5. */
  6. function scanDirectory(dir, basePath = '') {
  7. const exports = {};
  8. if (!fs.existsSync(dir)) {
  9. return exports;
  10. }
  11. const entries = fs.readdirSync(dir, { withFileTypes: true });
  12. for (const entry of entries) {
  13. const fullPath = path.join(dir, entry.name);
  14. const relativePath = basePath ? `${basePath}/${entry.name}` : entry.name;
  15. if (entry.isDirectory()) {
  16. // 检查目录是否有 index.js
  17. const indexJsPath = path.join(fullPath, 'index.js');
  18. if (fs.existsSync(indexJsPath)) {
  19. // 为目录生成导出映射(指向 index.js)
  20. const exportKey = `./lib/es/${relativePath}`;
  21. const exportKeyNoLib = `./${relativePath}`;
  22. const esPath = `lib/es/${relativePath}/index.js`;
  23. const cjsPath = `lib/cjs/${relativePath}/index.js`;
  24. const typesPath = `lib/es/${relativePath}/index.d.ts`;
  25. const exportValue = {
  26. types: `./${typesPath}`,
  27. import: `./${esPath}`,
  28. require: `./${cjsPath}`
  29. };
  30. // 添加带 lib/es 前缀的键
  31. exports[exportKey] = exportValue;
  32. // 添加不带 lib/es 前缀的键
  33. exports[exportKeyNoLib] = exportValue;
  34. }
  35. // 递归扫描子目录
  36. const subExports = scanDirectory(fullPath, relativePath);
  37. Object.assign(exports, subExports);
  38. } else if (entry.isFile()) {
  39. if (entry.name.endsWith('.js')) {
  40. // 找到 .js 文件,生成导出映射
  41. // relativePath 已经是相对于 lib/es 的路径
  42. // 生成两个键:带 .js 和不带 .js(因为导入时可能不带扩展名)
  43. const pathWithoutExt = relativePath.replace(/\.js$/, '');
  44. const exportKeyWithExt = `./lib/es/${relativePath}`;
  45. const exportKeyWithoutExt = `./lib/es/${pathWithoutExt}`;
  46. // 添加不带 lib/es 前缀的路径
  47. const exportKeyWithExtNoLib = `./${relativePath}`;
  48. const exportKeyWithoutExtNoLib = `./${pathWithoutExt}`;
  49. const esPath = `lib/es/${relativePath}`;
  50. const cjsPath = `lib/cjs/${relativePath}`;
  51. const typesPath = `lib/es/${relativePath.replace(/\.js$/, '.d.ts')}`;
  52. const exportValue = {
  53. types: `./${typesPath}`,
  54. import: `./${esPath}`,
  55. require: `./${cjsPath}`
  56. };
  57. // 添加带扩展名的键(带 lib/es)
  58. exports[exportKeyWithExt] = exportValue;
  59. // 添加不带扩展名的键(带 lib/es,如果不同)
  60. if (exportKeyWithExt !== exportKeyWithoutExt) {
  61. exports[exportKeyWithoutExt] = exportValue;
  62. }
  63. // 添加不带 lib/es 前缀的键(带扩展名)
  64. exports[exportKeyWithExtNoLib] = exportValue;
  65. // 添加不带 lib/es 前缀的键(不带扩展名,如果不同)
  66. if (exportKeyWithExtNoLib !== exportKeyWithoutExtNoLib) {
  67. exports[exportKeyWithoutExtNoLib] = exportValue;
  68. }
  69. } else if (entry.name.endsWith('.css')) {
  70. // 找到 .css 文件,生成导出映射
  71. const exportKey = `./lib/es/${relativePath}`;
  72. const exportKeyNoLib = `./${relativePath}`;
  73. const esPath = `lib/es/${relativePath}`;
  74. const cjsPath = `lib/cjs/${relativePath}`;
  75. const exportValue = {
  76. import: `./${esPath}`,
  77. require: `./${cjsPath}`,
  78. default: `./${esPath}`
  79. };
  80. // 添加带 lib/es 前缀的键
  81. exports[exportKey] = exportValue;
  82. // 添加不带 lib/es 前缀的键
  83. exports[exportKeyNoLib] = exportValue;
  84. } else if (entry.name.endsWith('.scss')) {
  85. // 找到 .scss 文件,生成导出映射
  86. const exportKey = `./lib/es/${relativePath}`;
  87. const exportKeyNoLib = `./${relativePath}`;
  88. const esPath = `lib/es/${relativePath}`;
  89. const cjsPath = `lib/cjs/${relativePath}`;
  90. const exportValue = {
  91. import: `./${esPath}`,
  92. require: `./${cjsPath}`,
  93. default: `./${esPath}`
  94. };
  95. // 添加带 lib/es 前缀的键
  96. exports[exportKey] = exportValue;
  97. // 添加不带 lib/es 前缀的键
  98. exports[exportKeyNoLib] = exportValue;
  99. }
  100. }
  101. }
  102. return exports;
  103. }
  104. /**
  105. * 生成 exports 字段
  106. */
  107. function generateExports() {
  108. const libEsPath = path.join(__dirname, '../lib/es');
  109. if (!fs.existsSync(libEsPath)) {
  110. console.error('Error: lib/es directory does not exist. Please run build:lib first.');
  111. process.exit(1);
  112. }
  113. console.log('Scanning lib/es directory...');
  114. const exports = scanDirectory(libEsPath, '');
  115. // 添加主入口
  116. const mainExports = {
  117. '.': {
  118. types: './lib/es/base/index.d.ts',
  119. import: './lib/es/base/index.js',
  120. require: './lib/cjs/base/index.js'
  121. }
  122. };
  123. // 添加 CSS 文件的通配符规则(这些通常可以正常工作)
  124. const cssExports = {
  125. './lib/es/*/*.css': {
  126. import: './lib/es/*/*.css',
  127. require: './lib/cjs/*/*.css',
  128. default: './lib/es/*/*.css'
  129. },
  130. './lib/es/*.css': {
  131. import: './lib/es/*.css',
  132. require: './lib/cjs/*.css',
  133. default: './lib/es/*.css'
  134. },
  135. './lib/cjs/*/*.css': {
  136. import: './lib/es/*/*.css',
  137. require: './lib/cjs/*/*.css',
  138. default: './lib/cjs/*/*.css'
  139. },
  140. './lib/cjs/*.css': {
  141. import: './lib/es/*.css',
  142. require: './lib/cjs/*.css',
  143. default: './lib/cjs/*.css'
  144. },
  145. // 添加不带 lib/es 前缀的通配符规则
  146. './*/*.css': {
  147. import: './lib/es/*/*.css',
  148. require: './lib/cjs/*/*.css',
  149. default: './lib/es/*/*.css'
  150. },
  151. './*.css': {
  152. import: './lib/es/*.css',
  153. require: './lib/cjs/*.css',
  154. default: './lib/es/*.css'
  155. }
  156. };
  157. // 添加 SCSS 文件的通配符规则
  158. const scssExports = {
  159. './lib/es/*/*.scss': {
  160. import: './lib/es/*/*.scss',
  161. require: './lib/cjs/*/*.scss',
  162. default: './lib/es/*/*.scss'
  163. },
  164. './lib/es/*.scss': {
  165. import: './lib/es/*.scss',
  166. require: './lib/cjs/*.scss',
  167. default: './lib/es/*.scss'
  168. },
  169. './lib/cjs/*/*.scss': {
  170. import: './lib/es/*/*.scss',
  171. require: './lib/cjs/*/*.scss',
  172. default: './lib/cjs/*/*.scss'
  173. },
  174. './lib/cjs/*.scss': {
  175. import: './lib/es/*.scss',
  176. require: './lib/cjs/*.scss',
  177. default: './lib/cjs/*.scss'
  178. },
  179. // 添加不带 lib/es 前缀的通配符规则
  180. './*/*.scss': {
  181. import: './lib/es/*/*.scss',
  182. require: './lib/cjs/*/*.scss',
  183. default: './lib/es/*/*.scss'
  184. },
  185. './*.scss': {
  186. import: './lib/es/*.scss',
  187. require: './lib/cjs/*.scss',
  188. default: './lib/es/*.scss'
  189. }
  190. };
  191. // 合并所有 exports
  192. const allExports = {
  193. ...mainExports,
  194. ...exports,
  195. ...cssExports,
  196. ...scssExports
  197. };
  198. console.log(`Generated ${Object.keys(exports).length} export paths`);
  199. return allExports;
  200. }
  201. /**
  202. * 更新 package.json
  203. */
  204. function updatePackageJson() {
  205. const packageJsonPath = path.join(__dirname, '../package.json');
  206. const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
  207. // 生成新的 exports
  208. const newExports = generateExports();
  209. // 更新 package.json
  210. packageJson.exports = newExports;
  211. // 写回文件
  212. fs.writeFileSync(
  213. packageJsonPath,
  214. JSON.stringify(packageJson, null, 4) + '\n',
  215. 'utf-8'
  216. );
  217. console.log('Successfully updated package.json exports field');
  218. console.log(`Total exports: ${Object.keys(newExports).length}`);
  219. }
  220. // 运行脚本
  221. if (require.main === module) {
  222. try {
  223. updatePackageJson();
  224. } catch (error) {
  225. console.error('Error:', error.message);
  226. process.exit(1);
  227. }
  228. }
  229. module.exports = { generateExports, updatePackageJson };