diff --git a/README.md b/README.md index 6b1df94..e3e1ae1 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,23 @@ `compass update` Cli更新检查 -`compass create` 创建项目, `compass create --help` 可以获得更多可选项说明, 支持创建的项目如下: +`compass pull` 通过拉取模板来创建项目, `compass pull --help` 可以获得更多可选项说明,支持拉取的模板如下: + +| Name | Description | +| :-------------------------------------------------------------------: | :---------------------: | +| [utils](https://github.com/Aiden-FE/compass-template/tree/temp/utils) | Utils实用程序工具库模板 | + +`compass plugin` 向项目添加或删除插件, `compass plugin --help` 可以获得更多可选项说明,支持创建的插件如下: + +| Name | Description | +| :---------: | :---------------------------------------------------------------------------------: | +| Githooks | 使用SimpleGitHooks基于githooks对项目添加自动化任务 | +| Prettier | Prettier 代码格式化 | +| eslint | Eslint 基于Airbnb规范对代码进行检查 | +| prettyquick | PrettyQuick 在Commit前仅对变更文件进行快速格式化,该插件依赖于githooks及prettier插件 | +| commitlint | Commitlint 提交信息格式校验,该插件依赖于githooks插件 | + +`compass create` 创建各官方标准项目, `compass create --help` 可以获得更多可选项说明, 支持创建的项目如下: | Name | Description | | :------: | :----------------: | @@ -22,9 +38,6 @@ | Uniapp | Uniapp 跨端项目 | | Electron | Electron桌面端项目 | | Nest | Nest后端项目 | -| Utils | 实用程序工具库 | - -`compass plugin` 向项目添加或删除插件, `compass plugin --help` 可以获得更多可选项说明 ## Contributes diff --git a/package.json b/package.json index bbec1ad..e9cf0f3 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^15.2.3", "@rollup/plugin-terser": "^0.4.4", + "@types/adm-zip": "^0.5.5", "@types/figlet": "^1.5.8", "@types/inquirer": "^9.0.7", "@types/node": "^20.11.27", @@ -74,6 +75,7 @@ "@compass-aiden/helpers": "^0.2.0", "@compass-aiden/telegram": "^2.1.0", "@inquirer/prompts": "^4.3.0", + "adm-zip": "^0.5.12", "axios": "^1.6.7", "chalk": "^5.3.0", "commander": "^12.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 31f6e47..15d963e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ dependencies: '@inquirer/prompts': specifier: ^4.3.0 version: 4.3.0 + adm-zip: + specifier: ^0.5.12 + version: 0.5.12 axios: specifier: ^1.6.7 version: 1.6.7 @@ -58,6 +61,9 @@ devDependencies: '@rollup/plugin-terser': specifier: ^0.4.4 version: 0.4.4(rollup@4.13.0) + '@types/adm-zip': + specifier: ^0.5.5 + version: 0.5.5 '@types/figlet': specifier: ^1.5.8 version: 1.5.8 @@ -807,6 +813,12 @@ packages: dev: true optional: true + /@types/adm-zip@0.5.5: + resolution: {integrity: sha512-YCGstVMjc4LTY5uK9/obvxBya93axZOVOyf2GSUulADzmLhYE45u2nAssCs/fWBs1Ifq5Vat75JTPwd5XZoPJw==} + dependencies: + '@types/node': 20.11.27 + dev: true + /@types/conventional-commits-parser@5.0.0: resolution: {integrity: sha512-loB369iXNmAZglwWATL+WRe+CRMmmBPtpolYzIebFaX4YA3x+BEfLqhUAV9WanycKI3TG1IMr5bMJDajDKLlUQ==} dependencies: @@ -1058,6 +1070,11 @@ packages: hasBin: true dev: true + /adm-zip@0.5.12: + resolution: {integrity: sha512-6TVU49mK6KZb4qG6xWaaM4C7sA/sgUMLy/JYMOzkcp3BvVLpW0fXDFQiIzAuxFCt/2+xD7fNIiPFAoLZPhVNLQ==} + engines: {node: '>=6.0'} + dev: false + /ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} dependencies: diff --git a/src/commands/create.cmd.ts b/src/commands/create.cmd.ts index e4d41d8..c111869 100644 --- a/src/commands/create.cmd.ts +++ b/src/commands/create.cmd.ts @@ -9,23 +9,12 @@ import { createUniapp, createVue, selectPkgManager, - createUtils, createAngular, } from '@/utils'; import { PkgManager } from '@/interfaces'; interface CommandOptions { - projectType?: - | 'turboMonorepo' - | 'uniapp' - | 'vue' - | 'react' - | 'electron' - | 'nest' - | 'next' - | 'utils' - | 'angular' - | string; + projectType?: 'turboMonorepo' | 'uniapp' | 'vue' | 'react' | 'electron' | 'nest' | 'next' | 'angular' | string; pkgManager?: PkgManager; } @@ -39,10 +28,10 @@ interface CommandOptions { export default (program: Command) => { program .command('create') - .description('快速创建项目') + .description('快速创建官方标准项目') .option( '-T, --project-type [projectType]', - '需要创建的项目类型\n\t\t\t\t\t- vue\tVue项目\n\t\t\t\t\t- react\tReact项目\n\t\t\t\t\t- angular\tAngular项目\n\t\t\t\t\t- next\tNext SSR项目\n\t\t\t\t\t- turboMonorepo\tTurbo monorepo项目\n\t\t\t\t\t- uniapp\tUniapp跨端项目\n\t\t\t\t\t- electron\tElectron桌面端项目\n\t\t\t\t\t- nest\tNest后端项目\n\t\t\t\t\t- utils\t实用程序工具库', + '需要创建的项目类型\n\t\t\t\t\t- vue\tVue项目\n\t\t\t\t\t- react\tReact项目\n\t\t\t\t\t- angular\tAngular项目\n\t\t\t\t\t- next\tNext SSR项目\n\t\t\t\t\t- turboMonorepo\tTurbo monorepo项目\n\t\t\t\t\t- uniapp\tUniapp跨端项目\n\t\t\t\t\t- electron\tElectron桌面端项目\n\t\t\t\t\t- nest\tNest后端项目', ) .option('-M, --pkg-manager [pkgManager]', '指定npm管理器. npm,yarn,pnpm') .action(async (options: CommandOptions) => { @@ -86,10 +75,6 @@ export default (program: Command) => { name: 'Nest 后端项目', value: 'nest', }, - { - name: 'Utils 实用程序库', - value: 'utils', - }, ], }, ]); @@ -115,9 +100,6 @@ export default (program: Command) => { if (projectType === 'next') { await createNext(); } - if (projectType === 'utils') { - await createUtils(); - } if (projectType === 'angular') { await createAngular(); } diff --git a/src/commands/index.ts b/src/commands/index.ts index 9dfc377..0fa78fa 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -1,3 +1,4 @@ export { default as updateCommand } from './update.cmd'; export { default as createCommand } from './create.cmd'; export { default as pluginCommand } from './plugin.cmd'; +export { default as pullCommand } from './pull.cmd'; diff --git a/src/commands/pull.cmd.ts b/src/commands/pull.cmd.ts new file mode 100644 index 0000000..0f77944 --- /dev/null +++ b/src/commands/pull.cmd.ts @@ -0,0 +1,53 @@ +import { Command } from 'commander'; +import { input, select } from '@inquirer/prompts'; +import { join, dirname } from 'path'; +import { isFileOrFolderExists } from '@compass-aiden/helpers/cjs'; +import { SELECT_TEMPLATE } from '@/constants'; +import { Logger, pullUtilsTemplate } from '@/utils'; + +export default (program: Command) => { + program + .command('pull') + .description('通过拉取模板来创建项目') + .option('-N, --name [name]', '项目路径, 如: new-project, ./temp/new-project') + .option('-T, --template-type [tempType]', '需要拉取的模板类型\n\t\t\t\t\t- utils\tUtils实用程序工具库模板') + .action(async (options) => { + const tempType = + options.templateType || + (await select({ + message: '请选择要拉取的模板类型', + choices: SELECT_TEMPLATE, + })); + const tempConfig = SELECT_TEMPLATE.find((item) => item.value === tempType); + if (!tempConfig) { + throw new Error('Not found template'); + } + + let projectPath = + options.name || + (await input({ + message: '请输入项目路径', + default: './new-project', + })); + + projectPath = projectPath.startsWith('/') ? projectPath : join(process.cwd(), projectPath); + const projectName = projectPath.replace(join(dirname(projectPath), './'), ''); + + if (isFileOrFolderExists(projectPath)) { + Logger.error('❌ 目标路径已经存在'); + return; + } + + if (tempType === 'utils') { + await pullUtilsTemplate({ + projectPath, + templateData: await tempConfig.getTemplateVars({ + projectName, + }), + }); + return; + } + + Logger.error('❌ 暂不支持的模板类型'); + }); +}; diff --git a/src/constants/index.ts b/src/constants/index.ts index 7a0b8aa..475b166 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -1,5 +1,6 @@ +export * from './templates'; + /** ESlint 插件 */ -// eslint-disable-next-line import/prefer-default-export export const ESLINT_PLUGINS = [ { name: 'Next TS', diff --git a/src/constants/templates.ts b/src/constants/templates.ts new file mode 100644 index 0000000..4218708 --- /dev/null +++ b/src/constants/templates.ts @@ -0,0 +1,69 @@ +import { input, confirm } from '@inquirer/prompts'; + +/* eslint-disable import/prefer-default-export */ +export const SELECT_TEMPLATE = [ + { + name: '自定义模板', + value: 'custom', + getTemplateVars: async (options?: any) => options || {}, + }, + { + name: 'Utils 实用程序工具库模板', + value: 'utils', + getTemplateVars: async (options?: any) => { + const result = { + projectName: await input({ + message: '请输入项目名称', + default: options.projectName, + }), + projectDescription: + options?.projectDescription || + (await input({ + message: '请输入项目描述', + })), + enabledEslint: + options?.enabledEslint || + (await confirm({ + message: '是否启用 eslint 代码检查插件', + default: true, + })), + enabledPrettier: + options?.enabledEslint || + (await confirm({ + message: '是否启用 prettier 代码格式化插件', + default: true, + })), + enabledJest: + options?.enabledJest || + (await confirm({ + message: '是否启用 jest 单测插件', + default: true, + })), + enabledTypedoc: + options?.enabledTypedoc || + (await confirm({ + message: '是否启用 typedoc 生成文档', + default: true, + })), + enabledPrettyQuick: + options?.enabledPrettyQuick || + (await confirm({ + message: '是否启用 pretty-quick 插件,代码提交前快速格式化变更文件.依赖enabledGithooks开启', + default: true, + })), + enabledCommitlint: + options?.enabledPrettyQuick || + (await confirm({ + message: '是否启用 commitlint 插件,代码提交前对提交信息进行校验.依赖enabledGithooks开启', + default: true, + })), + enabledGithooks: false, + }; + + return { + ...result, + enabledGithooks: result.enabledPrettyQuick || result.enabledCommitlint || false, + }; + }, + }, +]; diff --git a/src/http/api.ts b/src/http/api.ts index b158b08..c98cda2 100644 --- a/src/http/api.ts +++ b/src/http/api.ts @@ -1,4 +1,9 @@ -import Telegram, { HttpTelegramResInterceptor, HttpTelegramErrorInterceptor } from '@compass-aiden/telegram'; +import { Logger } from '@/utils'; +import Telegram, { + HttpTelegramResInterceptor, + HttpTelegramErrorInterceptor, + HttpTelegramReqInterceptor, +} from '@compass-aiden/telegram'; const defaultResInterceptor: HttpTelegramResInterceptor = (data, res) => { if (res.status >= 200 && res.status < 300) { @@ -11,12 +16,26 @@ const defaultErrorInterceptor: HttpTelegramErrorInterceptor = (error) => { throw new Error(`[${error.response?.status || 'Api Error'}]: ${error.message || error}`); }; -const Api = new Telegram() +const defaultRequestInterceptor: HttpTelegramReqInterceptor = (req) => { + if (req.customMeta?.debug) { + Logger.info('Request debug:'); + Logger.log(req); + } + return req; +}; + +const Api = new Telegram({ + interceptors: { + response: defaultResInterceptor, + responseError: defaultErrorInterceptor, + }, +}) .register('github', { baseURL: 'https://api.github.com', interceptors: { response: defaultResInterceptor, responseError: defaultErrorInterceptor, + request: defaultRequestInterceptor, }, }) .register('npm', { diff --git a/src/http/github.ts b/src/http/github.ts index 12eb727..bca83e9 100644 --- a/src/http/github.ts +++ b/src/http/github.ts @@ -1,12 +1,11 @@ import Api from './api'; -import { RepositoryInfo, GithubReleaseInfo } from './interfaces'; +import { RepositoryInfo, GithubReleaseInfo, ContentOfGithubRepo } from './interfaces'; /** * @description 获取存储库已发布版本列表 * @param repoInfo * @param token */ -// eslint-disable-next-line import/prefer-default-export export function getRepoReleasesFromGithub(repoInfo: Pick, token?: string) { return Api.chain() .domain('github') @@ -21,3 +20,49 @@ export function getRepoReleasesFromGithub(repoInfo: Pick(); } + +/** + * @description 获取存储库 + * @param repoInfo + * @param token + */ +export function getRepoFromGithub(repoInfo: RepositoryInfo, token?: string) { + return Api.chain() + .domain('github') + .get(`/repos/${repoInfo.author}/${repoInfo.repository}/zipball/${repoInfo.branch || ''}`) + .path('author', repoInfo.author) + .path('repository', repoInfo.repository) + .path('branch', repoInfo.branch || '') + .config({ + headers: { + accept: 'application/vnd.github+json', + Authorization: token ? `Bearer ${token}` : undefined, + }, + responseType: 'arraybuffer', + timeout: 1000 * 60, + }) + .request(); +} + +/** + * @description 获取仓库内容 + * @param repoInfo + */ +export function getRepoContentsFromGithub(repoInfo: RepositoryInfo, token?: string) { + return Api.chain() + .domain('github') + .get('/repos/:author/:repository/contents/:repoPath') + .path('author', repoInfo.author) + .path('repository', repoInfo.repository) + .path('repoPath', repoInfo.repoPath || '') + .searchParams({ + ref: repoInfo.branch, + }) + .config({ + headers: { + accept: 'application/vnd.github+json', + Authorization: token ? `Bearer ${token}` : undefined, + }, + }) + .request(); +} diff --git a/src/http/index.ts b/src/http/index.ts index 9ef4b2c..bdea3d0 100644 --- a/src/http/index.ts +++ b/src/http/index.ts @@ -1,2 +1,13 @@ +import Api from './api'; + export * from './github'; export * from './npm'; + +export function getFile(url: string, headers?: Record) { + return Api.chain() + .get(url) + .config({ + headers, + }) + .request(); +} diff --git a/src/http/interfaces.ts b/src/http/interfaces.ts index 9e24a44..f4aad0e 100644 --- a/src/http/interfaces.ts +++ b/src/http/interfaces.ts @@ -13,6 +13,9 @@ export interface GithubReleaseInfo { prerelease: boolean; created_at: string; published_at: string; + type: string; + path: string; + download_url: string; } export interface RepositoryInfo { @@ -25,3 +28,9 @@ export interface RepositoryInfo { /** 仓库子路径 */ repoPath?: string; } + +export type ContentOfGithubRepo = { + type: 'dir' | 'file'; + path: string; + download_url?: string; +}; diff --git a/src/interfaces/index.ts b/src/interfaces/index.ts index 363bebc..e058dd3 100644 --- a/src/interfaces/index.ts +++ b/src/interfaces/index.ts @@ -1,2 +1,9 @@ /** npm包管理器 */ export type PkgManager = 'npm' | 'yarn' | 'pnpm'; + +export type RepositoryInfo = { + author: string; + repository: string; + branch?: string; + repoPath?: string; +}; diff --git a/src/utils/create-utils.ts b/src/utils/create-utils.ts deleted file mode 100644 index bc90e3b..0000000 --- a/src/utils/create-utils.ts +++ /dev/null @@ -1,136 +0,0 @@ -import { fileURLToPath } from 'url'; -import { join, dirname } from 'path'; -import inquirer from 'inquirer'; -import ora from 'ora'; -import chalk from 'chalk'; -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); -// eslint-disable-next-line @typescript-eslint/naming-convention, no-underscore-dangle -const __dirname = dirname(__filename); -const utilsTempBasePath = join(__dirname, '../templates/utils'); - -export default async function createUtils() { - /* eslint-disable prefer-const */ - let { - projectPath, - projectDescription, - enabledEslint, - enabledPrettier, - enabledJest, - enabledTypedoc, - enabledPrettyQuick, - enabledCommitlint, - enabledGithubActions, - /* eslint-enable prefer-const */ - } = await inquirer.prompt([ - { - type: 'input', - name: 'projectPath', - message: '请指定项目路径', - default: './new-project', - }, - { - type: 'input', - name: 'projectDescription', - message: '[可选]请输入项目描述', - default: '', - }, - { - type: 'confirm', - name: 'enabledEslint', - message: '是否启用Eslint代码检查', - defaut: true, - }, - { - type: 'confirm', - name: 'enabledPrettier', - message: '是否启用Prettier代码检查', - defaut: true, - }, - { - type: 'confirm', - name: 'enabledJest', - message: '是否启用Jest单元测试', - defaut: true, - }, - { - type: 'confirm', - name: 'enabledTypedoc', - message: '是否启用Typedoc构建文档', - defaut: true, - }, - { - type: 'confirm', - name: 'enabledPrettyQuick', - message: '是否启用pretty-quick在代码提交前自动格式化变更文件', - defaut: true, - }, - { - type: 'confirm', - name: 'enabledCommitlint', - message: '是否启用Commitlint在代码提交时校验提交信息', - defaut: true, - }, - { - type: 'confirm', - name: 'enabledGithubActions', - message: '是否启用Github actions CICD执行自动化任务', - defaut: true, - }, - ]); - const loading = ora(); - loading.start(chalk.cyan('开始创建项目文件\n')); - if (isFileOrFolderExists(join(process.cwd(), projectPath))) { - loading.fail(chalk.red('目标路径已经存在')); - return; - } - const enabledGithooks = enabledPrettyQuick || enabledCommitlint; - if (enabledPrettyQuick) { - enabledPrettier = true; - } - const pathArr = projectPath.split('/'); - const projectName = pathArr.pop(); - await createFolder(projectPath, {}); - 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, - enabledJest, - enabledTypedoc, - enabledPrettyQuick, - enabledCommitlint, - enabledGithooks, - projectName, - enabledGithubActions, - }, - ); - copyFolderSync(join(utilsTempBasePath, 'src'), join(projectPath, 'src')); - loading.succeed(chalk.green('创建完成')); -} diff --git a/src/utils/delete-folder-sync.ts b/src/utils/delete-folder-sync.ts new file mode 100644 index 0000000..ad504da --- /dev/null +++ b/src/utils/delete-folder-sync.ts @@ -0,0 +1,25 @@ +import { existsSync, lstatSync, readdirSync, rmdirSync, unlinkSync } from 'fs'; +import { join } from 'path'; + +export default function deleteFoldersSync(folderPaths: string | string[]) { + const targetPath = Array.isArray(folderPaths) ? folderPaths : [folderPaths]; + + targetPath.forEach((folderPath) => { + if (existsSync(folderPath)) { + readdirSync(folderPath).forEach((file) => { + const curPath = join(folderPath, file); + + if (lstatSync(curPath).isDirectory()) { + // 递归删除子文件夹 + deleteFoldersSync(curPath); + } else { + // 删除文件 + unlinkSync(curPath); + } + }); + + // 删除空文件夹 + rmdirSync(folderPath); + } + }); +} diff --git a/src/utils/download-repo-from-github.ts b/src/utils/download-repo-from-github.ts new file mode 100644 index 0000000..6bbc4d3 --- /dev/null +++ b/src/utils/download-repo-from-github.ts @@ -0,0 +1,140 @@ +import AdmZip from 'adm-zip'; +import fs from 'fs'; +import path, { join } from 'path'; +import { createFolder } from '@compass-aiden/helpers/cjs'; +import { RepositoryInfo } from '@/interfaces'; +import { getFile, getRepoReleasesFromGithub, getRepoFromGithub } from '@/http'; +import { Logger } from '@/utils'; + +function downloadFiles(promises: Promise<{ path: string; data: any }>[], basePath: string, isSingleFile?: boolean) { + const admZip = new AdmZip(); + return Promise.all(promises).then(async (result) => { + const files = result.filter((r) => !!r); + if (files.length !== result.length) { + Logger.warn(`部分文件获取失败,可能是与 raw.githubusercontent.com 的连接不畅, + 您可选择如下方式之一进行重试 + 1. hosts内调整raw.githubusercontent.com与实际IP的对应关系 + 2. 指定-T或--token参数,提供授权信息 + 3. 不使用特定路径或文件拉取,直接获取仓库本身,该方式较为稳定`); + } + if (!files.length) { + Logger.error('未能获取到任何文件'); + throw new Error('未能获取到任何文件'); + } + files.forEach((file) => { + admZip.addFile(isSingleFile ? file.path : file.path.replace(basePath, '.'), file.data); + }); + admZip.writeZip('temp.zip'); + }); +} + +async function mapFileAndDirectory({ + dirs, + repoInfo, + promises, + basePath, + token, + isNotInit, +}: { + dirs: string[]; + promises: Promise[]; + basePath: string; + repoInfo: RepositoryInfo; + token?: string; + isNotInit?: boolean; +}) { + return getRepoReleasesFromGithub( + { + author: repoInfo.author, + repository: repoInfo.repository, + }, + token, + ).then(async (result) => { + const data = Array.isArray(result) ? result : [result]; + const isSingleFile = !isNotInit && !Array.isArray(result); + data.forEach((content) => { + if (content.type === 'dir') { + dirs.push(content.path); + } else if (content.download_url) { + promises.push( + new Promise((resolve) => { + getFile( + content.download_url as string, + token + ? { + Authorization: `Bearer ${token}`, + } + : undefined, + ) + .then((d) => + resolve({ + path: content.path, + data: d, + }), + ) + .catch(() => resolve(false)); + }), + ); + } + }); + + if (dirs.length) { + await mapFileAndDirectory({ + dirs, + repoInfo, + promises, + basePath, + token, + isNotInit: true, + }); + } else { + await downloadFiles(promises, basePath, isSingleFile); + } + }); +} + +function downloadFilesFromGithub(repoInfo: RepositoryInfo, token?: string) { + const dirs = []; + const promises: Promise[] = []; + + dirs.push(repoInfo.repoPath as string); + return mapFileAndDirectory({ + dirs, + promises, + repoInfo, + basePath: repoInfo.repoPath as string, + token, + }); +} + +/** + * @description 下载存储库 + * @param repoInfo + * @param output + */ +export default async function downloadRepoFromGithub(repoInfo: RepositoryInfo, output = './', token?: string) { + try { + await createFolder(output); + const zipPath = join(output, 'temp.zip'); + if (repoInfo.repoPath) { + await downloadFilesFromGithub(repoInfo, token); + const tempZip = new AdmZip(zipPath); + tempZip.extractAllTo(output, true); + fs.rmSync(zipPath); + } else { + const result = await getRepoFromGithub(repoInfo, token); + fs.writeFileSync(zipPath, result); + // fs.writeFileSync('temp.zip', Buffer.from(result, 'binary')); + const tempZip = new AdmZip(zipPath); + const entryFile = tempZip.getEntries()[0]; + tempZip.extractAllTo(output, true); + const unZipPath = path.join(output, entryFile.entryName); + fs.cpSync(unZipPath, output, { recursive: true }); + fs.rmSync(zipPath); + fs.rmSync(unZipPath, { recursive: true }); + } + } catch (err) { + Logger.error(err); + fs.unlinkSync(output); + } +} diff --git a/src/utils/get-file-paths-in-folder.ts b/src/utils/get-file-paths-in-folder.ts new file mode 100644 index 0000000..abeeeb6 --- /dev/null +++ b/src/utils/get-file-paths-in-folder.ts @@ -0,0 +1,27 @@ +import { readdirSync, statSync } from 'fs'; +import { join } from 'path'; + +export default function getFilePathsInFolder(folderPath: string) { + try { + const files = readdirSync(folderPath); + let filePaths: string[] = []; + + files.forEach((file) => { + const filePath = join(folderPath, file); + const stats = statSync(filePath); + + if (stats.isFile()) { + // 是文件,将文件路径添加到结果数组中 + filePaths.push(filePath); + } else if (stats.isDirectory()) { + // 是目录,递归调用函数获取子目录中的文件路径 + const subDirectoryPaths = getFilePathsInFolder(filePath); + filePaths = filePaths.concat(subDirectoryPaths); + } + }); + + return filePaths; + } catch { + return []; + } +} diff --git a/src/utils/index.ts b/src/utils/index.ts index 698494a..19b3663 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -7,13 +7,15 @@ export { default as createReact } from './create-react'; 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 createAngular } from './create-angular'; // tools export { default as batchCompileTemplates } from './batch-compile-templates'; export { default as Logger } from './logger'; export { default as getLibraryVersionFromNpmRegisty } from './get-library-version-from-npm-registy'; +export { default as downloadRepoFromGithub } from './download-repo-from-github'; +export { default as getFilePathsInFolder } from './get-file-paths-in-folder'; +export { default as deleteFoldersSync } from './delete-folder-sync'; export * from './delete-files-sync'; // plugin utils @@ -22,3 +24,6 @@ export * from './prettier.plugin'; export * from './prettyquick.plugin'; export * from './commitlint.plugin'; export * from './eslint.plugin'; + +// pull templates +export { default as pullUtilsTemplate } from './pull-utils.template'; diff --git a/src/utils/pull-utils.template.ts b/src/utils/pull-utils.template.ts new file mode 100644 index 0000000..fd69f6d --- /dev/null +++ b/src/utils/pull-utils.template.ts @@ -0,0 +1,61 @@ +import chalk from 'chalk'; +import { join } from 'path'; +import Logger from './logger'; +import downloadRepoFromGithub from './download-repo-from-github'; +import getFilePathsInFolder from './get-file-paths-in-folder'; +import batchCompileTemplates from './batch-compile-templates'; +import deleteFoldersSync from './delete-folder-sync'; + +interface UtilsTempProps { + projectPath?: string; + templateData?: Record; +} + +export default async function pullUtilsTemplate(options?: UtilsTempProps) { + const { projectPath, templateData } = { + templateData: {}, + projectPath: './new-project', + ...options, + }; + const loading = Logger.createLoading(); + loading.start(chalk.cyan('开始拉取目标模板')); + const tempFolderPath = join(projectPath, 'temp'); + await downloadRepoFromGithub( + { + author: 'Aiden-FE', + repository: 'compass-template', + branch: 'temp/utils', + }, + tempFolderPath, + ); + const tempFiles = getFilePathsInFolder(tempFolderPath); + const ignoreFiles: string[] = []; + if (!templateData.enabledJest) { + ignoreFiles.push('tsconfig.test.json', 'jest.config.cjs'); + } + if (!templateData.enabledCommitlint) { + ignoreFiles.push('commitlint.config.js'); + } + if (!templateData.enabledPrettier) { + ignoreFiles.push('.prettierrc.json', '.prettierignore'); + } + if (!templateData.enabledEslint) { + ignoreFiles.push('.eslintrc.cjs.handlebars'); + } + if (!templateData.enabledGithubActions) { + ignoreFiles.push( + '.github/workflows/lint-and-test.yml.handlebars', + '.github/workflows/publish-and-deploy.yml.handlebars', + ); + } + await batchCompileTemplates( + tempFiles + .map((fp) => { + return [fp, join(projectPath, fp.replace(tempFolderPath, '')).replace('.handlebars', '')] as [string, string]; + }) + .filter((item) => !ignoreFiles.some((f) => item[0].endsWith(f))), + templateData, + ); + deleteFoldersSync(tempFolderPath); + loading.succeed(chalk.green('模板拉取完成')); +} diff --git a/templates/utils/.eslintrc.cjs.handlebars b/templates/utils/.eslintrc.cjs.handlebars deleted file mode 100644 index b74c92d..0000000 --- a/templates/utils/.eslintrc.cjs.handlebars +++ /dev/null @@ -1,13 +0,0 @@ -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 deleted file mode 100644 index 8d7c0f2..0000000 --- a/templates/utils/.github/workflows/lint-and-test.yml.handlebars +++ /dev/null @@ -1,59 +0,0 @@ -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 deleted file mode 100644 index cd7b429..0000000 --- a/templates/utils/.github/workflows/publish-and-deploy.yml.handlebars +++ /dev/null @@ -1,110 +0,0 @@ -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 deleted file mode 100644 index faf5591..0000000 --- a/templates/utils/.gitignore +++ /dev/null @@ -1,174 +0,0 @@ -## 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 deleted file mode 100644 index bd5535a..0000000 --- a/templates/utils/.prettierignore +++ /dev/null @@ -1 +0,0 @@ -pnpm-lock.yaml diff --git a/templates/utils/.prettierrc.json b/templates/utils/.prettierrc.json deleted file mode 100644 index 9d2bd60..0000000 --- a/templates/utils/.prettierrc.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "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 deleted file mode 100644 index 6103b46..0000000 --- a/templates/utils/README.md.handlebars +++ /dev/null @@ -1,104 +0,0 @@ -# {{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 deleted file mode 100644 index 0616fb9..0000000 --- a/templates/utils/commitlint.config.js +++ /dev/null @@ -1,3 +0,0 @@ -export default { - extends: ['@commitlint/config-conventional'], -}; diff --git a/templates/utils/jest.config.cjs b/templates/utils/jest.config.cjs deleted file mode 100644 index 70718a9..0000000 --- a/templates/utils/jest.config.cjs +++ /dev/null @@ -1,23 +0,0 @@ -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 deleted file mode 100644 index 9c122b1..0000000 --- a/templates/utils/package.json.handlebars +++ /dev/null @@ -1,149 +0,0 @@ -{ - "name": "{{projectName}}", - "type": "module", - "version": "0.0.1", - "description": "{{projectDescription}}", - "main": "dist/web.es.js", - "typings": "types/web.es.d.ts", - "jsdelivr": "dist/browser.umd.js", - "unpkg": "dist/browser.umd.js", - "exports": { - ".": { - "types": { - "require": "./types/node.d.ts", - "default": "./types/web.es.d.ts" - }, - "require": "./dist/node.js", - "default": "./dist/web.es.js" - }, - "./cjs": { - "types": "./types/node.d.ts", - "default": "./dist/node.js" - }, - "./esm": { - "types": "./types/web.es.d.ts", - "default": "./dist/web.es.js" - }, - "./dist/*": "./dist/*", - "./types/*": "./types/*" - }, - "files": [ - "dist", - "types" - ], - "author": "", - "repository": "", - "license": "MIT", - "publishConfig": { - "registry": "https://registry.npmjs.org/", - "access": "public" - }, - "keywords": [ - "utils", - "helpers", - "helper", - "tools" - ], - "scripts": { - "dev": "rollup -w -c rollup.config.js", - "build": "npm run clean && rollup -c rollup.config.js", - {{#if enabledEslint}} - "lint": "eslint src --ext .ts,.js --fix", - {{/if}} - {{#if enabledPrettier}} - "format": "prettier --write src", - {{/if}} - {{#if enabledJest}} - "test": "jest --coverage", - {{/if}} - {{#if enabledTypedoc}} - "build:doc": "npm run build:doc-web && npm run build:doc-node", - "build:doc-web": "typedoc src/web.ts --tsconfig tsconfig.web.json --out docs/web --name \"Compass helpers for web platforms\"", - "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", - {{/if}} - {{#if enabledTypedoc}} - {{#if enabledJest}} - "clean": "rimraf dist && rimraf types && rimraf stats.html && rimraf coverage && rimraf docs" - {{else}} - "clean": "rimraf dist && rimraf types && rimraf stats.html && rimraf docs" - {{/if}} - {{else if enabledJest}} - "clean": "rimraf dist && rimraf types && rimraf stats.html && rimraf coverage" - {{else}} - "clean": "rimraf dist && rimraf types && rimraf stats.html" - {{/if}} - }, - {{#if enabledGithooks}} - "simple-git-hooks": { - {{#if enabledPrettyQuick}} - {{#if enabledCommitlint}} - "pre-commit": "npx pretty-quick --staged", - {{else}} - "pre-commit": "npx pretty-quick --staged" - {{/if}} - {{/if}} - {{#if enabledCommitlint}} - "commit-msg": "npx --no -- commitlint --edit $1" - {{/if}} - }, - {{/if}} - "devDependencies": { - {{#if enabledCommitlint}} - "@commitlint/cli": "^19.1.0", - "@commitlint/config-conventional": "^19.1.0", - {{/if}} - {{#if enabledEslint}} - "@compass-aiden/eslint-config": "^1.6.3", - {{/if}} - "@rollup/plugin-commonjs": "^25.0.7", - "@rollup/plugin-json": "^6.1.0", - "@rollup/plugin-node-resolve": "^15.2.3", - "@rollup/plugin-terser": "^0.4.4", - {{#if enabledJest}} - "@types/jest": "^29.5.12", - {{/if}} - "@types/node": "^20.11.26", - {{#if enabledEslint}} - "@typescript-eslint/eslint-plugin": "^7.2.0", - "@typescript-eslint/parser": "^7.2.0", - {{/if}} - "@zerollup/ts-transform-paths": "^1.7.18", - {{#if enabledEslint}} - "eslint": "^8.57.0", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-config-airbnb-typescript": "^18.0.0", - "eslint-config-prettier": "^9.1.0", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-prettier": "^5.1.3", - {{/if}} - {{#if enabledJest}} - "jest": "^29.7.0", - {{/if}} - {{#if enabledPrettier}} - "prettier": "^3.2.5", - {{/if}} - {{#if enabledPrettyQuick}} - "pretty-quick": "^4.0.0", - {{/if}} - "rimraf": "^5.0.5", - "rollup": "^4.12.1", - "rollup-plugin-cleanup": "^3.2.1", - "rollup-plugin-summary": "^2.0.0", - "rollup-plugin-ts": "^3.4.5", - "rollup-plugin-visualizer": "^5.12.0", - {{#if enabledGithooks}} - "simple-git-hooks": "^2.10.0", - {{/if}} - {{#if enabledJest}} - "ts-jest": "^29.1.2", - {{/if}} - "tslib": "^2.6.2", - {{#if enabledTypedoc}} - "typedoc": "^0.25.12", - {{/if}} - "typescript": "^5.4.2" - } -} \ No newline at end of file diff --git a/templates/utils/rollup.config.js b/templates/utils/rollup.config.js deleted file mode 100644 index 14a21e0..0000000 --- a/templates/utils/rollup.config.js +++ /dev/null @@ -1,121 +0,0 @@ -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 deleted file mode 100644 index c6dddd7..0000000 --- a/templates/utils/src/common-modules/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -/** - * @description 请在该文件夹下导出可供web或node平台使用的实用程序 - * @module - */ - -export {}; diff --git a/templates/utils/src/interfaces/index.ts b/templates/utils/src/interfaces/index.ts deleted file mode 100644 index 0f76cf7..0000000 --- a/templates/utils/src/interfaces/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -/** - * @description 请在该文件夹下导出可供外部使用的类型接口 - * @module - */ - -export {}; diff --git a/templates/utils/src/node-modules/index.ts b/templates/utils/src/node-modules/index.ts deleted file mode 100644 index d8f927e..0000000 --- a/templates/utils/src/node-modules/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -/** - * @description 请在该文件夹下导出仅供node平台使用的实用程序 - * @module - */ - -export {}; diff --git a/templates/utils/src/node.ts b/templates/utils/src/node.ts deleted file mode 100644 index 1cd4925..0000000 --- a/templates/utils/src/node.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * @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 deleted file mode 100644 index 2dba4e7..0000000 --- a/templates/utils/src/web-modules/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -/** - * @description 请在该文件夹下导出可供Browser或前端ESM使用的实用程序 - * @module - */ - -export {}; diff --git a/templates/utils/src/web.ts b/templates/utils/src/web.ts deleted file mode 100644 index 44f0a2f..0000000 --- a/templates/utils/src/web.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * @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 deleted file mode 100644 index 981a54e..0000000 --- a/templates/utils/tsconfig.json.handlebars +++ /dev/null @@ -1,31 +0,0 @@ -{ - "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 deleted file mode 100644 index 018c94b..0000000 --- a/templates/utils/tsconfig.node.json.handlebars +++ /dev/null @@ -1,28 +0,0 @@ -{ - "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 deleted file mode 100644 index 44acafa..0000000 --- a/templates/utils/tsconfig.test.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "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 deleted file mode 100644 index 34b317b..0000000 --- a/templates/utils/tsconfig.web.json.handlebars +++ /dev/null @@ -1,13 +0,0 @@ -{ - "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