diff --git a/README.MD b/README.MD index b08a910..7acfd9f 100644 --- a/README.MD +++ b/README.MD @@ -61,9 +61,9 @@ npm install http://xxxx/npm/haina-npm-0.1.0.tgz // import { commons, request, utils, hooks } from '@haina/npm'; // Import only common utilities -import { isEmpty } from '@haina/npm/esm/utils/commons.js'; +import { isEmpty } from '@haina/npm/build/esm/utils/commons.js'; // Import only request utilities -import { fetchJSON } from '@haina/npm/esm/utils/request.js'; +import { fetchJSON } from '@haina/npm/build/esm/utils/request.js'; ``` ### 安装单个模块 diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..75a6316 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "allowJs": true + } +} diff --git a/package.json b/package.json index 5905a2d..fa17ef8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,8 @@ { "name": "@haina/npm", "version": "0.1.0", - "main": "build/esm/index.js", + "main": "./build/cjs/index.js", + "module": "./build/esm/index.js", "exports": { ".": { "import": "./build/esm/index.js", @@ -18,7 +19,8 @@ "generate-indexes": "node scripts/generate-indexes.js", "build:cjs": "npm run generate-indexes && babel src --out-dir build/cjs --plugins=@babel/plugin-transform-modules-commonjs", "build:esm": "npm run generate-indexes && babel src --out-dir build/esm", - "build": "npm run clean && npm run build:cjs && npm run build:esm", + "build:individual": "npm run generate-indexes && rollup -c", + "build": "npm run clean && npm run build:cjs && npm run build:esm && npm run build:individual", "pack": "npm run build && node scripts/pack-modules.js", "pack:all": "npm run build && npm pack --pack-destination ./dist && node scripts/pack-modules.js", "test": "echo \"Error: no test specified\" && exit 1" @@ -27,10 +29,10 @@ "@babel/cli": "^7.28.3", "@babel/core": "^7.28.5", "@babel/preset-env": "^7.28.5", - "rimraf": "^6.1.2" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/hainatravel-it/hai-npm.git" + "@rollup/plugin-babel": "^6.0.4", + "@rollup/plugin-commonjs": "^28.0.0", + "@rollup/plugin-node-resolve": "^15.3.0", + "rimraf": "^6.1.2", + "rollup": "^4.24.0" } } diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 0000000..5f0d98e --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,109 @@ +const { nodeResolve } = require('@rollup/plugin-node-resolve'); +const commonjs = require('@rollup/plugin-commonjs'); +const babel = require('@rollup/plugin-babel'); +const fs = require('fs'); +const path = require('path'); + +// each file in utils +const utilsDir = path.join(__dirname, 'src', 'utils'); +const utilsFiles = fs.readdirSync(utilsDir).filter((file) => file.endsWith('.js') && file !== 'index.js'); + +const srcDir = path.join(__dirname, 'src'); +const hasIndexFiles = []; +const srcItems = fs.readdirSync(srcDir); +srcItems.forEach((item) => { + const itemPath = path.join(srcDir, item); + if (fs.statSync(itemPath).isDirectory()) { + const _Files = fs.readdirSync(itemPath).filter((file) => file.endsWith('.js') && file === 'index.js'); + if (_Files.length > 0) { + hasIndexFiles.push(item); + } + } +}); +// console.log('🍕🍕🍕', utilsFiles); +// console.log('🍕🍕', hasIndexFiles); +const indexEntries = []; +hasIndexFiles.forEach(subDir => { + indexEntries.push(...generateEntries(['index.js'], subDir)); +}); +// src/index.js +indexEntries.push(...generateEntries(['index.js'])); + // console.log('🍕', indexEntries); +// return; + +function generateEntries(files, parentDir) { + // Create entries with both ESM and CJS outputs + const _Entries = files.flatMap((file) => { + const moduleName = path.basename(file, '.js'); + // console.log('🍕', file, moduleName); + + return [ + // ESM output + { + input: parentDir ? `src/${parentDir}/${file}` : `src/${file}`, + output: { + file: parentDir ? `build/esm/${parentDir}/${moduleName}.js` : `build/esm/${moduleName}.js`, + format: 'es', + exports: 'named', + }, + external: [], + plugins: [ + nodeResolve({ + preferBuiltins: false, + }), + commonjs(), + babel({ + babelHelpers: 'bundled', + presets: [ + [ + '@babel/preset-env', + { + modules: false, + targets: '> 0.25%, not dead', + exclude: ['transform-parameters'], + }, + ], + ], + exclude: 'node_modules/**', + }), + ], + }, + // CJS output + { + input: parentDir ? `src/${parentDir}/${file}` : `src/${file}`, + output: { + file: parentDir ? `build/cjs/${parentDir}/${moduleName}.js` : `build/cjs/${moduleName}.js`, + format: 'cjs', + exports: 'named', + }, + external: [], + plugins: [ + nodeResolve({ + preferBuiltins: false, + }), + commonjs(), + babel({ + babelHelpers: 'bundled', + presets: [ + [ + '@babel/preset-env', + { + modules: false, + targets: 'node 14', + }, + ], + ], + exclude: 'node_modules/**', + }), + ], + }, + ]; + }); + return _Entries; +} + +module.exports = [ + // ...utilsEntries + ...generateEntries(utilsFiles, 'utils'), + ...indexEntries, +]; diff --git a/scripts/generate-indexes.js b/scripts/generate-indexes.js index e0f2658..38761b3 100644 --- a/scripts/generate-indexes.js +++ b/scripts/generate-indexes.js @@ -21,7 +21,7 @@ function generateIndexFile(dirPath) { console.log(`Generated index.js for: ${dirPath}`); } -// Generate index for each subdirectory in src +// 1. Generate index for each subdirectory in src const srcDir = path.join(__dirname, '..', 'src'); const srcItems = fs.readdirSync(srcDir); @@ -32,10 +32,10 @@ srcItems.forEach(item => { } }); -// Generate index for src directory that imports subdirectories +// 2 Generate index for src directory that imports subdirectories let srcContent = '\/\/ Auto Generated index.js\n'; -// Add imports for each subdirectory +// 2.1 Add imports for each subdirectory srcItems.forEach(item => { const itemPath = path.join(srcDir, item); if (fs.statSync(itemPath).isDirectory() ) { // && item !== 'utils' @@ -50,7 +50,7 @@ srcItems.forEach(item => { } }); -// Add imports for files in the utils directory +// 2.2 Add imports for files in the utils directory const utilsDir = path.join(srcDir, 'utils'); if (fs.existsSync(utilsDir)) { generateIndexFile(utilsDir); @@ -65,7 +65,6 @@ if (fs.existsSync(utilsDir)) { srcContent += `export * as ${moduleName} from './utils/${file}';\n`; }); } - // Write the src index.js file const srcIndexPath = path.join(srcDir, 'index.js'); fs.writeFileSync(srcIndexPath, srcContent); diff --git a/scripts/pack-modules.js b/scripts/pack-modules.js index b95eb99..66df458 100644 --- a/scripts/pack-modules.js +++ b/scripts/pack-modules.js @@ -49,9 +49,10 @@ if (fs.existsSync(utilsDir)) { } // // Process each individual file in src directory (not in subdirectories) +// const srcDir = path.join(__dirname, '..', 'src'); // const srcFiles = fs.readdirSync(srcDir).filter(file => { // const filePath = path.join(srcDir, file); -// return fs.statSync(filePath).isFile() && file.endsWith('.js'); +// return fs.statSync(filePath).isFile() && file.endsWith('.js') && file !== 'index.js'; // }); // srcFiles.forEach(file => { @@ -72,7 +73,7 @@ function packDirectory(dirName, dirPath) { name: `@haina/${dirName}`, version: require('../package.json').version, description: `Haina ${dirName} module - part of @haina/npm utility library`, - main: `build/esm/${dirName}/index.js`, // Assuming there's an index.js in the directory + main: `build/cjs/${dirName}/index.js`, // Assuming there's an index.js in the directory module: `build/esm/${dirName}/index.js`, type: 'module', files: [ @@ -142,8 +143,8 @@ function packIndividualFile(fileName, parentDir, parentPath) { const packageJson = { name: `@haina/${parentDir}-${moduleName}`, version: require('../package.json').version, - description: `Haina ${moduleName} module - part of @haina/npm utility library`, - main: parentDir === 'src' ? `build/esm/${fileName}` : `build/esm/${parentDir}/${fileName}`, + description: `Haina ${parentDir}-${moduleName} module - part of @haina/npm utility library`, + main: parentDir === 'src' ? `build/cjs/${fileName}` : `build/cjs/${parentDir}/${fileName}`, module: parentDir === 'src' ? `build/esm/${fileName}` : `build/esm/${parentDir}/${fileName}`, type: 'module', files: [ @@ -164,7 +165,7 @@ function packIndividualFile(fileName, parentDir, parentPath) { if (fs.existsSync(readmePath)) { const readmeContent = fs.readFileSync(readmePath, 'utf8'); // Add module-specific information to README - const moduleReadmeContent = `# @haina/${moduleName}\n\n${readmeContent}\n\n## Note\n\nThis is a standalone module from the \`@haina/npm\` package. \n\nFor more information about the full package, visit the [original repository](https://github.com/hainatravel-it/hai-npm.git).\n`; + const moduleReadmeContent = `# @haina/${parentDir}-${moduleName}\n\n${readmeContent}\n\n## Note\n\nThis is a standalone module from the \`@haina/npm\` package. \n\nFor more information about the full package, visit the [original repository](https://github.com/hainatravel-it/hai-npm.git).\n`; fs.writeFileSync(path.join(moduleDir, 'README.MD'), moduleReadmeContent); } @@ -194,18 +195,22 @@ function packIndividualFile(fileName, parentDir, parentPath) { // Copy the specific module file const srcFile = fileName; - fs.copyFileSync( - path.join(esmSrcDir, srcFile), - path.join(esmDestDir, srcFile) - ); + if (fs.existsSync(path.join(esmSrcDir, srcFile))) { + fs.copyFileSync( + path.join(esmSrcDir, srcFile), + path.join(esmDestDir, srcFile) + ); + } - fs.copyFileSync( - path.join(cjsSrcDir, srcFile), - path.join(cjsDestDir, srcFile) - ); + if (fs.existsSync(path.join(cjsSrcDir, srcFile))) { + fs.copyFileSync( + path.join(cjsSrcDir, srcFile), + path.join(cjsDestDir, srcFile) + ); + } // Run npm pack in the module directory - console.log(`Packing individual file module: ${moduleName}`); + console.log(`Packing individual file module: ${parentDir}.${moduleName}`); const result = execSync(`cd "${moduleDir}" && npm pack`, { encoding: 'utf8' }); console.log(result); diff --git a/src/index.js b/src/index.js index 54c4fb8..13c4eb7 100644 --- a/src/index.js +++ b/src/index.js @@ -2,4 +2,5 @@ export * as hooks from './hooks/index.js'; export * as utils from './utils/index.js'; export * as commons from './utils/commons.js'; +export * as pagespy from './utils/pagespy.js'; export * as request from './utils/request.js'; diff --git a/src/utils/commons.js b/src/utils/commons.js index 5c63021..f40dfde 100644 --- a/src/utils/commons.js +++ b/src/utils/commons.js @@ -653,6 +653,10 @@ export const getNestedValue = (obj, keyArr) => { /** * 计算笛卡尔积 + * @param {object[]} arr + * @param {string} sep '_' + * @param {number} index 0 + * @param {string} prefix '' */ export const cartesianProductArray = (arr, sep = '_', index = 0, prefix = '') => { let result = []; diff --git a/src/utils/index.js b/src/utils/index.js index b798c78..2618f53 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -1,3 +1,4 @@ // Auto Generated index.js export * as commons from './commons.js'; +export * as pagespy from './pagespy.js'; export * as request from './request.js'; diff --git a/src/utils/pagespy.js b/src/utils/pagespy.js new file mode 100644 index 0000000..2b45546 --- /dev/null +++ b/src/utils/pagespy.js @@ -0,0 +1,63 @@ +import { loadScript } from './commons'; + +const TODAY_TIME = new Date().getTime(); + +export const loadPageSpy = (title, projectName = 'hn-page-spy') => { + if (import.meta.env.DEV || window.$pageSpy) return; + + const PageSpyConfig = { api: 'page-spy.mycht.cn', project: projectName, title: title, autoRender: false }; + const PageSpySrc = [ + 'https://page-spy.mycht.cn/page-spy/index.min.js' + `?v=${TODAY_TIME}`, + 'https://page-spy.mycht.cn/plugin/data-harbor/index.min.js' + `?v=${TODAY_TIME}`, + 'https://page-spy.mycht.cn/plugin/rrweb/index.min.js' + `?v=${TODAY_TIME}`, + ]; + + Promise.all(PageSpySrc.map((src) => loadScript(src))).then(() => { + // 注册插件 + window.$harbor = new DataHarborPlugin(); + window.$rrweb = new RRWebPlugin(); + [window.$harbor, window.$rrweb].forEach((p) => { + PageSpy.registerPlugin(p); + }); + window.$pageSpy = new PageSpy(PageSpyConfig); + + window.onerror = async function (msg, url, lineNo, columnNo, error) { + + // 当页面有 iframe 时,rrweb 会报错:Cannot set property attributeName of # which has only a getter + // 而且这个错误无法修复,所以只能先忽略掉 + if (url && url.indexOf('https://page-spy.mycht.cn/plugin/rrweb/index.min.js') > -1) { + console.info('ignore rrweb error') + } else { + // 上传最近 5 分钟的日志 + const now = Date.now() + await window.$harbor.uploadPeriods({ + startTime: now - 5 * 60000, + endTime: now, + remark: `\`onerror\`自动上传. ${msg}`, + }) + } + } + }); +}; + +export const uploadPageSpyLog = async (remark = '') => { + + if (import.meta.env.DEV) return true; + + if (window.$pageSpy) { + try { + // 上传最近一小时的日志, 直接upload 所有日志: 413 Payload Too Large + const now = Date.now(); + await window.$harbor.uploadPeriods({ + startTime: now - 1 * 60 * 60000, + endTime: now, + remark, + }); + return true; + } catch (error) { + return false; + } + } else { + return false; + } +} diff --git a/structure.txt b/structure.txt new file mode 100644 index 0000000..dfb6e46 --- /dev/null +++ b/structure.txt @@ -0,0 +1,59 @@ +卷 软件 的文件夹 PATH 列表 +卷序列号为 C9C1-727D +D:. +│ .babelrc +│ .gitignore +│ .npmignore +│ package-lock.json +│ package.json +│ README.MD +│ +├─build +│ ├─cjs +│ │ │ index.js +│ │ │ +│ │ ├─hooks +│ │ │ index.js +│ │ │ useHTLanguageSets.js +│ │ │ +│ │ └─utils +│ │ commons.js +│ │ index.js +│ │ request.js +│ │ +│ └─esm +│ │ index.js +│ │ +│ ├─hooks +│ │ index.js +│ │ useHTLanguageSets.js +│ │ +│ └─utils +│ commons.js +│ index.js +│ request.js +│ +├─dist +│ haina-npm-0.1.0.tgz +│ hooks-0.1.0.tgz +│ structure.txt +│ utils-0.1.0.tgz +│ utils-commons-0.1.0.tgz +│ utils-request-0.1.0.tgz +│ +├─scripts +│ generate-indexes.js +│ pack-modules.js +│ +└─src + │ index.js + │ + ├─hooks + │ index.js + │ useHTLanguageSets.js + │ + └─utils + commons.js + index.js + request.js +