Skip to content

Commit

Permalink
Merge pull request #18 from dumlj/alpha
Browse files Browse the repository at this point in the history
support pnpm
  • Loading branch information
DavidKk authored Feb 20, 2024
2 parents fa2ca75 + 4161b0b commit 9d5a2bc
Show file tree
Hide file tree
Showing 176 changed files with 25,582 additions and 21,285 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
libs
!**/src/**/libs
!**/__tests__/**/libs
!**/__example
build
.next
coverage
Expand Down
55 changes: 16 additions & 39 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,11 @@ module.exports = {
* @see https://eslint.org/docs/latest/user-guide/configuring/configuration-files#cascading-and-hierarchy
*/
root: true,
extends: ['plugin:@typescript-eslint/recommended', 'prettier'],
parser: '@typescript-eslint/parser',
parserOptions: {
/** 项目 ts 配置文件 */
project: './tsconfig.json',
},
extends: ['prettier'],
env: {
node: true,
},
plugins: ['@typescript-eslint', 'eslint-plugin-import', 'prettier', 'react-hooks'],
plugins: ['eslint-plugin-import', 'prettier'],
rules: {
/** 请与 `.prettierrc.js` 保持一致 */
'max-len': [
Expand All @@ -31,36 +26,6 @@ module.exports = {
'no-console': 'warn',
/** 不能重复引入 */
'import/no-duplicates': 'warn',
/** 类型导出必须使用 type */
'@typescript-eslint/consistent-type-exports': 'warn',
/** 类型导入必须使用 type */
'@typescript-eslint/consistent-type-imports': 'warn',
/** 不能使用 any */
'@typescript-eslint/no-explicit-any': 'off',
/** 必须声明返回类型 */
'@typescript-eslint/explicit-function-return-type': 'off',
/** 必须声明入参类型 */
'@typescript-eslint/explicit-module-boundary-types': 'off',
/**
* 基础类型复制无需声明类型
* @see https://typescript-eslint.io/rules/no-inferrable-types
*/
'@typescript-eslint/no-inferrable-types': 'warn',
/** interface 名字前缀 */
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/member-delimiter-style': [
'error',
{
multiline: {
delimiter: 'none',
requireLast: false,
},
singleline: {
delimiter: 'semi',
requireLast: false,
},
},
],
/** 引用必须在依赖中有声明 */
'import/no-extraneous-dependencies': [
'warn',
Expand All @@ -72,7 +37,19 @@ module.exports = {
devDependencies: ['**/*.spec.ts', '**/*/jest.config.*.ts'],
},
],
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
},
overrides: [
{
files: ['**/*.ts'],
extends: ['./public/eslintrc/ts.js'],
},
{
files: ['**/*.js'],
extends: ['./public/eslintrc/cjs.js'],
},
{
files: ['**/*.mjs'],
extends: ['./public/eslintrc/esm.js'],
},
],
}
10 changes: 1 addition & 9 deletions .github/workflows/build.workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,7 @@ on:
workflow_dispatch:
push:
branches:
- main
- 'feat/*'
- 'feature/*'
- 'hotfix/*'
- 'fix/*'
- 'ci/*'
- 'perf/*'
- 'docs/*'
- 'style/*'
- '**'
tags-ignore:
- '**'

Expand Down
4 changes: 3 additions & 1 deletion .readmerc.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { ReadmeConfiguration } from '@dumlj/tidy-cli'

export const configure: ReadmeConfiguration = async () => {
return {}
return {
locals: ['zh-CN'],
}
}
216 changes: 216 additions & 0 deletions .templaterc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
/* eslint-disable import/no-extraneous-dependencies */

import path from 'path'
import { upperFirst, camelCase, kebabCase } from 'lodash'
import { SyntaxKind, type TemplateSchema } from '@dumlj/create-cli'

const configureCli = async (): Promise<TemplateSchema> => {
const alias = (name: string) => upperFirst(camelCase(name))
const nameClass = (name: string) => `${alias(name)}Cli`
const nameModule = (name: string) => `@dumlj/${kebabCase(`${name}-cli`)}`
const nameDirectory = (name: string) => `@cli/${kebabCase(`${name}-cli`)}`
const folder = path.join(__dirname, '@cli')

return {
template: path.join(folder, '__template__'),
output: folder,
name: 'Cli Template',
description: 'Create a cli which inherits seed-cli.',
egName: 'CustomCli',
nameTransform: (input: string) => {
const SUFFIX_NAME = 'Cli'

let length = 0
while (true) {
if (SUFFIX_NAME.length === length) {
break
}

const t = SUFFIX_NAME.substring(0, length + 1)
if (new RegExp(t, 'i').test(input)) {
length++
continue
}

break
}

const suffixSameStr = SUFFIX_NAME.substring(0, length)
const nameSameStr = input.substring(input.length - length)
if (suffixSameStr.toUpperCase() !== nameSameStr.toUpperCase()) {
return { shortName: input, name: nameClass(input), same: '', suffix: SUFFIX_NAME }
}

const shortName = input.substring(0, input.length - nameSameStr.length)
const name = alias(`${shortName}${SUFFIX_NAME}`)
const suffix = SUFFIX_NAME.substring(length)
return { shortName, name, same: suffixSameStr, suffix }
},
outputPathResolver: (kebabCaseName: string) => nameDirectory(kebabCaseName),
pkgTransform: () => {
return async ({ name, description, source }) => {
source.name = nameModule(name)
source.description = description
source.repository.directory = nameDirectory(name)
}
},
tsTransform: (file) => {
switch (file) {
case 'src/actions/entry.ts': {
return async ({ name, ast }) => {
const iOptions = ast.getInterfaceOrThrow('EntryOptions')
iOptions.rename(`${upperFirst(name)}Options`)

const iConst = ast.getVariableDeclarationOrThrow('entry')
iConst.rename(name)

return { output: `src/actions/${name}.ts` }
}
}

case 'src/commands/entry.ts': {
return async ({ name, ast }) => {
const declaration = ast.getImportDeclarationOrThrow('../actions/entry')
declaration.setModuleSpecifier(`../actions/${name}`)

const imports = declaration.getNamedImports()
const vEntry = imports.find((item) => item.getName() === 'entry')
const vEntryOptions = imports.find((item) => item.getName() === 'EntryOptions')

vEntry?.getNameNode().rename(name)
vEntryOptions?.getNameNode().rename(`${upperFirst(name)}Options`)

vEntry?.setName(name).removeAlias()
vEntryOptions?.setName(`${upperFirst(name)}Options`).removeAlias()

for (const callExpression of ast.getDescendantsOfKind(SyntaxKind.CallExpression)) {
callExpression
.getArguments()
.find((arg) => arg.getText() === `'entry'`)
?.replaceWithText(`'${name}'`)
}

return { output: `src/commands/${name}.ts` }
}
}

case 'src/index.ts': {
return async ({ name, ast }) => {
const declarations = ast.getExportDeclarations()
const declaration = declarations.find((d) => d.getModuleSpecifier()!.getLiteralText() === './commands/entry')!
declaration.setModuleSpecifier(`./commands/${name}`)

const entry = declaration.getNamedExports().find((item) => item.getAliasNode()?.getText() === 'entry')
entry?.getAliasNode()?.rename(name)

return
}
}
}
},
}
}

const configureFeature = async (): Promise<TemplateSchema> => {
const nameModule = (name: string) => `@dumlj/feature-${kebabCase(name)}`
const nameDirectory = (name: string) => `@feature/feature-${kebabCase(name)}`
const folder = path.join(__dirname, '@feature')

return {
template: path.join(folder, '__template__'),
output: folder,
name: 'Feature Template',
description: 'Create a common features.',
outputPathResolver: (kebabCaseName: string) => nameDirectory(kebabCaseName),
pkgTransform: () => {
return async ({ name, description, source }) => {
source.name = nameModule(name)
source.description = description
source.repository.directory = nameDirectory(name)
}
},
}
}

const configureWebpack = async (): Promise<TemplateSchema> => {
const alias = (name: string) => upperFirst(camelCase(name))
const nameClass = (name: string) => `${alias(name)}WebpackPlugin`
const nameOptions = (name: string) => `${alias(name)}WebpackPluginOptions`
const namePlugin = (name: string) => `${kebabCase(name)}-webpack-plugin`
const nameModule = (name: string) => `@dumlj/${kebabCase(name)}-webpack-plugin`
const nameDirectory = (name: string) => `@webpack-plugin/${kebabCase(name)}-webpack-plugin`
const folder = path.join(__dirname, '@webpack-plugin')

return {
template: path.join(folder, '__template__'),
output: folder,
name: 'Webpack Plugin Template',
description: 'Create a webpack plugin which inherits seed-webpack-plugin.',
egName: 'CustomWebpackPlugin',
nameTransform: (input: string) => {
const SUFFIX_NAME = 'WebpackPlugin'

let length = 0
while (true) {
if (SUFFIX_NAME.length === length) {
break
}

const t = SUFFIX_NAME.substring(0, length + 1)
if (new RegExp(t, 'i').test(input)) {
length++
continue
}

break
}

const suffixSameStr = SUFFIX_NAME.substring(0, length)
const nameSameStr = input.substring(input.length - length)
if (suffixSameStr.toUpperCase() !== nameSameStr.toUpperCase()) {
return { shortName: input, name: nameClass(input), same: '', suffix: SUFFIX_NAME }
}

const shortName = input.substring(0, input.length - nameSameStr.length)
const name = alias(`${shortName}${SUFFIX_NAME}`)
const suffix = SUFFIX_NAME.substring(length)
return { shortName, name, same: suffixSameStr, suffix }
},
outputPathResolver: (kebabCaseName: string) => nameDirectory(kebabCaseName),
pkgTransform: () => {
return async ({ name, description, source }) => {
source.name = nameModule(name)
source.description = description
source.repository.directory = nameDirectory(name)
}
},
tsTransform: (file) => {
switch (file) {
case 'src/WebpackPlugin.ts':
return async ({ name, ast }) => {
const nOptions = ast.getInterfaceOrThrow('WebpackPluginOptions')
nOptions.rename(nameOptions(name))

const nClass = ast.getClassOrThrow('WebpackPlugin')
nClass.rename(nameClass(name))

const nPluginName = nClass.getStaticProperty('PLUGIN_NAME')!
nPluginName.set({ initializer: JSON.stringify(namePlugin(name)) })
return { output: `src/${nameClass(name)}.ts` }
}

case 'src/index.ts':
return async ({ name, ast }) => {
const declarations = ast.getExportDeclarations()
const declaration = declarations.find((d) => d.getModuleSpecifier()!.getLiteralText() === './WebpackPlugin')!
declaration.setModuleSpecifier(`./${nameClass(name)}`)
return
}
}
},
}
}

export const configure = async () => {
return [await configureCli(), await configureFeature(), await configureWebpack()]
}
Loading

0 comments on commit 9d5a2bc

Please sign in to comment.