From 36b5cc535f6bb401c3cc6545cf174a1f1e44db3d Mon Sep 17 00:00:00 2001 From: Aiden-FE Date: Thu, 21 Mar 2024 14:48:44 +0800 Subject: [PATCH] feat: support create utils template --- .eslintrc.cjs | 2 +- package.json | 2 +- pnpm-lock.yaml | 8 +- src/utils/batch-compile-templates.ts | 23 +++ src/utils/create-turbo.ts | 14 +- src/utils/create-utils.ts | 53 +++++- src/utils/index.ts | 1 + templates/utils/.eslintrc.cjs.handlebars | 13 ++ .../workflows/lint-and-test.yml.handlebars | 59 ++++++ .../publish-and-deploy.yml.handlebars | 110 +++++++++++ templates/utils/.gitignore | 174 ++++++++++++++++++ templates/utils/.prettierignore | 1 + templates/utils/.prettierrc.json | 14 ++ templates/utils/README.md.handlebars | 104 +++++++++++ templates/utils/commitlint.config.js | 3 + templates/utils/jest.config.cjs | 23 +++ templates/utils/package.json.handlebars | 11 +- templates/utils/rollup.config.js | 121 ++++++++++++ templates/utils/src/common-modules/index.ts | 6 + templates/utils/src/interfaces/index.ts | 6 + templates/utils/src/node-modules/index.ts | 6 + templates/utils/src/node.ts | 8 + templates/utils/src/web-modules/index.ts | 6 + templates/utils/src/web.ts | 8 + templates/utils/tsconfig.json.handlebars | 31 ++++ templates/utils/tsconfig.node.json.handlebars | 28 +++ templates/utils/tsconfig.test.json | 12 ++ templates/utils/tsconfig.web.json.handlebars | 13 ++ 28 files changed, 832 insertions(+), 28 deletions(-) create mode 100644 src/utils/batch-compile-templates.ts create mode 100644 templates/utils/.eslintrc.cjs.handlebars create mode 100644 templates/utils/.github/workflows/lint-and-test.yml.handlebars create mode 100644 templates/utils/.github/workflows/publish-and-deploy.yml.handlebars create mode 100644 templates/utils/.gitignore create mode 100644 templates/utils/.prettierignore create mode 100644 templates/utils/.prettierrc.json create mode 100644 templates/utils/README.md.handlebars create mode 100644 templates/utils/commitlint.config.js create mode 100644 templates/utils/jest.config.cjs create mode 100644 templates/utils/rollup.config.js create mode 100644 templates/utils/src/common-modules/index.ts create mode 100644 templates/utils/src/interfaces/index.ts create mode 100644 templates/utils/src/node-modules/index.ts create mode 100644 templates/utils/src/node.ts create mode 100644 templates/utils/src/web-modules/index.ts create mode 100644 templates/utils/src/web.ts create mode 100644 templates/utils/tsconfig.json.handlebars create mode 100644 templates/utils/tsconfig.node.json.handlebars create mode 100644 templates/utils/tsconfig.test.json create mode 100644 templates/utils/tsconfig.web.json.handlebars diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 998a389..f6de517 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -2,7 +2,7 @@ module.exports = { parserOptions: { project: ['./tsconfig.json'], }, - ignorePatterns: ['.eslintrc.cjs', 'dist', 'types', 'node_modules'], + ignorePatterns: ['.eslintrc.cjs', 'dist', 'types', 'node_modules', 'templates'], extends: [ // typescript使用此配置 '@compass-aiden/eslint-config/ts', diff --git a/package.json b/package.json index 0171d06..9e30ddd 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "typescript": "^5.4.2" }, "dependencies": { - "@compass-aiden/helpers": "^0.1.1", + "@compass-aiden/helpers": "^0.2.0", "@compass-aiden/telegram": "^2.1.0", "axios": "^1.6.7", "chalk": "^5.3.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9aba4cb..31858c0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,8 +6,8 @@ settings: dependencies: '@compass-aiden/helpers': - specifier: ^0.1.1 - version: 0.1.1 + specifier: ^0.2.0 + version: 0.2.0 '@compass-aiden/telegram': specifier: ^2.1.0 version: 2.1.0(axios@1.6.7) @@ -337,8 +337,8 @@ packages: eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0)(eslint@8.57.0) dev: true - /@compass-aiden/helpers@0.1.1: - resolution: {integrity: sha512-16Bbuv+ZVXA7muClclwccjP388laMJ3h8JiRcV6wte2xp2O0dL77KkYF+K0CzQAZwJ1SnL22nLY0tH3SNLJpdQ==} + /@compass-aiden/helpers@0.2.0: + resolution: {integrity: sha512-sn27xu6OvZdgEmaB+78gDqx6Zp/Q1m99ioIXNTIJO2X1MBHUUgvFU1+VlesOpXGQw3vYkQxgUvRa1xaqJjwgew==} dev: false /@compass-aiden/telegram@2.1.0(axios@1.6.7): diff --git a/src/utils/batch-compile-templates.ts b/src/utils/batch-compile-templates.ts new file mode 100644 index 0000000..b928d75 --- /dev/null +++ b/src/utils/batch-compile-templates.ts @@ -0,0 +1,23 @@ +import { readFileSync } from 'fs'; +import { dirname } from 'path'; +import handlebars from 'handlebars'; +import { createFileSync, createFolder, isFileOrFolderExists } from '@compass-aiden/helpers/cjs'; + +/** + * @description 使用handlebars批量编译模板 + * @param temps 模板的源路径与目标路径 + * @param tempData 模板的上下文数据 + */ +export default async function batchCompileTemplates(temps: [string, string][], tempData: Record) { + const tasks = temps.map(async (temp) => { + if (temp && temp[0] && temp[1]) { + const compileTemp = handlebars.compile(readFileSync(temp[0], 'utf-8')); + const targetDirPath = dirname(temp[1]); + if (!isFileOrFolderExists(targetDirPath)) { + await createFolder(targetDirPath); + } + createFileSync(temp[1], compileTemp(tempData)); + } + }); + await Promise.all(tasks); +} diff --git a/src/utils/create-turbo.ts b/src/utils/create-turbo.ts index 81a6cd6..6c7d5ac 100644 --- a/src/utils/create-turbo.ts +++ b/src/utils/create-turbo.ts @@ -144,14 +144,14 @@ export default async function createTurbo(options?: { pkgManager?: PkgManager }) await createFolder(projectPath, {}); // 创建workspaces配置 if (opt.pkgManager === 'pnpm') { - createFile('package.json', PACKAGE_FILE, execOptions); - createFile('pnpm-workspace.yaml', PNPM_WORKSPACES_FILE, execOptions); + await createFile('package.json', PACKAGE_FILE, execOptions); + await createFile('pnpm-workspace.yaml', PNPM_WORKSPACES_FILE, execOptions); } else { - createFile('package.json', WORKSPACE_PACKAGE_FILE, execOptions); + await createFile('package.json', WORKSPACE_PACKAGE_FILE, execOptions); } - createFolder('apps', execOptions); - createFolder('packages', execOptions); - createFile('turbo.json', TURBO_JSON_FILE, execOptions); - createFile('.gitignore', GITIGNORE_FILE, execOptions); + await createFolder('apps', execOptions); + await createFolder('packages', execOptions); + await createFile('turbo.json', TURBO_JSON_FILE, execOptions); + await createFile('.gitignore', GITIGNORE_FILE, execOptions); loading.succeed(chalk.green('创建完成')); } diff --git a/src/utils/create-utils.ts b/src/utils/create-utils.ts index 252b913..bc90e3b 100644 --- a/src/utils/create-utils.ts +++ b/src/utils/create-utils.ts @@ -1,11 +1,10 @@ import { fileURLToPath } from 'url'; import { join, dirname } from 'path'; -import { readFileSync } from 'fs'; import inquirer from 'inquirer'; import ora from 'ora'; import chalk from 'chalk'; -import handlebars from 'handlebars'; -import { createFile, createFolder, isFileOrFolderExists } from '@compass-aiden/helpers/cjs'; +import { createFolder, isFileOrFolderExists, copyFolderSync } from '@compass-aiden/helpers/cjs'; +import batchCompileTemplates from './batch-compile-templates'; // eslint-disable-next-line @typescript-eslint/naming-convention, no-underscore-dangle const __filename = fileURLToPath(import.meta.url); @@ -14,7 +13,8 @@ const __dirname = dirname(__filename); const utilsTempBasePath = join(__dirname, '../templates/utils'); export default async function createUtils() { - const { + /* eslint-disable prefer-const */ + let { projectPath, projectDescription, enabledEslint, @@ -23,6 +23,8 @@ export default async function createUtils() { enabledTypedoc, enabledPrettyQuick, enabledCommitlint, + enabledGithubActions, + /* eslint-enable prefer-const */ } = await inquirer.prompt([ { type: 'input', @@ -72,6 +74,12 @@ export default async function createUtils() { message: '是否启用Commitlint在代码提交时校验提交信息', defaut: true, }, + { + type: 'confirm', + name: 'enabledGithubActions', + message: '是否启用Github actions CICD执行自动化任务', + defaut: true, + }, ]); const loading = ora(); loading.start(chalk.cyan('开始创建项目文件\n')); @@ -80,14 +88,37 @@ export default async function createUtils() { return; } const enabledGithooks = enabledPrettyQuick || enabledCommitlint; + if (enabledPrettyQuick) { + enabledPrettier = true; + } const pathArr = projectPath.split('/'); const projectName = pathArr.pop(); await createFolder(projectPath, {}); - // 输出package.json文件 - const packageTemplate = handlebars.compile(readFileSync(join(utilsTempBasePath, 'package.json.handlebars'), 'utf-8')); - createFile( - join(projectPath, 'package.json'), - packageTemplate({ + await batchCompileTemplates( + [ + [join(utilsTempBasePath, 'package.json.handlebars'), join(projectPath, 'package.json')], + [join(utilsTempBasePath, 'tsconfig.json.handlebars'), join(projectPath, 'tsconfig.json')], + [join(utilsTempBasePath, 'tsconfig.web.json.handlebars'), join(projectPath, 'tsconfig.web.json')], + [join(utilsTempBasePath, 'tsconfig.node.json.handlebars'), join(projectPath, 'tsconfig.node.json')], + [join(utilsTempBasePath, 'rollup.config.js'), join(projectPath, 'rollup.config.js')], + [join(utilsTempBasePath, 'README.md.handlebars'), join(projectPath, 'README.md')], + [join(utilsTempBasePath, '.gitignore'), join(projectPath, '.gitignore')], + enabledJest && [join(utilsTempBasePath, 'tsconfig.test.json'), join(projectPath, 'tsconfig.test.json')], + enabledJest && [join(utilsTempBasePath, 'jest.config.cjs'), join(projectPath, 'jest.config.cjs')], + enabledCommitlint && [join(utilsTempBasePath, 'commitlint.config.js'), join(projectPath, 'commitlint.config.js')], + enabledPrettier && [join(utilsTempBasePath, '.prettierrc.json'), join(projectPath, '.prettierrc.json')], + enabledPrettier && [join(utilsTempBasePath, '.prettierignore'), join(projectPath, '.prettierignore')], + enabledEslint && [join(utilsTempBasePath, '.eslintrc.cjs.handlebars'), join(projectPath, '.eslintrc.cjs')], + enabledGithubActions && [ + join(utilsTempBasePath, '.github/workflows/lint-and-test.yml.handlebars'), + join(projectPath, '.github/workflows/lint-and-test.yml'), + ], + enabledGithubActions && [ + join(utilsTempBasePath, '.github/workflows/publish-and-deploy.yml.handlebars'), + join(projectPath, '.github/workflows/publish-and-deploy.yml'), + ], + ], + { projectDescription, enabledEslint, enabledPrettier, @@ -97,7 +128,9 @@ export default async function createUtils() { enabledCommitlint, enabledGithooks, projectName, - }), + enabledGithubActions, + }, ); + copyFolderSync(join(utilsTempBasePath, 'src'), join(projectPath, 'src')); loading.succeed(chalk.green('创建完成')); } diff --git a/src/utils/index.ts b/src/utils/index.ts index edfd672..a120744 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -7,3 +7,4 @@ export { default as createElectron } from './create-electron'; export { default as createNest } from './create-nest'; export { default as createNext } from './create-next'; export { default as createUtils } from './create-utils'; +export { default as batchCompileTemplates } from './batch-compile-templates'; diff --git a/templates/utils/.eslintrc.cjs.handlebars b/templates/utils/.eslintrc.cjs.handlebars new file mode 100644 index 0000000..b74c92d --- /dev/null +++ b/templates/utils/.eslintrc.cjs.handlebars @@ -0,0 +1,13 @@ +module.exports = { + parserOptions: { + project: ['./tsconfig.*.json'], + }, + ignorePatterns: ['.eslintrc.cjs', 'dist', 'types'], + extends: [ + // typescript使用此配置 + '@compass-aiden/eslint-config/ts', + {{#if enabledPrettier}} + 'plugin:prettier/recommended', + {{/if}} + ], +}; diff --git a/templates/utils/.github/workflows/lint-and-test.yml.handlebars b/templates/utils/.github/workflows/lint-and-test.yml.handlebars new file mode 100644 index 0000000..8d7c0f2 --- /dev/null +++ b/templates/utils/.github/workflows/lint-and-test.yml.handlebars @@ -0,0 +1,59 @@ +name: Lint and test + +on: + pull_request: + branches: + - '**' + +jobs: + lint: + name: Lint and test code + runs-on: ubuntu-latest + steps: + # 签出分支 + - name: Checkout Repository + uses: actions/checkout@v3 + with: + fetch-depth: 2 + + # 设置node环境 + - name: Setup node + uses: actions/setup-node@v3 + with: + node-version: 18 + + # 设置pnpm + - uses: pnpm/action-setup@v2 + with: + version: 8.7.1 + + # 设置 pnpm 缓存文件 + - name: Cache pnpm + uses: actions/cache@v3 + with: + path: | + node_modules + key: pnpm-cache-$\{{ runner.os }}-$\{{ hashFiles('pnpm-lock.yaml') }} + + # 恢复项目依赖 + - name: Install + env: + # HUSKY: 0 + SKIP_INSTALL_SIMPLE_GIT_HOOKS: 1 + SKIP_SIMPLE_GIT_HOOKS: 1 + run: | + pnpm install + + {{#if enabledEslint}} + # 检查项目 + - name: Run lint + run: | + pnpm lint + {{/if}} + + {{#if enabledJest}} + # 测试项目 + - name: Run test + run: | + pnpm test + {{/if}} \ No newline at end of file diff --git a/templates/utils/.github/workflows/publish-and-deploy.yml.handlebars b/templates/utils/.github/workflows/publish-and-deploy.yml.handlebars new file mode 100644 index 0000000..cd7b429 --- /dev/null +++ b/templates/utils/.github/workflows/publish-and-deploy.yml.handlebars @@ -0,0 +1,110 @@ +name: Publish and deploy + +on: + push: + branches: + - master + +permissions: + contents: write + pages: write + id-token: write + +concurrency: + group: 'deploy' + cancel-in-progress: false + +jobs: + lint: + name: Publish and deploy + runs-on: ubuntu-latest + steps: + # 签出分支 + - uses: actions/checkout@v4 + + # 设置 git + - name: Setup git + run: | + git config --local user.email github_bot@users.noreply.github.com + git config --local user.name github_bot + + # 设置node环境 + - name: Setup node + uses: actions/setup-node@v3 + with: + node-version: 18 + + # 设置pnpm + - uses: pnpm/action-setup@v2 + with: + version: 8.7.1 + + # 设置 pnpm 缓存文件 + - name: Cache pnpm + uses: actions/cache@v3 + with: + path: | + node_modules + key: pnpm-cache-$\{{ runner.os }}-$\{{ hashFiles('pnpm-lock.yaml') }} + + # 恢复项目依赖 + - name: Install + env: + # HUSKY: 0 + SKIP_INSTALL_SIMPLE_GIT_HOOKS: 1 + SKIP_SIMPLE_GIT_HOOKS: 1 + run: | + pnpm install --frozen-lockfile + + # 同步版本及推送标签 + - name: Bump version and push tag + id: tag_version + uses: mathieudutour/github-tag-action@v6.2 + with: + github_token: $\{{ secrets.GITHUB_TOKEN }} + + # 更新npm版本 + - name: Updated version + run: | + npm pkg set version=$\{{ steps.tag_version.outputs.new_version }} + git add -A + git commit -m "chore: published tag $\{{ steps.tag_version.outputs.new_tag }}" + + # 构建项目 + - name: Run build + env: + NODE_ENV: production + run: | + pnpm build + {{#if enabledTypedoc}} + pnpm build:doc + {{/if}} + + # 创建Github release + - name: Create a GitHub release + uses: ncipollo/release-action@v1 + with: + tag: $\{{ steps.tag_version.outputs.new_tag }} + name: Release $\{{ steps.tag_version.outputs.new_tag }} + body: $\{{ steps.tag_version.outputs.changelog }} + + # 发布npm包 + - name: Publish + uses: JS-DevTools/npm-publish@v3 + with: + token: $\{{ secrets.NPM_AUTH_TOKEN }} + + # 推送变更至仓库 + - name: Push changes + uses: ad-m/github-push-action@master + with: + github_token: $\{{ secrets.GITHUB_TOKEN }} + branch: $\{{ github.ref }} + + {{#if enabledTypedoc}} + # 部署文档 + - name: Deploy GitHub Pages site + uses: JamesIves/github-pages-deploy-action@v4 + with: + folder: ./docs + {{/if}} \ No newline at end of file diff --git a/templates/utils/.gitignore b/templates/utils/.gitignore new file mode 100644 index 0000000..faf5591 --- /dev/null +++ b/templates/utils/.gitignore @@ -0,0 +1,174 @@ +## Examples +### *.a // 所有以 '.a' 为后缀的文件都屏蔽掉 +### tags // 所有名为tags屏蔽 +### core.* // 所有core开头的文件屏蔽 +### dist/ // 屏蔽dist目录 +### dist/* // 屏蔽dist内所有文件,不屏蔽目录本身 +### /lib // 只屏蔽目录根目录下的lib文件,其他不屏蔽 +### !/readme.md # 不屏蔽readme.md文件 + +# Logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +*.tsbuildinfo + +# Runtime data +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# next.js build output +.next + +# OS X temporary files +.DS_Store + +# IntelliJ IDEA project files; if you want to commit IntelliJ settings, this recipe may be helpful: +# https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +.idea/ +*.iml + +# Rush temporary files +common/deploy/ +common/temp/ +common/autoinstallers/*/.npmrc +**/.rush/temp/ + +# Heft temporary files +.heft + + +# Created by .ignore support plugin (hsz.mobi) + +### Node template +# Logs +pnpm-debug.log* +testem.log + +# Runtime data +pids +.vscode + +# TypeScript v1 declaration files +typings/ +types/ + +.env.local +.env.*.local + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# nuxt.js build output +.nuxt + +# Nuxt generate +# dist + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless + +# IDE / Editor +.idea +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +.history/* + +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +# Service worker +sw.* + +# System Files +Thumbs.db + +# Vim swap files +*.swp + +# misc +# package-lock.json +# yarn.lock +# 建议不排除,否则依赖树内包小版本更新极易引发未知异常 +#pnpm-lock.yaml + +# compiled output +tmp +out-tsc +lib +dist +docs + +# Only exists if Bazel was run +bazel-out + +# profiling files +chrome-profiler-events*.json +speed-measure-plugin*.json + +# documents临时文件 +index.html.js +index.html.vue + +stats.html diff --git a/templates/utils/.prettierignore b/templates/utils/.prettierignore new file mode 100644 index 0000000..bd5535a --- /dev/null +++ b/templates/utils/.prettierignore @@ -0,0 +1 @@ +pnpm-lock.yaml diff --git a/templates/utils/.prettierrc.json b/templates/utils/.prettierrc.json new file mode 100644 index 0000000..9d2bd60 --- /dev/null +++ b/templates/utils/.prettierrc.json @@ -0,0 +1,14 @@ +{ + "printWidth": 120, + "tabWidth": 2, + "useTabs": false, + "semi": true, + "singleQuote": true, + "quoteProps": "as-needed", + "jsxSingleQuote": false, + "trailingComma": "all", + "bracketSpacing": true, + "bracketSameLine": false, + "arrowParens": "always", + "endOfLine": "lf" +} diff --git a/templates/utils/README.md.handlebars b/templates/utils/README.md.handlebars new file mode 100644 index 0000000..6103b46 --- /dev/null +++ b/templates/utils/README.md.handlebars @@ -0,0 +1,104 @@ +# {{projectName}} + +> {{projectDescription}} + +## Getting Started + +### web项目使用 + +npm方式安装: + +`npm install {{projectName}}` + +```typescript +// 自动识别导入esm文件 +import { formatDate } from '{{projectName}}'; +// 全量导入 +import * as allHelpers from '{{projectName}}'; +// 通过别名路径导入esm文件 +import { formatDate } from '{{projectName}}/esm'; +``` + +浏览器script标签安装: + +```html + + + +``` + +### node项目使用 + +npm方式安装: + +`npm install {{projectName}}` + +```typescript +// 自动导入cjs文件 +const { createFile } = require('{{projectName}}'); +// 全量导入 +const { createFile } = require('{{projectName}}'); + +/** 在type: module启用ESM环境下,请参考如下方式 */ +// 通过别名路径导入cjs文件,如果不能识别条件导出,tsconfig可设置 `{ "moduleResolution": "bundler" }` +import { createFile } from '{{projectName}}/cjs'; +// 自动导入默认cjs文件, 当 tsconfig 配置包含 `{ "moduleResolution": "NodeNext" }`时可用 +import { createFile } from '{{projectName}}'; +``` + +## Contributes + +### Install + +`pnpm install` + +### Base commands + +- `pnpm dev` 启用开发模式 +- `pnpm build` 生产构建 +{{#if enabledEslint}} +- `pnpm lint` 代码校验 +{{/if}} +{{#if enabledPrettier}} +- `pnpm format` 代码格式化 +{{/if}} +{{#if enabledJest}} +- `pnpm test` 执行单元测试 +{{/if}} +{{#if enabledTypedoc}} +- `pnpm build:doc` 构建文档 +{{/if}} + +### 添加一个新的工具函数 + +1. 请先确定该函数适用的平台 Web/Node/Common +2. 通用函数请放入 `src/common-modules` +3. Web平台函数放入 `src/web-modules` +4. Node平台函数放入 `src/node-modules` +{{#if enabledTypedoc}} +5. 为函数添加一定的文档描述,如下示例 + +```typescript +// src/web-modules/example.ts + +/** + * @category Tools + */ +export default function example() { + console.log('可指定的category在 src/web.ts 或 src/node.ts 文件顶部声明'); +} +``` + +更多文档注解参考 [TypeDoc](https://typedoc.org/guides/overview/) +{{/if}} + +{{#if enabledGithubActions}} +### Publish library + +> 使用Github actions自动发布依赖提供 secrets.NPM_AUTH_TOKEN 变量 + +1. 变更package.json内的version字段 +2. 提交合并请求至master即可 +{{/if}} \ No newline at end of file diff --git a/templates/utils/commitlint.config.js b/templates/utils/commitlint.config.js new file mode 100644 index 0000000..0616fb9 --- /dev/null +++ b/templates/utils/commitlint.config.js @@ -0,0 +1,3 @@ +export default { + extends: ['@commitlint/config-conventional'], +}; diff --git a/templates/utils/jest.config.cjs b/templates/utils/jest.config.cjs new file mode 100644 index 0000000..70718a9 --- /dev/null +++ b/templates/utils/jest.config.cjs @@ -0,0 +1,23 @@ +module.exports = { + moduleFileExtensions: ['js', 'json', 'ts'], + moduleNameMapper: { + '@/(.*)': '/src/$1', + }, + testMatch: ['/src/**/*.spec.ts'], + transform: { + '^.+\\.tsx?$': ['ts-jest', { tsconfig: 'tsconfig.test.json' }], + }, + collectCoverage: true, + collectCoverageFrom: ['/src/**/*.ts'], + preset: 'ts-jest', + rootDir: '.', + // 单测覆盖率限制 + // coverageThreshold: { + // "global": { + // "branches": 100, + // "functions": 100, + // "lines": 100, + // "statements": 100 + // } + // }, +}; diff --git a/templates/utils/package.json.handlebars b/templates/utils/package.json.handlebars index fd0b8df..9c122b1 100644 --- a/templates/utils/package.json.handlebars +++ b/templates/utils/package.json.handlebars @@ -62,18 +62,18 @@ "build:doc-node": "typedoc src/node.ts --tsconfig tsconfig.node.json --out docs/node --name \"Compass helpers for node platforms\"", {{/if}} {{#if enabledGithooks}} - "prepare": "npx simple-git-hooks", + "prepare": "npx simple-git-hooks", {{/if}} {{#if enabledTypedoc}} {{#if enabledJest}} - "clean": "rimraf dist && rimraf types && rimraf stats.html && rimraf coverage && rimraf docs" + "clean": "rimraf dist && rimraf types && rimraf stats.html && rimraf coverage && rimraf docs" {{else}} - "clean": "rimraf dist && rimraf types && rimraf stats.html && rimraf docs" + "clean": "rimraf dist && rimraf types && rimraf stats.html && rimraf docs" {{/if}} {{else if enabledJest}} - "clean": "rimraf dist && rimraf types && rimraf stats.html && rimraf coverage" + "clean": "rimraf dist && rimraf types && rimraf stats.html && rimraf coverage" {{else}} - "clean": "rimraf dist && rimraf types && rimraf stats.html" + "clean": "rimraf dist && rimraf types && rimraf stats.html" {{/if}} }, {{#if enabledGithooks}} @@ -140,6 +140,7 @@ {{#if enabledJest}} "ts-jest": "^29.1.2", {{/if}} + "tslib": "^2.6.2", {{#if enabledTypedoc}} "typedoc": "^0.25.12", {{/if}} diff --git a/templates/utils/rollup.config.js b/templates/utils/rollup.config.js new file mode 100644 index 0000000..14a21e0 --- /dev/null +++ b/templates/utils/rollup.config.js @@ -0,0 +1,121 @@ +import { builtinModules } from 'module'; +import json from '@rollup/plugin-json'; +import ts from 'rollup-plugin-ts'; +import { nodeResolve } from '@rollup/plugin-node-resolve'; +import commonjs from '@rollup/plugin-commonjs'; +import terser from '@rollup/plugin-terser'; +import cleanup from 'rollup-plugin-cleanup'; +import summary from 'rollup-plugin-summary'; +import { visualizer } from 'rollup-plugin-visualizer'; +import { name } from './package.json' assert { type: 'json' }; + +const IS_PROD = !process.env.ROLLUP_WATCH; + +/** + * @description 获取构建插件 + * @param {Record<'json'|'ts'|'nodeResolve'|'commonjs'|'terser'|'cleanup'|'summary'|'visualizer', object>} [options] + * @param {('json'|'ts'|'nodeResolve'|'commonjs'|'terser'|'cleanup'|'summary'|'visualizer')[]} [ignorePlugins] + * @returns + */ +function getPlugins(options = {}, ignorePlugins = []) { + return [ + !ignorePlugins.includes('json') && json(options.json || undefined), + !ignorePlugins.includes('ts') && ts(options.ts || undefined), + // 如果目标是node环境,需要提供选项{ exportConditions: ["node"] }以支持构建 + // !ignorePlugins.includes('nodeResolve') && nodeResolve(options.nodeResolve || undefined), + !ignorePlugins.includes('commonjs') && commonjs(options.commonjs || undefined), + IS_PROD && !ignorePlugins.includes('terser') && terser(options.terser || undefined), + IS_PROD && !ignorePlugins.includes('cleanup') && cleanup({ comments: 'none', ...(options.cleanup || {}) }), + IS_PROD && + !ignorePlugins.includes('summary') && + summary({ + showGzippedSize: true, + ...(options.summary || {}), + }), + IS_PROD && + !ignorePlugins.includes('visualizer') && + visualizer({ + gzipSize: true, + // template: 'treemap', // network, treemap,sunburst, default: treemap + ...(options.visualizer || {}), + }), + ].filter((item) => !!item); +} + +/** + * @description 获取要排除的外部选项 + * @param {string[]} additionalExternal + * @return {string[]} + */ +function getExternal(additionalExternal = []) { + return [...builtinModules].concat(additionalExternal || []); +} + +/** + * @description 获取输出配置项 + * @param options 文档: https://www.rollupjs.com/guide/big-list-of-options + * @return {Record} + */ +function getOutput(options = {}) { + return { + dir: 'dist', + format: 'es', + chunkFileNames: 'bundle/chunk.[format].[hash].js', + entryFileNames: '[name].[format].js', + sourcemap: IS_PROD, + ...options, + }; +} + +export default [ + // umd + IS_PROD && { + input: 'src/web.ts', + output: getOutput({ + format: 'umd', + file: 'dist/browser.umd.js', + name, // Set your library name. + dir: undefined, + chunkFileNames: undefined, + entryFileNames: undefined, + exports: 'auto', + }), + external: getExternal(), + plugins: getPlugins({ + ts: { + tsconfig: './tsconfig.web.json', + }, + nodeResolve: { browser: true }, + }), + }, + // node + IS_PROD && { + input: 'src/node.ts', + output: getOutput({ + format: 'cjs', + exports: 'auto', + entryFileNames: '[name].js', + }), + external: getExternal(), + plugins: getPlugins({ + ts: { + tsconfig: './tsconfig.node.json', + }, + nodeResolve: { browser: false, exportConditions: ['node'] }, + }), + }, + // esm + { + input: 'src/web.ts', + output: getOutput(), + external: getExternal(), + plugins: getPlugins({ + ts: { + tsconfig: './tsconfig.web.json', + }, + }), + watch: { + include: ['src/**', 'index.html'], + }, + }, +].filter((item) => !!item); diff --git a/templates/utils/src/common-modules/index.ts b/templates/utils/src/common-modules/index.ts new file mode 100644 index 0000000..c6dddd7 --- /dev/null +++ b/templates/utils/src/common-modules/index.ts @@ -0,0 +1,6 @@ +/** + * @description 请在该文件夹下导出可供web或node平台使用的实用程序 + * @module + */ + +export {}; diff --git a/templates/utils/src/interfaces/index.ts b/templates/utils/src/interfaces/index.ts new file mode 100644 index 0000000..0f76cf7 --- /dev/null +++ b/templates/utils/src/interfaces/index.ts @@ -0,0 +1,6 @@ +/** + * @description 请在该文件夹下导出可供外部使用的类型接口 + * @module + */ + +export {}; diff --git a/templates/utils/src/node-modules/index.ts b/templates/utils/src/node-modules/index.ts new file mode 100644 index 0000000..d8f927e --- /dev/null +++ b/templates/utils/src/node-modules/index.ts @@ -0,0 +1,6 @@ +/** + * @description 请在该文件夹下导出仅供node平台使用的实用程序 + * @module + */ + +export {}; diff --git a/templates/utils/src/node.ts b/templates/utils/src/node.ts new file mode 100644 index 0000000..1cd4925 --- /dev/null +++ b/templates/utils/src/node.ts @@ -0,0 +1,8 @@ +/** + * @description 这里是可供Node平台使用的包入口 + * @module + */ + +export * from './common-modules'; +export * from './interfaces'; +export * from './node-modules'; diff --git a/templates/utils/src/web-modules/index.ts b/templates/utils/src/web-modules/index.ts new file mode 100644 index 0000000..2dba4e7 --- /dev/null +++ b/templates/utils/src/web-modules/index.ts @@ -0,0 +1,6 @@ +/** + * @description 请在该文件夹下导出可供Browser或前端ESM使用的实用程序 + * @module + */ + +export {}; diff --git a/templates/utils/src/web.ts b/templates/utils/src/web.ts new file mode 100644 index 0000000..44f0a2f --- /dev/null +++ b/templates/utils/src/web.ts @@ -0,0 +1,8 @@ +/** + * @description 这里是可供Browser或前端esm使用的包入口 + * @module + */ + +export * from './common-modules'; +export * from './interfaces'; +export * from './web-modules'; diff --git a/templates/utils/tsconfig.json.handlebars b/templates/utils/tsconfig.json.handlebars new file mode 100644 index 0000000..981a54e --- /dev/null +++ b/templates/utils/tsconfig.json.handlebars @@ -0,0 +1,31 @@ +{ + "compilerOptions": { + "target": "ES6", + "module": "ESNext", + "lib": ["ESNext"], + "strict": true, + "sourceMap": true, + "declaration": true, + "declarationDir": "types", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "moduleResolution": "bundler", + "outDir": "dist", + "baseUrl": ".", + "paths": { + "@": ["src"], + "@/*": ["src/*"] + }, + "types": [], + "plugins": [{ "transform": "@zerollup/ts-transform-paths" }] + }, + "references": [ + { "path": "./tsconfig.web.json" }, + {{#if enabledJest}} + { "path": "./tsconfig.node.json" }, + { "path": "./tsconfig.test.json" } + {{else}} + { "path": "./tsconfig.node.json" } + {{/if}} + ] +} \ No newline at end of file diff --git a/templates/utils/tsconfig.node.json.handlebars b/templates/utils/tsconfig.node.json.handlebars new file mode 100644 index 0000000..018c94b --- /dev/null +++ b/templates/utils/tsconfig.node.json.handlebars @@ -0,0 +1,28 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "composite": true, + "types": ["node"] + }, + "include": [ + "src/node.ts", + "src/node-modules/**/*.ts", + "src/common-modules/**/*.ts", + "src/interfaces/**/*.ts", + {{#if enabledEslint}} + ".eslintrc.cjs", + {{/if}} + {{#if enabledJest}} + "jest.config.cjs", + {{/if}} + {{#if enabledCommitlint}} + "commitlint.config.js", + {{/if}} + "rollup.config.js" + ], + {{#if enabledJest}} + "exclude": ["src/**/*.spec.ts"] + {{else}} + "exclude": [] + {{/if}} +} \ No newline at end of file diff --git a/templates/utils/tsconfig.test.json b/templates/utils/tsconfig.test.json new file mode 100644 index 0000000..44acafa --- /dev/null +++ b/templates/utils/tsconfig.test.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "composite": true, + "types": ["node", "jest"], + "baseUrl": ".", + "paths": { + "@": ["src"], + "@/*": ["src/*"] + } + }, + "include": ["src/**/*.spec.ts"] +} diff --git a/templates/utils/tsconfig.web.json.handlebars b/templates/utils/tsconfig.web.json.handlebars new file mode 100644 index 0000000..34b317b --- /dev/null +++ b/templates/utils/tsconfig.web.json.handlebars @@ -0,0 +1,13 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "composite": true, + "lib": ["ESNext", "DOM"] + }, + "include": ["src/web.ts", "src/web-modules/**/*.ts", "src/common-modules/**/*.ts", "src/interfaces/**/*.ts"], + {{#if enabledJest}} + "exclude": ["src/**/*.spec.ts"] + {{else}} + "exclude": [] + {{/if}} +} \ No newline at end of file