@doyuli/create-lib 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,9 @@
1
+ ### Usage
2
+
3
+ ```bash
4
+ npx @doyuli/create-lib
5
+
6
+ # or
7
+
8
+ npm create @doyuli/lib
9
+ ```
package/bin/index.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import '../dist/index.mjs'
package/dist/index.mjs ADDED
@@ -0,0 +1,100 @@
1
+ import * as path from "node:path";
2
+ import process from "node:process";
3
+ import { fileURLToPath } from "node:url";
4
+ import { parseArgs } from "node:util";
5
+ import { intro, outro } from "@clack/prompts";
6
+ import { getCommand, getPackageManager, renderFile, renderTemplate, setupFeatures, setupProject, setupPrompts } from "@doyuli/kits-core";
7
+ import pico from "picocolors";
8
+ import * as fs from "node:fs";
9
+
10
+ //#region src/constants.ts
11
+ const DEFAULT_BANNER = "Template-Kits - 快速生成你的模板代码";
12
+ const FEATURE_OPTIONS = [
13
+ {
14
+ value: "monorepo",
15
+ label: "Monorepo(pnpm workspace 多包管理)"
16
+ },
17
+ {
18
+ value: "simple-git-hooks",
19
+ label: "Simple Git Hooks(Git Commit 检查)"
20
+ },
21
+ {
22
+ value: "github-workflows",
23
+ label: "GitHub Workflows(CI/CD 自动化)"
24
+ }
25
+ ];
26
+
27
+ //#endregion
28
+ //#region src/helper.ts
29
+ /**
30
+ * Convert devDependencies to catalog: references and generate pnpm-workspace.yaml
31
+ */
32
+ function renderMonorepoDeps(root) {
33
+ const pkgPath = path.join(root, "package.json");
34
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
35
+ const devDeps = pkg.devDependencies ?? {};
36
+ const sortedEntries = Object.entries(devDeps).sort(([a], [b]) => a.localeCompare(b));
37
+ pkg.devDependencies = Object.fromEntries(sortedEntries.map(([k]) => [k, "catalog:"]));
38
+ renderFile(root, "package.json", `${JSON.stringify(pkg, null, 2)}\n`);
39
+ renderFile(root, "pnpm-workspace.yaml", [
40
+ "shellEmulator: true",
41
+ "trustPolicy: no-downgrade",
42
+ "",
43
+ "packages:",
44
+ " - packages/*",
45
+ "",
46
+ "catalog:",
47
+ sortedEntries.map(([name, version]) => {
48
+ return ` ${name.includes("/") ? `'${name}'` : name}: ${version}`;
49
+ }).join("\n"),
50
+ ""
51
+ ].join("\n"));
52
+ }
53
+
54
+ //#endregion
55
+ //#region src/index.ts
56
+ (async function() {
57
+ const cwd = process.cwd();
58
+ const { positionals } = parseArgs({
59
+ strict: true,
60
+ allowPositionals: true
61
+ });
62
+ intro(pico.magenta(DEFAULT_BANNER));
63
+ const inputTargetDir = positionals[0];
64
+ const { result, targetDir } = await setupPrompts(inputTargetDir, [setupFeatures("features", { options: [...FEATURE_OPTIONS] })]);
65
+ const root = await setupProject(cwd, result, targetDir);
66
+ renderTemplates(root, result);
67
+ outro(getOutroMessage(root, cwd));
68
+ })();
69
+ function getOutroMessage(root, cwd) {
70
+ const manager = getPackageManager();
71
+ let message = `项目初始化完成,可执行以下命令:\n\n`;
72
+ if (root !== cwd) {
73
+ const cdProjectName = path.relative(cwd, root);
74
+ message += ` ${pico.bold(pico.green(`cd ${cdProjectName.includes(" ") ? `"${cdProjectName}"` : cdProjectName}`))}\n`;
75
+ }
76
+ message += ` ${pico.bold(pico.green(getCommand(manager, "install")))}\n`;
77
+ message += ` ${pico.bold(pico.green(getCommand(manager, "dev")))}\n`;
78
+ return message;
79
+ }
80
+ function renderTemplates(root, result) {
81
+ const { features } = result;
82
+ const needsMonorepo = features.includes("monorepo");
83
+ const needsGitHooks = features.includes("simple-git-hooks");
84
+ const needsWorkflows = features.includes("github-workflows");
85
+ const templateRoot = fileURLToPath(new URL("../template", import.meta.url));
86
+ const render = (templateName) => {
87
+ renderTemplate(path.resolve(templateRoot, templateName), root);
88
+ };
89
+ render("base");
90
+ render("eslint");
91
+ if (needsGitHooks) render("git-hooks");
92
+ if (needsWorkflows) render("github-workflows");
93
+ if (needsMonorepo) {
94
+ render("monorepo");
95
+ renderMonorepoDeps(root);
96
+ } else render("single-repo");
97
+ }
98
+
99
+ //#endregion
100
+ export { };
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@doyuli/create-lib",
3
+ "type": "module",
4
+ "version": "0.2.1",
5
+ "description": "@doyuli/create-lib",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/doyuli/template-kits.git",
10
+ "directory": "packages/create-lib"
11
+ },
12
+ "keywords": [
13
+ "templates",
14
+ "create-lib"
15
+ ],
16
+ "sideEffects": false,
17
+ "main": "dist/index.js",
18
+ "bin": {
19
+ "create-lib": "bin/index.js"
20
+ },
21
+ "files": [
22
+ "bin",
23
+ "dist",
24
+ "template",
25
+ "template/**/settings.json"
26
+ ],
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "engines": {
31
+ "node": "^20.19.0 || >=22.12.0"
32
+ },
33
+ "scripts": {
34
+ "dev": "tsdown --watch",
35
+ "build": "tsdown",
36
+ "prepack": "pnpm run build"
37
+ },
38
+ "dependencies": {
39
+ "@clack/prompts": "catalog:",
40
+ "@doyuli/kits-core": "workspace:^",
41
+ "picocolors": "catalog:"
42
+ }
43
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "recommendations": ["vitest.explorer", "dbaeumer.vscode-eslint"]
3
+ }
@@ -0,0 +1,50 @@
1
+ {
2
+ // Disable the default formatter, use eslint instead
3
+ "prettier.enable": false,
4
+ "editor.formatOnSave": false,
5
+
6
+ // Auto fix
7
+ "editor.codeActionsOnSave": {
8
+ "source.fixAll.eslint": "explicit",
9
+ "source.organizeImports": "never"
10
+ },
11
+
12
+ // Silent the stylistic rules in you IDE, but still auto fix them
13
+ "eslint.rules.customizations": [
14
+ { "rule": "style/*", "severity": "off", "fixable": true },
15
+ { "rule": "format/*", "severity": "off", "fixable": true },
16
+ { "rule": "*-indent", "severity": "off", "fixable": true },
17
+ { "rule": "*-spacing", "severity": "off", "fixable": true },
18
+ { "rule": "*-spaces", "severity": "off", "fixable": true },
19
+ { "rule": "*-order", "severity": "off", "fixable": true },
20
+ { "rule": "*-dangle", "severity": "off", "fixable": true },
21
+ { "rule": "*-newline", "severity": "off", "fixable": true },
22
+ { "rule": "*quotes", "severity": "off", "fixable": true },
23
+ { "rule": "*semi", "severity": "off", "fixable": true }
24
+ ],
25
+
26
+ // Enable eslint for all supported languages
27
+ "eslint.validate": [
28
+ "javascript",
29
+ "javascriptreact",
30
+ "typescript",
31
+ "typescriptreact",
32
+ "vue",
33
+ "html",
34
+ "markdown",
35
+ "json",
36
+ "jsonc",
37
+ "yaml",
38
+ "toml",
39
+ "xml",
40
+ "gql",
41
+ "graphql",
42
+ "astro",
43
+ "svelte",
44
+ "css",
45
+ "less",
46
+ "scss",
47
+ "pcss",
48
+ "postcss"
49
+ ]
50
+ }
@@ -0,0 +1,6 @@
1
+ root = true
2
+
3
+ [*]
4
+ indent_size = 2
5
+ end_of_line = lf
6
+ insert_final_newline = true
@@ -0,0 +1 @@
1
+ * text=auto eol=lf
@@ -0,0 +1,5 @@
1
+ node_modules
2
+ .DS_Store
3
+ dist
4
+ *.log
5
+ .eslintcache
@@ -0,0 +1,27 @@
1
+ {
2
+ "type": "module",
3
+ "private": true,
4
+ "license": "MIT",
5
+ "packageManager": "pnpm@10.25.0",
6
+ "engines": {
7
+ "node": ">=20.18.0"
8
+ },
9
+ "scripts": {
10
+ "dev": "tsdown --watch",
11
+ "build": "tsdown",
12
+ "test": "vitest",
13
+ "release": "bumpp -r",
14
+ "lint": "eslint --cache",
15
+ "lint:fix": "eslint --cache --fix",
16
+ "typecheck": "tsc --noEmit",
17
+ "prepublishOnly": "pnpm run build"
18
+ },
19
+ "devDependencies": {
20
+ "@types/node": "^25.3.2",
21
+ "bumpp": "^10.4.1",
22
+ "tsdown": "^0.20.3",
23
+ "tsx": "^4.21.0",
24
+ "typescript": "^5.9.3",
25
+ "vitest": "^4.0.18"
26
+ }
27
+ }
@@ -0,0 +1,8 @@
1
+ // @ts-check
2
+ import antfu from '@antfu/eslint-config'
3
+
4
+ export default antfu(
5
+ {
6
+ formatters: true,
7
+ },
8
+ )
@@ -0,0 +1,11 @@
1
+ {
2
+ "scripts": {
3
+ "lint": "eslint --cache",
4
+ "lint:fix": "eslint --cache --fix"
5
+ },
6
+ "devDependencies": {
7
+ "@antfu/eslint-config": "catalog:",
8
+ "eslint": "catalog:",
9
+ "eslint-plugin-format": "catalog:"
10
+ }
11
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "scripts": {
3
+ "postinstall": "simple-git-hooks"
4
+ },
5
+ "devDependencies": {
6
+ "picocolors": "^1.1.1",
7
+ "lint-staged": "^16.1.6",
8
+ "simple-git-hooks": "^2.13.1"
9
+ },
10
+ "simple-git-hooks": {
11
+ "pre-commit": "pnpm lint-staged",
12
+ "commit-msg": "node scripts/verify-commit.js"
13
+ },
14
+ "lint-staged": {
15
+ "*": "eslint --fix"
16
+ }
17
+ }
@@ -0,0 +1,41 @@
1
+ // @ts-check
2
+
3
+ import { readFileSync } from 'node:fs'
4
+ import path from 'node:path'
5
+ import process from 'node:process'
6
+ import pico from 'picocolors'
7
+
8
+ const msgPath = path.resolve('.git/COMMIT_EDITMSG')
9
+ const msg = readFileSync(msgPath, 'utf-8').trim()
10
+
11
+ // eslint-disable-next-line regexp/no-unused-capturing-group
12
+ const COMMIT_RE = /^(revert: )?(feat|fix|docs|dx|style|refactor|perf|test|workflow|build|ci|chore|types|wip|release)(\(.+\))?: .{1,50}/
13
+
14
+ if (!COMMIT_RE.test(msg)) {
15
+ console.log()
16
+ console.error(
17
+ ` ${pico.bgRed(pico.white(' ERROR '))} ${pico.red(`Invalid commit message format.`)}\n\n`
18
+ + ` ${pico.dim('Help us keep a meaningful git history by following')}\n\n`
19
+
20
+ + ` ${pico.yellow('Standard Format:')}\n`
21
+ + ` ${pico.green('<type>[optional scope]: <description>')}\n\n`
22
+
23
+ + ` ${pico.cyan('Common Types:')}\n`
24
+ + ` ${pico.green(' feat')} ${pico.dim('A new feature')}\n`
25
+ + ` ${pico.green(' fix')} ${pico.dim('A bug fix')}\n`
26
+ + ` ${pico.green(' docs')} ${pico.dim('Documentation only changes')}\n`
27
+ + ` ${pico.green(' style')} ${pico.dim('Changes that do not affect the meaning of the code')}\n`
28
+ + ` ${pico.green(' refactor')} ${pico.dim('Code change that neither fixes a bug nor adds a feature')}\n`
29
+ + ` ${pico.green(' perf')} ${pico.dim('A code change that improves performance')}\n`
30
+ + ` ${pico.green(' test')} ${pico.dim('Adding missing tests or correcting existing tests')}\n`
31
+ + ` ${pico.green(' build')} ${pico.dim('Changes that affect the build system or external dependencies')}\n`
32
+ + ` ${pico.green(' ci')} ${pico.dim('Changes to CI configuration files and scripts')}\n`
33
+ + ` ${pico.green(' chore')} ${pico.dim('Other changes that don\'t modify src or test files')}\n`
34
+ + ` ${pico.green(' revert')} ${pico.dim('Reverts a previous commit')}\n\n`
35
+
36
+ + ` ${pico.cyan('Correct Examples:')}\n`
37
+ + ` ${pico.white(' feat(ui): add secondary button style')}\n`
38
+ + ` ${pico.white(' fix(auth): resolve token expiration issue')}\n\n`,
39
+ )
40
+ process.exit(1)
41
+ }
@@ -0,0 +1,36 @@
1
+ name: Release
2
+
3
+ permissions:
4
+ contents: write
5
+
6
+ on:
7
+ push:
8
+ tags:
9
+ - 'v*'
10
+
11
+ jobs:
12
+ release:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v6
16
+ with:
17
+ fetch-depth: 0
18
+
19
+ - name: Install pnpm
20
+ uses: pnpm/action-setup@v4.2.0
21
+
22
+ - name: Set node
23
+ uses: actions/setup-node@v6
24
+ with:
25
+ node-version: lts/*
26
+
27
+ - name: Generate GitHub Changelog
28
+ run: pnpx changelogithub
29
+ env:
30
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
31
+
32
+ - name: Build
33
+ run: pnpm run build
34
+
35
+ - name: Publish to NPM
36
+ run: pnpm -r publish --access public --no-git-checks
@@ -0,0 +1,63 @@
1
+ name: Unit Test
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ lint:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - name: Checkout
14
+ uses: actions/checkout@v6
15
+
16
+ - name: Install pnpm
17
+ uses: pnpm/action-setup@v4.2.0
18
+
19
+ - name: Set node LTS
20
+ uses: actions/setup-node@v6
21
+ with:
22
+ node-version: lts/*
23
+ cache: pnpm
24
+
25
+ - name: Install
26
+ run: pnpm install
27
+
28
+ - name: Lint
29
+ run: pnpm run lint
30
+
31
+ - name: Typecheck
32
+ run: pnpm run typecheck
33
+
34
+ test:
35
+ runs-on: ${{ matrix.os }}
36
+
37
+ strategy:
38
+ matrix:
39
+ os: [ubuntu-latest, windows-latest]
40
+ node: [20, 22, 24]
41
+ fail-fast: false
42
+
43
+ steps:
44
+ - name: Checkout
45
+ uses: actions/checkout@v6
46
+
47
+ - name: Install pnpm
48
+ uses: pnpm/action-setup@v4.2.0
49
+
50
+ - name: Set node ${{ matrix.node }}
51
+ uses: actions/setup-node@v6
52
+ with:
53
+ node-version: ${{ matrix.node }}
54
+ cache: pnpm
55
+
56
+ - name: Install
57
+ run: pnpm install
58
+
59
+ - name: Build
60
+ run: pnpm run build
61
+
62
+ - name: Test
63
+ run: pnpm run test
@@ -0,0 +1,9 @@
1
+ // @ts-check
2
+ import antfu from '@antfu/eslint-config'
3
+
4
+ export default antfu(
5
+ {
6
+ formatters: true,
7
+ pnpm: true,
8
+ },
9
+ )
@@ -0,0 +1,3 @@
1
+ # @scope/foo
2
+
3
+ @scope/foo
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "@scope/foo",
3
+ "type": "module",
4
+ "version": "0.0.0",
5
+ "packageManager": "pnpm@10.25.0",
6
+ "license": "MIT",
7
+ "exports": {
8
+ ".": "./dist/index.mjs",
9
+ "./package.json": "./package.json"
10
+ },
11
+ "types": "./dist/index.d.ts",
12
+ "files": [
13
+ "dist"
14
+ ],
15
+ "engines": {
16
+ "node": ">=20.18.0"
17
+ },
18
+ "publishConfig": {
19
+ "access": "public"
20
+ }
21
+ }
@@ -0,0 +1 @@
1
+ export const foo = 'foo'
@@ -0,0 +1,6 @@
1
+ import { expect, it } from 'vitest'
2
+ import { foo } from '../src'
3
+
4
+ it('simple', () => {
5
+ expect(foo).toBe('foo')
6
+ })
@@ -0,0 +1,5 @@
1
+ shellEmulator: true
2
+ trustPolicy: no-downgrade
3
+
4
+ packages:
5
+ - packages/*
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "esnext",
4
+ "lib": ["es2023"],
5
+ "moduleDetection": "force",
6
+ "module": "preserve",
7
+ "moduleResolution": "bundler",
8
+ "resolveJsonModule": true,
9
+ "types": ["node"],
10
+ "strict": true,
11
+ "noUnusedLocals": true,
12
+ "declaration": true,
13
+ "esModuleInterop": true,
14
+ "isolatedDeclarations": true,
15
+ "isolatedModules": true,
16
+ "verbatimModuleSyntax": true,
17
+ "skipLibCheck": true
18
+ },
19
+ "include": ["packages/*/src", "packages/*/tests"],
20
+ "exclude": ["packages/*/tests/fixtures"]
21
+ }
@@ -0,0 +1,9 @@
1
+ import { defineConfig } from 'tsdown'
2
+
3
+ export default defineConfig({
4
+ workspace: true,
5
+ entry: ['src/index.ts'],
6
+ exports: true,
7
+ dts: true,
8
+ publint: true,
9
+ })
@@ -0,0 +1,13 @@
1
+ {
2
+ "exports": {
3
+ ".": "./dist/index.mjs",
4
+ "./package.json": "./package.json"
5
+ },
6
+ "types": "./dist/index.d.ts",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "publishConfig": {
11
+ "access": "public"
12
+ }
13
+ }
@@ -0,0 +1 @@
1
+ export const foo = 'foo'
@@ -0,0 +1,6 @@
1
+ import { expect, it } from 'vitest'
2
+ import { foo } from '../src'
3
+
4
+ it('simple', () => {
5
+ expect(foo).toBe('foo')
6
+ })
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "esnext",
4
+ "lib": ["es2023"],
5
+ "moduleDetection": "force",
6
+ "module": "preserve",
7
+ "moduleResolution": "bundler",
8
+ "resolveJsonModule": true,
9
+ "types": ["node"],
10
+ "strict": true,
11
+ "noUnusedLocals": true,
12
+ "declaration": true,
13
+ "esModuleInterop": true,
14
+ "isolatedDeclarations": true,
15
+ "isolatedModules": true,
16
+ "verbatimModuleSyntax": true,
17
+ "skipLibCheck": true
18
+ },
19
+ "include": ["src", "tests"]
20
+ }
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from 'tsdown'
2
+
3
+ export default defineConfig({
4
+ entry: ['src/index.ts'],
5
+ exports: true,
6
+ dts: true,
7
+ publint: true,
8
+ })