278 changed files with 22530 additions and 0 deletions
@ -0,0 +1,23 @@ |
|||
import { requestClient } from '#/api/request' |
|||
|
|||
export namespace userApi { |
|||
|
|||
export function page(params:any){ |
|||
|
|||
return requestClient.get('/health_user/page',{params}) |
|||
|
|||
} |
|||
|
|||
export function save(data:any){ |
|||
|
|||
return requestClient.post('/health_user',data) |
|||
|
|||
} |
|||
|
|||
export function remove(id:number){ |
|||
|
|||
return requestClient.delete('/health_user/'+id) |
|||
|
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,133 @@ |
|||
import { FormSchema } from '/@/components/Form'; |
|||
|
|||
export const formSchema: FormSchema[] = [ |
|||
|
|||
|
|||
{ |
|||
field: '', |
|||
label: '', |
|||
component: 'Input', |
|||
}, |
|||
|
|||
{ |
|||
field: '', |
|||
label: '', |
|||
component: 'Input', |
|||
}, |
|||
|
|||
{ |
|||
field: '', |
|||
label: '', |
|||
component: 'Input', |
|||
}, |
|||
|
|||
{ |
|||
field: '', |
|||
label: '', |
|||
component: 'Input', |
|||
}, |
|||
|
|||
{ |
|||
field: '', |
|||
label: '', |
|||
component: 'Input', |
|||
}, |
|||
|
|||
{ |
|||
field: '', |
|||
label: '', |
|||
component: 'Input', |
|||
}, |
|||
|
|||
{ |
|||
field: '', |
|||
label: '', |
|||
component: 'Input', |
|||
}, |
|||
|
|||
{ |
|||
field: '', |
|||
label: '', |
|||
component: 'Input', |
|||
}, |
|||
|
|||
{ |
|||
field: '', |
|||
label: '', |
|||
component: 'Input', |
|||
}, |
|||
|
|||
{ |
|||
field: '', |
|||
label: '', |
|||
component: 'Input', |
|||
}, |
|||
|
|||
{ |
|||
field: '', |
|||
label: '', |
|||
component: 'Input', |
|||
}, |
|||
|
|||
{ |
|||
field: '', |
|||
label: '', |
|||
component: 'Input', |
|||
}, |
|||
|
|||
{ |
|||
field: '', |
|||
label: '', |
|||
component: 'Input', |
|||
}, |
|||
|
|||
{ |
|||
field: '', |
|||
label: '', |
|||
component: 'Input', |
|||
}, |
|||
|
|||
{ |
|||
field: '', |
|||
label: '', |
|||
component: 'Input', |
|||
}, |
|||
|
|||
{ |
|||
field: '', |
|||
label: '', |
|||
component: 'Input', |
|||
}, |
|||
|
|||
{ |
|||
field: '', |
|||
label: '', |
|||
component: 'Input', |
|||
}, |
|||
|
|||
{ |
|||
field: '', |
|||
label: '', |
|||
component: 'Input', |
|||
}, |
|||
|
|||
{ |
|||
field: '', |
|||
label: '', |
|||
component: 'Input', |
|||
}, |
|||
|
|||
{ |
|||
field: '', |
|||
label: '', |
|||
component: 'Input', |
|||
}, |
|||
|
|||
{ |
|||
field: '', |
|||
label: '', |
|||
component: 'Input', |
|||
}, |
|||
|
|||
|
|||
]; |
|||
@ -0,0 +1,112 @@ |
|||
import type { BasicColumn } from '#/components/Table' |
|||
|
|||
export const columns:BasicColumn[]=[ |
|||
|
|||
|
|||
{ |
|||
title:'主键ID', |
|||
dataIndex:'id' |
|||
}, |
|||
|
|||
{ |
|||
title:'账号', |
|||
dataIndex:'user_name' |
|||
}, |
|||
|
|||
{ |
|||
title:'手机号', |
|||
dataIndex:'user_phone' |
|||
}, |
|||
|
|||
{ |
|||
title:'姓名', |
|||
dataIndex:'user_real_name' |
|||
}, |
|||
|
|||
{ |
|||
title:'性别:0默认保密,1男2女', |
|||
dataIndex:'user_gender' |
|||
}, |
|||
|
|||
{ |
|||
title:'密码', |
|||
dataIndex:'user_password' |
|||
}, |
|||
|
|||
{ |
|||
title:'生日', |
|||
dataIndex:'user_birthday' |
|||
}, |
|||
|
|||
{ |
|||
title:'头像', |
|||
dataIndex:'user_face' |
|||
}, |
|||
|
|||
{ |
|||
title:'邮箱', |
|||
dataIndex:'user_email' |
|||
}, |
|||
|
|||
{ |
|||
title:'创建时间', |
|||
dataIndex:'created_at' |
|||
}, |
|||
|
|||
{ |
|||
title:'更新时间', |
|||
dataIndex:'updated_at' |
|||
}, |
|||
|
|||
{ |
|||
title:'创建人', |
|||
dataIndex:'created_by' |
|||
}, |
|||
|
|||
{ |
|||
title:'更新人', |
|||
dataIndex:'updated_by' |
|||
}, |
|||
|
|||
{ |
|||
title:'删除 0 默认 1删除', |
|||
dataIndex:'deleted_flag' |
|||
}, |
|||
|
|||
{ |
|||
title:'地址', |
|||
dataIndex:'user_address' |
|||
}, |
|||
|
|||
{ |
|||
title:'用户ID冗余字段', |
|||
dataIndex:'user_id' |
|||
}, |
|||
|
|||
{ |
|||
title:'系统型号', |
|||
dataIndex:'user_sys' |
|||
}, |
|||
|
|||
{ |
|||
title:'手机型号', |
|||
dataIndex:'user_phone_model' |
|||
}, |
|||
|
|||
{ |
|||
title:'用户状态默认启用0,注销1', |
|||
dataIndex:'user_status' |
|||
}, |
|||
|
|||
{ |
|||
title:'手机唯一标识', |
|||
dataIndex:'user_cid' |
|||
}, |
|||
|
|||
{ |
|||
title:'手机IP', |
|||
dataIndex:'user_ip' |
|||
}, |
|||
|
|||
|
|||
] |
|||
@ -0,0 +1,112 @@ |
|||
import type { BasicColumn } from '#/components/Table' |
|||
|
|||
export const columns: BasicColumn[] = [ |
|||
|
|||
|
|||
{ |
|||
title:'', |
|||
dataIndex:'', |
|||
}, |
|||
|
|||
{ |
|||
title:'', |
|||
dataIndex:'', |
|||
}, |
|||
|
|||
{ |
|||
title:'', |
|||
dataIndex:'', |
|||
}, |
|||
|
|||
{ |
|||
title:'', |
|||
dataIndex:'', |
|||
}, |
|||
|
|||
{ |
|||
title:'', |
|||
dataIndex:'', |
|||
}, |
|||
|
|||
{ |
|||
title:'', |
|||
dataIndex:'', |
|||
}, |
|||
|
|||
{ |
|||
title:'', |
|||
dataIndex:'', |
|||
}, |
|||
|
|||
{ |
|||
title:'', |
|||
dataIndex:'', |
|||
}, |
|||
|
|||
{ |
|||
title:'', |
|||
dataIndex:'', |
|||
}, |
|||
|
|||
{ |
|||
title:'', |
|||
dataIndex:'', |
|||
}, |
|||
|
|||
{ |
|||
title:'', |
|||
dataIndex:'', |
|||
}, |
|||
|
|||
{ |
|||
title:'', |
|||
dataIndex:'', |
|||
}, |
|||
|
|||
{ |
|||
title:'', |
|||
dataIndex:'', |
|||
}, |
|||
|
|||
{ |
|||
title:'', |
|||
dataIndex:'', |
|||
}, |
|||
|
|||
{ |
|||
title:'', |
|||
dataIndex:'', |
|||
}, |
|||
|
|||
{ |
|||
title:'', |
|||
dataIndex:'', |
|||
}, |
|||
|
|||
{ |
|||
title:'', |
|||
dataIndex:'', |
|||
}, |
|||
|
|||
{ |
|||
title:'', |
|||
dataIndex:'', |
|||
}, |
|||
|
|||
{ |
|||
title:'', |
|||
dataIndex:'', |
|||
}, |
|||
|
|||
{ |
|||
title:'', |
|||
dataIndex:'', |
|||
}, |
|||
|
|||
{ |
|||
title:'', |
|||
dataIndex:'', |
|||
}, |
|||
|
|||
|
|||
] |
|||
@ -0,0 +1,16 @@ |
|||
<script setup lang="ts"> |
|||
|
|||
import { BasicTable } from '#/components/Table' |
|||
import { columns } from './data' |
|||
import { userApi } from '#/api/user' |
|||
|
|||
</script> |
|||
|
|||
<template> |
|||
|
|||
<BasicTable |
|||
:columns="columns" |
|||
:api="userApi.page" |
|||
/> |
|||
|
|||
</template> |
|||
@ -0,0 +1,14 @@ |
|||
# default onwer |
|||
* anncwb@126.com vince292007@gmail.com netfan@foxmail.com jinmao88@qq.com |
|||
|
|||
# vben core onwer |
|||
/.github/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com jinmao88@qq.com |
|||
/.vscode/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com jinmao88@qq.com |
|||
/packages/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com jinmao88@qq.com |
|||
/packages/@core/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com jinmao88@qq.com |
|||
/internal/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com jinmao88@qq.com |
|||
/scripts/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com jinmao88@qq.com |
|||
|
|||
# vben team onwer |
|||
apps/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com @vbenjs/team-v5 jinmao88@qq.com |
|||
docs/ anncwb@126.com vince292007@gmail.com netfan@foxmail.com @vbenjs/team-v5 jinmao88@qq.com |
|||
@ -0,0 +1,74 @@ |
|||
name: 🐞 Bug Report |
|||
description: Report an issue with Vben Admin to help us make it better. |
|||
title: 'Bug: ' |
|||
labels: ['bug: pending triage'] |
|||
|
|||
body: |
|||
- type: markdown |
|||
attributes: |
|||
value: | |
|||
Thanks for taking the time to fill out this bug report! |
|||
- type: dropdown |
|||
id: version |
|||
attributes: |
|||
label: Version |
|||
description: What version of our software are you running? |
|||
options: |
|||
- Vben Admin V5 |
|||
- Vben Admin V2 |
|||
default: 0 |
|||
validations: |
|||
required: true |
|||
|
|||
- type: textarea |
|||
id: bug-desc |
|||
attributes: |
|||
label: Describe the bug? |
|||
description: A clear and concise description of what the bug is. If you intend to submit a PR for this issue, tell us in the description. Thanks! |
|||
placeholder: Bug Description |
|||
validations: |
|||
required: true |
|||
|
|||
- type: textarea |
|||
id: reproduction |
|||
attributes: |
|||
label: Reproduction |
|||
description: Please provide a link to [StackBlitz](https://stackblitz.com/fork/github/vitest-dev/vitest/tree/main/examples/basic?initialPath=__vitest__/) (you can also use [examples](https://github.com/vitest-dev/vitest/tree/main/examples)) or a github repo that can reproduce the problem you ran into. A [minimal reproduction](https://stackoverflow.com/help/minimal-reproducible-example) is required unless you are absolutely sure that the issue is obvious and the provided information is enough to understand the problem. If a report is vague (e.g. just a generic error message) and has no reproduction, it will receive a "needs reproduction" label. If no reproduction is provided after 3 days, it will be auto-closed. |
|||
placeholder: Reproduction |
|||
validations: |
|||
required: true |
|||
|
|||
- type: textarea |
|||
id: system-info |
|||
attributes: |
|||
label: System Info |
|||
description: Output of `npx envinfo --system --npmPackages '{vue}' --binaries --browsers` |
|||
render: shell |
|||
placeholder: System, Binaries, Browsers |
|||
validations: |
|||
required: true |
|||
|
|||
- type: textarea |
|||
id: logs |
|||
attributes: |
|||
label: Relevant log output |
|||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. |
|||
render: shell |
|||
|
|||
- type: checkboxes |
|||
id: terms |
|||
attributes: |
|||
label: Validations |
|||
description: Before submitting the issue, please make sure you do the following |
|||
# description: By submitting this issue, you agree to follow our [Code of Conduct](https://example.com). |
|||
options: |
|||
- label: Read the [docs](https://doc.vben.pro/) |
|||
required: true |
|||
- label: Ensure the code is up to date. (Some issues have been fixed in the latest version) |
|||
required: true |
|||
- label: I have searched the [existing issues](https://github.com/vbenjs/vue-vben-admin/issues) and checked that my issue does not duplicate any existing issues. |
|||
required: true |
|||
- label: Check that this is a concrete bug. For Q&A open a [GitHub Discussion](https://github.com/vbenjs/vue-vben-admin/discussions) or join our [Discord Chat Server](https://discord.gg/8GuAdwDhj6). |
|||
required: true |
|||
- label: The provided reproduction is a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) of the bug. |
|||
required: true |
|||
@ -0,0 +1,38 @@ |
|||
name: 📚 Documentation |
|||
description: Report an issue with Vben Admin Website to help us make it better. |
|||
title: 'Docs: ' |
|||
labels: [documentation] |
|||
body: |
|||
- type: markdown |
|||
attributes: |
|||
value: | |
|||
Thanks for taking the time to fill out this issue! |
|||
- type: checkboxes |
|||
id: documentation_is |
|||
attributes: |
|||
label: Documentation is |
|||
options: |
|||
- label: Missing |
|||
- label: Outdated |
|||
- label: Confusing |
|||
- label: Not sure? |
|||
- type: textarea |
|||
id: description |
|||
attributes: |
|||
label: Explain in Detail |
|||
description: A clear and concise description of your suggestion. If you intend to submit a PR for this issue, tell us in the description. Thanks! |
|||
placeholder: The description of ... page is not clear. I thought it meant ... but it wasn't. |
|||
validations: |
|||
required: true |
|||
- type: textarea |
|||
id: suggestion |
|||
attributes: |
|||
label: Your Suggestion for Changes |
|||
validations: |
|||
required: true |
|||
- type: textarea |
|||
id: reproduction-steps |
|||
attributes: |
|||
label: Steps to reproduce |
|||
description: Please provide any reproduction steps that may need to be described. E.g. if it happens only when running the dev or build script make sure it's clear which one to use. |
|||
placeholder: Run `pnpm install` followed by `pnpm run docs:dev` |
|||
@ -0,0 +1,70 @@ |
|||
name: ✨ New Feature Proposal |
|||
description: Propose a new feature to be added to Vben Admin |
|||
title: 'FEATURE: ' |
|||
labels: ['enhancement: pending triage'] |
|||
body: |
|||
- type: markdown |
|||
attributes: |
|||
value: | |
|||
Thank you for suggesting a feature for our project! Please fill out the information below to help us understand and implement your request! |
|||
- type: dropdown |
|||
id: version |
|||
attributes: |
|||
label: Version |
|||
description: What version of our software are you running? |
|||
options: |
|||
- Vben Admin V5 |
|||
- Vben Admin V2 |
|||
default: 0 |
|||
validations: |
|||
required: true |
|||
|
|||
- type: textarea |
|||
id: description |
|||
attributes: |
|||
label: Description |
|||
description: A detailed description of the feature request. |
|||
placeholder: Please describe the feature you would like to see, and why it would be useful. |
|||
validations: |
|||
required: true |
|||
|
|||
- type: textarea |
|||
id: proposed-solution |
|||
attributes: |
|||
label: Proposed Solution |
|||
description: A clear and concise description of what you want to happen. |
|||
placeholder: Describe the solution you'd like to see |
|||
validations: |
|||
required: true |
|||
|
|||
- type: textarea |
|||
id: alternatives |
|||
attributes: |
|||
label: Alternatives Considered |
|||
description: | |
|||
A clear and concise description of any alternative solutions or features you've considered. |
|||
placeholder: Describe any alternative solutions or features you've considered |
|||
validations: |
|||
required: false |
|||
|
|||
- type: input |
|||
id: additional-context |
|||
attributes: |
|||
label: Additional Context |
|||
description: Add any other context or screenshots about the feature request here. |
|||
placeholder: Any additional information |
|||
validations: |
|||
required: false |
|||
|
|||
- type: checkboxes |
|||
id: checkboxes |
|||
attributes: |
|||
label: Validations |
|||
description: Before submitting the issue, please make sure you do the following |
|||
options: |
|||
- label: Read the [docs](https://doc.vben.pro/) |
|||
required: true |
|||
- label: Ensure the code is up to date. (Some issues have been fixed in the latest version) |
|||
required: true |
|||
- label: I have searched the [existing issues](https://github.com/vbenjs/vue-vben-admin/issues) and checked that my issue does not duplicate any existing issues. |
|||
required: true |
|||
@ -0,0 +1,40 @@ |
|||
name: 'Setup Node' |
|||
|
|||
description: 'Setup node and pnpm' |
|||
|
|||
runs: |
|||
using: 'composite' |
|||
steps: |
|||
- name: Install pnpm |
|||
uses: pnpm/action-setup@v4 |
|||
|
|||
- name: Install Node.js |
|||
uses: actions/setup-node@v6 |
|||
with: |
|||
node-version-file: .node-version |
|||
cache: 'pnpm' |
|||
|
|||
- name: Get pnpm store directory |
|||
shell: bash |
|||
run: | |
|||
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV |
|||
|
|||
- uses: actions/cache@v4 |
|||
name: Setup pnpm cache |
|||
if: ${{ github.ref_name == 'main' }} |
|||
with: |
|||
path: ${{ env.STORE_PATH }} |
|||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} |
|||
restore-keys: | |
|||
${{ runner.os }}-pnpm-store- |
|||
|
|||
- uses: actions/cache/restore@v4 |
|||
if: ${{ github.ref_name != 'main' }} |
|||
with: |
|||
path: ${{ env.STORE_PATH }} |
|||
key: | |
|||
${{ runner.os }}-pnpm-store- |
|||
|
|||
- name: Install dependencies |
|||
shell: bash |
|||
run: pnpm install --frozen-lockfile |
|||
@ -0,0 +1,89 @@ |
|||
## Git Commit Message Convention |
|||
|
|||
> This is adapted from [Angular's commit convention](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular). |
|||
|
|||
#### TL;DR: |
|||
|
|||
Messages must be matched by the following regex: |
|||
|
|||
```js |
|||
/^(revert: )?(feat|fix|docs|style|refactor|perf|test|workflow|build|ci|chore|types|wip): .{1,50}/; |
|||
``` |
|||
|
|||
#### Examples |
|||
|
|||
Appears under "Features" header, `dev` subheader: |
|||
|
|||
``` |
|||
feat(dev): add 'comments' option |
|||
``` |
|||
|
|||
Appears under "Bug Fixes" header, `dev` subheader, with a link to issue #28: |
|||
|
|||
``` |
|||
fix(dev): fix dev error |
|||
|
|||
close #28 |
|||
``` |
|||
|
|||
Appears under "Performance Improvements" header, and under "Breaking Changes" with the breaking change explanation: |
|||
|
|||
``` |
|||
perf(build): remove 'foo' option |
|||
|
|||
BREAKING CHANGE: The 'foo' option has been removed. |
|||
``` |
|||
|
|||
The following commit and commit `667ecc1` do not appear in the changelog if they are under the same release. If not, the revert commit appears under the "Reverts" header. |
|||
|
|||
``` |
|||
revert: feat(compiler): add 'comments' option |
|||
|
|||
This reverts commit 667ecc1654a317a13331b17617d973392f415f02. |
|||
``` |
|||
|
|||
### Full Message Format |
|||
|
|||
A commit message consists of a **header**, **body** and **footer**. The header has a **type**, **scope** and **subject**: |
|||
|
|||
``` |
|||
<type>(<scope>): <subject> |
|||
<BLANK LINE> |
|||
<body> |
|||
<BLANK LINE> |
|||
<footer> |
|||
``` |
|||
|
|||
The **header** is mandatory and the **scope** of the header is optional. |
|||
|
|||
### Revert |
|||
|
|||
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. In the body, it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted. |
|||
|
|||
### Type |
|||
|
|||
If the prefix is `feat`, `fix` or `perf`, it will appear in the changelog. However, if there is any [BREAKING CHANGE](#footer), the commit will always appear in the changelog. |
|||
|
|||
Other prefixes are up to your discretion. Suggested prefixes are `docs`, `chore`, `style`, `refactor`, and `test` for non-changelog related tasks. |
|||
|
|||
### Scope |
|||
|
|||
The scope could be anything specifying the place of the commit change. For example `dev`, `build`, `workflow`, `cli` etc... |
|||
|
|||
### Subject |
|||
|
|||
The subject contains a succinct description of the change: |
|||
|
|||
- use the imperative, present tense: "change" not "changed" nor "changes" |
|||
- don't capitalize the first letter |
|||
- no dot (.) at the end |
|||
|
|||
### Body |
|||
|
|||
Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes". The body should include the motivation for the change and contrast this with previous behavior. |
|||
|
|||
### Footer |
|||
|
|||
The footer should contain any information about **Breaking Changes** and is also the place to reference GitHub issues that this commit **Closes**. |
|||
|
|||
**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this. |
|||
@ -0,0 +1,39 @@ |
|||
# Prevent issues being created without using the template |
|||
blank_issues_enabled: false |
|||
checkIssueTemplate: true |
|||
checkPullRequestTemplate: true |
|||
|
|||
contact_links: |
|||
- name: 💬 Discord Chat |
|||
url: https://discord.gg/8GuAdwDhj6 |
|||
about: Ask questions and discuss with other Vben users in real time. |
|||
|
|||
- name: ❓ Questions & Discussions |
|||
url: https://github.com/@vbenjs/vue-vben-admin/discussions |
|||
about: Use GitHub discussions for message-board style questions and discussions. |
|||
|
|||
# Comment to be posted to on PRs from first time contributors in your repository |
|||
newPRWelcomeComment: | |
|||
💖 Thanks for opening this pull request! 💖 |
|||
Please be patient and we will get back to you as soon as we can. |
|||
|
|||
# Comment to be posted to on pull requests merged by a first time user |
|||
firstPRMergeComment: > |
|||
Thanks for your contribution! 🎉🎉🎉 |
|||
|
|||
|
|||
# Comment to be posted to on first time issues |
|||
newIssueWelcomeComment: > |
|||
Thanks for opening your first issue! Be sure to follow the issue template and provide every bit of information to help the developers! |
|||
|
|||
|
|||
# *OPTIONAL* default titles to check against for lack of descriptiveness |
|||
# MUST BE ALL LOWERCASE |
|||
requestInfoDefaultTitles: |
|||
- update readme.md |
|||
- updates |
|||
|
|||
# *Required* Comment to reply with |
|||
requestInfoReplyComment: > |
|||
Thanks for filing this issue/PR! It would be much appreciated if you could provide us with more information so we can effectively analyze the situation in context. |
|||
|
|||
@ -0,0 +1,40 @@ |
|||
# Vben Admin Contributing Guide |
|||
|
|||
Hi! We're really excited that you are interested in contributing to Vben Admin. Before submitting your contribution, please make sure to take a moment and read through the following guidelines: |
|||
|
|||
- [Pull Request Guidelines](#pull-request-guidelines) |
|||
|
|||
## Contributor Code of Conduct |
|||
|
|||
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. |
|||
|
|||
We are committed to making participation in this project a harassment-free experience for everyone, regardless of the level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion. |
|||
|
|||
Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. |
|||
|
|||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team. |
|||
|
|||
## Pull Request Guidelines |
|||
|
|||
- Checkout a topic branch from the relevant branch, e.g. main, and merge back against that branch. |
|||
|
|||
- If adding a new feature: |
|||
- Provide a convincing reason to add this feature. Ideally, you should open a suggestion issue first and have it approved before working on it. |
|||
|
|||
- If fixing bug: |
|||
- Provide a detailed description of the bug in the PR. Live demo preferred. |
|||
|
|||
- It's OK to have multiple small commits as you work on the PR - GitHub can automatically squash them before merging. |
|||
|
|||
## Development Setup |
|||
|
|||
You will need [pnpm](https://pnpm.io/) |
|||
|
|||
After cloning the repo, run: |
|||
|
|||
```bash |
|||
# install the dependencies of the project |
|||
$ pnpm install |
|||
# start the project |
|||
$ pnpm run dev |
|||
``` |
|||
@ -0,0 +1,17 @@ |
|||
version: 2 |
|||
updates: |
|||
- package-ecosystem: npm |
|||
directory: '/' |
|||
schedule: |
|||
interval: daily |
|||
groups: |
|||
non-breaking-changes: |
|||
update-types: [minor, patch] |
|||
|
|||
- package-ecosystem: github-actions |
|||
directory: '/' |
|||
schedule: |
|||
interval: weekly |
|||
groups: |
|||
non-breaking-changes: |
|||
update-types: [minor, patch] |
|||
@ -0,0 +1,33 @@ |
|||
## Description |
|||
|
|||
<!-- Please describe the change as necessary. If it's a feature or enhancement please be as detailed as possible. If it's a bug fix, please link the issue that it fixes or describe the bug in as much detail. |
|||
|
|||
--> |
|||
|
|||
<!-- You can also add additional context here --> |
|||
|
|||
## Type of change |
|||
|
|||
Please delete options that are not relevant. |
|||
|
|||
- [ ] Bug fix (non-breaking change which fixes an issue) |
|||
- [ ] New feature (non-breaking change which adds functionality) |
|||
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) |
|||
- [ ] This change requires a documentation update |
|||
- [ ] Please, don't make changes to `pnpm-lock.yaml` unless you introduce a new test example. |
|||
|
|||
## Checklist |
|||
|
|||
> ℹ️ Check all checkboxes - this will indicate that you have done everything in accordance with the rules in [CONTRIBUTING](contributing.md). |
|||
|
|||
- [ ] If you introduce new functionality, document it. You can run documentation with `pnpm run docs:dev` command. |
|||
- [ ] Run the tests with `pnpm test`. |
|||
- [ ] Changes in changelog are generated from PR name. Please, make sure that it explains your changes in an understandable manner. Please, prefix changeset messages with `feat:`, `fix:`, `perf:`, `docs:`, or `chore:`. |
|||
- [ ] My code follows the style guidelines of this project |
|||
- [ ] I have performed a self-review of my own code |
|||
- [ ] I have commented my code, particularly in hard-to-understand areas |
|||
- [ ] I have made corresponding changes to the documentation |
|||
- [ ] My changes generate no new warnings |
|||
- [ ] I have added tests that prove my fix is effective or that my feature works |
|||
- [ ] New and existing unit tests pass locally with my changes |
|||
- [ ] Any dependent changes have been merged and published in downstream modules |
|||
@ -0,0 +1,61 @@ |
|||
name-template: 'v$RESOLVED_VERSION' |
|||
tag-template: 'v$RESOLVED_VERSION' |
|||
version-template: $MAJOR.$MINOR.$PATCH |
|||
change-template: '* $TITLE (#$NUMBER) @$AUTHOR' |
|||
template: | |
|||
# What's Changed |
|||
|
|||
$CHANGES |
|||
|
|||
**Full Changelog**: https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION |
|||
|
|||
categories: |
|||
- title: '🚀 Features' |
|||
labels: |
|||
- 'feature' |
|||
- title: '🐞 Bug Fixes' |
|||
labels: |
|||
- 'bug' |
|||
- title: '📈 Performance & Enhancement' |
|||
labels: |
|||
- 'perf' |
|||
- 'enhancement' |
|||
- title: 📝 Documentation |
|||
labels: |
|||
- 'documentation' |
|||
- title: 👻 Maintenance |
|||
labels: |
|||
- 'chore' |
|||
- 'dependencies' |
|||
# collapse-after: 12 |
|||
- title: 🚦 Tests |
|||
labels: |
|||
- 'tests' |
|||
- title: 'Breaking' |
|||
label: 'breaking' |
|||
|
|||
version-resolver: |
|||
major: |
|||
labels: |
|||
- 'major' |
|||
- 'breaking' |
|||
minor: |
|||
labels: |
|||
- 'minor' |
|||
patch: |
|||
labels: |
|||
- 'feature' |
|||
- 'patch' |
|||
- 'bug' |
|||
- 'maintenance' |
|||
- 'docs' |
|||
- 'dependencies' |
|||
- 'security' |
|||
|
|||
exclude-labels: |
|||
- 'skip-changelog' |
|||
- 'no-changelog' |
|||
- 'changelog' |
|||
- 'bump versions' |
|||
- 'reverted' |
|||
- 'invalid' |
|||
@ -0,0 +1,13 @@ |
|||
titleAndCommits: true |
|||
types: |
|||
- feat |
|||
- fix |
|||
- docs |
|||
- chore |
|||
- style |
|||
- refactor |
|||
- perf |
|||
- test |
|||
- build |
|||
- ci |
|||
- revert |
|||
@ -0,0 +1,48 @@ |
|||
# name: Dependabot post-update |
|||
name: Build detection |
|||
on: |
|||
pull_request_target: |
|||
types: [opened, synchronize, reopened] |
|||
branches: |
|||
- main |
|||
|
|||
env: |
|||
HUSKY: '0' |
|||
|
|||
concurrency: |
|||
group: ${{ github.workflow }}-${{ github.event.pull_request.number }} |
|||
cancel-in-progress: true |
|||
|
|||
permissions: |
|||
contents: read |
|||
pull-requests: write |
|||
|
|||
jobs: |
|||
post-update: |
|||
if: github.repository == 'vbenjs/vue-vben-admin' |
|||
# if: ${{ github.actor == 'dependabot[bot]' }} |
|||
runs-on: ${{ matrix.os }} |
|||
strategy: |
|||
matrix: |
|||
os: |
|||
- ubuntu-latest |
|||
# - macos-latest |
|||
- windows-latest |
|||
steps: |
|||
- name: Checkout code |
|||
uses: actions/checkout@v6 |
|||
with: |
|||
fetch-depth: 0 |
|||
|
|||
- name: Checkout out pull request |
|||
env: |
|||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
|||
run: | |
|||
gh pr checkout ${{ github.event.pull_request.number }} |
|||
|
|||
- name: Setup Node |
|||
uses: ./.github/actions/setup-node |
|||
|
|||
- name: Build |
|||
run: | |
|||
pnpm run build |
|||
@ -0,0 +1,42 @@ |
|||
# https://github.com/changesets/action |
|||
name: Changeset version |
|||
|
|||
on: |
|||
workflow_dispatch: |
|||
pull_request: |
|||
types: |
|||
- closed |
|||
branches: |
|||
- main |
|||
|
|||
permissions: |
|||
pull-requests: write |
|||
contents: write |
|||
|
|||
env: |
|||
CI: true |
|||
|
|||
jobs: |
|||
version: |
|||
if: (github.event.pull_request.merged || github.event_name == 'workflow_dispatch') && github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') && github.repository == 'vbenjs/vue-vben-admin' |
|||
# if: github.repository == 'vbenjs/vue-vben-admin' |
|||
timeout-minutes: 15 |
|||
runs-on: ubuntu-latest |
|||
|
|||
steps: |
|||
- name: Checkout code |
|||
uses: actions/checkout@v6 |
|||
with: |
|||
fetch-depth: 0 |
|||
|
|||
- name: Setup Node |
|||
uses: ./.github/actions/setup-node |
|||
|
|||
- name: Create Release Pull Request |
|||
uses: changesets/action@v1 |
|||
with: |
|||
version: pnpm run version |
|||
commit: 'chore: bump versions' |
|||
title: 'chore: bump versions' |
|||
env: |
|||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
|||
@ -0,0 +1,125 @@ |
|||
name: CI |
|||
|
|||
on: |
|||
pull_request: |
|||
push: |
|||
branches: |
|||
- main |
|||
- 'releases/*' |
|||
|
|||
permissions: |
|||
contents: read |
|||
|
|||
env: |
|||
CI: true |
|||
TZ: Asia/Shanghai |
|||
|
|||
jobs: |
|||
test: |
|||
name: Test |
|||
if: github.repository == 'vbenjs/vue-vben-admin' |
|||
runs-on: ${{ matrix.os }} |
|||
strategy: |
|||
matrix: |
|||
os: |
|||
- ubuntu-latest |
|||
# - macos-latest |
|||
- windows-latest |
|||
timeout-minutes: 20 |
|||
steps: |
|||
- name: Checkout code |
|||
uses: actions/checkout@v6 |
|||
with: |
|||
fetch-depth: 0 |
|||
|
|||
- name: Install pnpm |
|||
uses: pnpm/action-setup@v4 |
|||
with: |
|||
run_install: false |
|||
|
|||
- name: Setup Node |
|||
uses: ./.github/actions/setup-node |
|||
|
|||
# - name: Check Git version |
|||
# run: git --version |
|||
|
|||
# - name: Setup mock Git user |
|||
# run: git config --global user.email "you@example.com" && git config --global user.name "Your Name" |
|||
|
|||
- name: Vitest tests |
|||
run: pnpm run test:unit |
|||
|
|||
# - name: Upload coverage |
|||
# uses: codecov/codecov-action@v4 |
|||
# with: |
|||
# token: ${{ secrets.CODECOV_TOKEN }} |
|||
|
|||
lint: |
|||
name: Lint |
|||
if: github.repository == 'vbenjs/vue-vben-admin' |
|||
runs-on: ${{ matrix.os }} |
|||
strategy: |
|||
matrix: |
|||
os: |
|||
- ubuntu-latest |
|||
# - macos-latest |
|||
- windows-latest |
|||
|
|||
steps: |
|||
- name: Checkout code |
|||
uses: actions/checkout@v6 |
|||
with: |
|||
fetch-depth: 0 |
|||
|
|||
- name: Setup Node |
|||
uses: ./.github/actions/setup-node |
|||
|
|||
- name: Lint |
|||
run: pnpm run lint |
|||
|
|||
check: |
|||
name: Check |
|||
if: github.repository == 'vbenjs/vue-vben-admin' |
|||
runs-on: ${{ matrix.os }} |
|||
timeout-minutes: 20 |
|||
strategy: |
|||
matrix: |
|||
os: |
|||
- ubuntu-latest |
|||
# - macos-latest |
|||
- windows-latest |
|||
steps: |
|||
- name: Checkout code |
|||
uses: actions/checkout@v6 |
|||
with: |
|||
fetch-depth: 0 |
|||
|
|||
- name: Setup Node |
|||
uses: ./.github/actions/setup-node |
|||
|
|||
- name: Typecheck |
|||
run: pnpm check:type |
|||
|
|||
# From https://github.com/rhysd/actionlint/blob/main/docs/usage.md#use-actionlint-on-github-actions |
|||
- name: Check workflow files |
|||
if: runner.os == 'Linux' |
|||
run: | |
|||
bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) |
|||
./actionlint -color -shellcheck="" |
|||
|
|||
ci-ok: |
|||
name: CI OK |
|||
if: github.repository == 'vbenjs/vue-vben-admin' |
|||
runs-on: ubuntu-latest |
|||
needs: [test, check, lint] |
|||
env: |
|||
FAILURE: ${{ contains(join(needs.*.result, ','), 'failure') }} |
|||
steps: |
|||
- name: Check for failure |
|||
run: | |
|||
echo $FAILURE |
|||
if [ "$FAILURE" = "false" ]; then |
|||
exit 0 |
|||
else |
|||
exit 1 |
|||
fi |
|||
@ -0,0 +1,94 @@ |
|||
# For most projects, this workflow file will not need changing; you simply need |
|||
# to commit it to your repository. |
|||
# |
|||
# You may wish to alter this file to override the set of languages analyzed, |
|||
# or to provide custom queries or build logic. |
|||
# |
|||
# ******** NOTE ******** |
|||
# We have attempted to detect the languages in your repository. Please check |
|||
# the `language` matrix defined below to confirm you have the correct set of |
|||
# supported CodeQL languages. |
|||
# |
|||
name: 'CodeQL' |
|||
|
|||
on: |
|||
push: |
|||
branches: ['main'] |
|||
pull_request: |
|||
branches: ['main'] |
|||
schedule: |
|||
- cron: '35 0 * * 0' |
|||
|
|||
jobs: |
|||
analyze: |
|||
name: Analyze (${{ matrix.language }}) |
|||
if: github.repository == 'vbenjs/vue-vben-admin' |
|||
# Runner size impacts CodeQL analysis time. To learn more, please see: |
|||
# - https://gh.io/recommended-hardware-resources-for-running-codeql |
|||
# - https://gh.io/supported-runners-and-hardware-resources |
|||
# - https://gh.io/using-larger-runners (GitHub.com only) |
|||
# Consider using larger runners or machines with greater resources for possible analysis time improvements. |
|||
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} |
|||
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} |
|||
permissions: |
|||
# required for all workflows |
|||
security-events: write |
|||
|
|||
# required to fetch internal or private CodeQL packs |
|||
packages: read |
|||
|
|||
# only required for workflows in private repositories |
|||
actions: read |
|||
contents: read |
|||
|
|||
strategy: |
|||
fail-fast: false |
|||
matrix: |
|||
include: |
|||
- language: javascript-typescript |
|||
build-mode: none |
|||
# CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' |
|||
# Use `c-cpp` to analyze code written in C, C++ or both |
|||
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both |
|||
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both |
|||
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, |
|||
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. |
|||
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how |
|||
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages |
|||
steps: |
|||
- name: Checkout repository |
|||
uses: actions/checkout@v6 |
|||
|
|||
# Initializes the CodeQL tools for scanning. |
|||
- name: Initialize CodeQL |
|||
uses: github/codeql-action/init@v3 |
|||
with: |
|||
languages: ${{ matrix.language }} |
|||
build-mode: ${{ matrix.build-mode }} |
|||
# If you wish to specify custom queries, you can do so here or in a config file. |
|||
# By default, queries listed here will override any specified in a config file. |
|||
# Prefix the list here with "+" to use these queries and those in the config file. |
|||
|
|||
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs |
|||
# queries: security-extended,security-and-quality |
|||
|
|||
# If the analyze step fails for one of the languages you are analyzing with |
|||
# "We were unable to automatically build your code", modify the matrix above |
|||
# to set the build mode to "manual" for that language. Then modify this step |
|||
# to build your code. |
|||
# ℹ️ Command-line programs to run using the OS shell. |
|||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun |
|||
- if: matrix.build-mode == 'manual' |
|||
shell: bash |
|||
run: | |
|||
echo 'If you are using a "manual" build mode for one or more of the' \ |
|||
'languages you are analyzing, replace this with the commands to build' \ |
|||
'your code, for example:' |
|||
echo ' make bootstrap' |
|||
echo ' make release' |
|||
exit 1 |
|||
|
|||
- name: Perform CodeQL Analysis |
|||
uses: github/codeql-action/analyze@v3 |
|||
with: |
|||
category: '/language:${{matrix.language}}' |
|||
@ -0,0 +1,172 @@ |
|||
name: Deploy Website on push |
|||
|
|||
on: |
|||
push: |
|||
branches: |
|||
- main |
|||
|
|||
jobs: |
|||
deploy-playground-ftp: |
|||
name: Deploy Push Playground Ftp |
|||
if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') && github.repository == 'vbenjs/vue-vben-admin' |
|||
runs-on: ubuntu-latest |
|||
steps: |
|||
- name: Checkout code |
|||
uses: actions/checkout@v6 |
|||
with: |
|||
fetch-depth: 0 |
|||
|
|||
- name: Sed Config Base |
|||
shell: bash |
|||
run: | |
|||
sed -i "s#VITE_COMPRESS\s*=.*#VITE_COMPRESS = gzip#g" ./playground/.env.production |
|||
sed -i "s#VITE_PWA\s*=.*#VITE_PWA = true#g" ./playground/.env.production |
|||
cat ./playground/.env.production |
|||
|
|||
- name: Setup Node |
|||
uses: ./.github/actions/setup-node |
|||
|
|||
- name: Build |
|||
run: pnpm build:play |
|||
|
|||
- name: Sync Playground files |
|||
uses: SamKirkland/FTP-Deploy-Action@v4.3.6 |
|||
with: |
|||
server: ${{ secrets.PRO_FTP_HOST }} |
|||
username: ${{ secrets.WEB_PLAYGROUND_FTP_ACCOUNT }} |
|||
password: ${{ secrets.WEB_PLAYGROUND_FTP_PWSSWORD }} |
|||
local-dir: ./playground/dist/ |
|||
|
|||
deploy-docs-ftp: |
|||
name: Deploy Push Docs Ftp |
|||
if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') && github.repository == 'vbenjs/vue-vben-admin' |
|||
runs-on: ubuntu-latest |
|||
steps: |
|||
- name: Checkout code |
|||
uses: actions/checkout@v6 |
|||
with: |
|||
fetch-depth: 0 |
|||
|
|||
- name: Setup Node |
|||
uses: ./.github/actions/setup-node |
|||
|
|||
- name: Build |
|||
run: pnpm build:docs |
|||
|
|||
- name: Sync Docs files |
|||
uses: SamKirkland/FTP-Deploy-Action@v4.3.6 |
|||
with: |
|||
server: ${{ secrets.PRO_FTP_HOST }} |
|||
username: ${{ secrets.WEBSITE_FTP_ACCOUNT }} |
|||
password: ${{ secrets.WEBSITE_FTP_PASSWORD }} |
|||
local-dir: ./docs/.vitepress/dist/ |
|||
|
|||
deploy-antd-ftp: |
|||
name: Deploy Push Antd Ftp |
|||
if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') && github.repository == 'vbenjs/vue-vben-admin' |
|||
runs-on: ubuntu-latest |
|||
steps: |
|||
- name: Checkout code |
|||
uses: actions/checkout@v6 |
|||
with: |
|||
fetch-depth: 0 |
|||
|
|||
- name: Sed Config Base |
|||
shell: bash |
|||
run: | |
|||
sed -i "s#VITE_COMPRESS\s*=.*#VITE_COMPRESS = gzip#g" ./apps/web-antd/.env.production |
|||
sed -i "s#VITE_PWA\s*=.*#VITE_PWA = true#g" ./apps/web-antd/.env.production |
|||
cat ./apps/web-antd/.env.production |
|||
|
|||
- name: Setup Node |
|||
uses: ./.github/actions/setup-node |
|||
|
|||
- name: Build |
|||
run: pnpm run build:antd |
|||
|
|||
- name: Sync files |
|||
uses: SamKirkland/FTP-Deploy-Action@v4.3.6 |
|||
with: |
|||
server: ${{ secrets.PRO_FTP_HOST }} |
|||
username: ${{ secrets.WEB_ANTD_FTP_ACCOUNT }} |
|||
password: ${{ secrets.WEB_ANTD_FTP_PASSWORD }} |
|||
local-dir: ./apps/web-antd/dist/ |
|||
|
|||
deploy-ele-ftp: |
|||
name: Deploy Push Element Ftp |
|||
if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') && github.repository == 'vbenjs/vue-vben-admin' |
|||
runs-on: ubuntu-latest |
|||
steps: |
|||
- name: Checkout code |
|||
uses: actions/checkout@v6 |
|||
with: |
|||
fetch-depth: 0 |
|||
|
|||
- name: Sed Config Base |
|||
shell: bash |
|||
run: | |
|||
sed -i "s#VITE_COMPRESS\s*=.*#VITE_COMPRESS = gzip#g" ./apps/web-ele/.env.production |
|||
sed -i "s#VITE_PWA\s*=.*#VITE_PWA = true#g" ./apps/web-ele/.env.production |
|||
cat ./apps/web-ele/.env.production |
|||
|
|||
- name: Setup Node |
|||
uses: ./.github/actions/setup-node |
|||
|
|||
- name: Build |
|||
run: pnpm run build:ele |
|||
|
|||
- name: Sync files |
|||
uses: SamKirkland/FTP-Deploy-Action@v4.3.6 |
|||
with: |
|||
server: ${{ secrets.PRO_FTP_HOST }} |
|||
username: ${{ secrets.WEB_ELE_FTP_ACCOUNT }} |
|||
password: ${{ secrets.WEB_ELE_FTP_PASSWORD }} |
|||
local-dir: ./apps/web-ele/dist/ |
|||
|
|||
deploy-naive-ftp: |
|||
name: Deploy Push Naive Ftp |
|||
if: github.actor != 'dependabot[bot]' && !contains(github.event.head_commit.message, '[skip ci]') && github.repository == 'vbenjs/vue-vben-admin' |
|||
runs-on: ubuntu-latest |
|||
steps: |
|||
- name: Checkout code |
|||
uses: actions/checkout@v6 |
|||
with: |
|||
fetch-depth: 0 |
|||
|
|||
- name: Sed Config Base |
|||
shell: bash |
|||
run: | |
|||
sed -i "s#VITE_COMPRESS\s*=.*#VITE_COMPRESS = gzip#g" ./apps/web-naive/.env.production |
|||
sed -i "s#VITE_PWA\s*=.*#VITE_PWA = true#g" ./apps/web-naive/.env.production |
|||
cat ./apps/web-naive/.env.production |
|||
|
|||
- name: Setup Node |
|||
uses: ./.github/actions/setup-node |
|||
|
|||
- name: Build |
|||
run: pnpm run build:naive |
|||
|
|||
- name: Sync files |
|||
uses: SamKirkland/FTP-Deploy-Action@v4.3.6 |
|||
with: |
|||
server: ${{ secrets.PRO_FTP_HOST }} |
|||
username: ${{ secrets.WEB_NAIVE_FTP_ACCOUNT }} |
|||
password: ${{ secrets.WEB_NAIVE_FTP_PASSWORD }} |
|||
local-dir: ./apps/web-naive/dist/ |
|||
|
|||
rerun-on-failure: |
|||
name: Rerun on failure |
|||
needs: |
|||
- deploy-playground-ftp |
|||
- deploy-docs-ftp |
|||
- deploy-antd-ftp |
|||
- deploy-ele-ftp |
|||
- deploy-naive-ftp |
|||
if: failure() && fromJSON(github.run_attempt) < 10 |
|||
runs-on: ubuntu-latest |
|||
steps: |
|||
- name: Retry ${{ fromJSON(github.run_attempt) }} of 10 |
|||
env: |
|||
GH_REPO: ${{ github.repository }} |
|||
GH_TOKEN: ${{ github.token }} |
|||
run: gh workflow run rerun.yml -F run_id=${{ github.run_id }} |
|||
@ -0,0 +1,25 @@ |
|||
name: Release Drafter |
|||
|
|||
on: |
|||
push: |
|||
branches: |
|||
- main |
|||
|
|||
permissions: |
|||
contents: read |
|||
pull-requests: write |
|||
|
|||
jobs: |
|||
update_release_draft: |
|||
permissions: |
|||
# write permission is required to create a github release |
|||
contents: write |
|||
# write permission is required for autolabeler |
|||
# otherwise, read permission is required at least |
|||
pull-requests: write |
|||
if: github.repository == 'vbenjs/vue-vben-admin' |
|||
runs-on: ubuntu-latest |
|||
steps: |
|||
- uses: release-drafter/release-drafter@v6 |
|||
env: |
|||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
|||
@ -0,0 +1,31 @@ |
|||
# 每天零点运行一次,它会检查所有带有 "need reproduction" 标签的 Issues。如果这些 Issues 在过去的 3 天内没有任何活动,它们将会被自动关闭。这有助于保持 Issue 列表的整洁,并且提醒用户在必要时提供更多的信息。 |
|||
name: Issue Close Require |
|||
|
|||
# 触发条件:每天零点 |
|||
on: |
|||
workflow_dispatch: |
|||
schedule: |
|||
- cron: '0 0 * * *' |
|||
|
|||
permissions: |
|||
pull-requests: write |
|||
contents: write |
|||
issues: write |
|||
|
|||
jobs: |
|||
close-issues: |
|||
if: github.repository == 'vbenjs/vue-vben-admin' |
|||
runs-on: ubuntu-latest |
|||
steps: |
|||
# 关闭未活动的 Issues |
|||
- name: Close Inactive Issues |
|||
uses: actions/stale@v9 |
|||
with: |
|||
days-before-stale: -1 # Issues and PR will never be flagged stale automatically. |
|||
stale-issue-label: needs-reproduction # Label that flags an issue as stale. |
|||
only-labels: needs-reproduction # Only process these issues |
|||
days-before-issue-close: 3 |
|||
ignore-updates: true |
|||
remove-stale-when-updated: false |
|||
close-issue-message: This issue was closed because it was open for 3 days without a valid reproduction. |
|||
close-issue-label: closed-by-action |
|||
@ -0,0 +1,46 @@ |
|||
name: Label Based Actions |
|||
|
|||
on: |
|||
issues: |
|||
types: [labeled] |
|||
# pull_request: |
|||
# types: [labeled] |
|||
|
|||
permissions: |
|||
issues: write |
|||
pull-requests: write |
|||
contents: write |
|||
|
|||
jobs: |
|||
reply-labeled: |
|||
if: github.repository == 'vbenjs/vue-vben-admin' |
|||
runs-on: ubuntu-latest |
|||
steps: |
|||
- name: remove enhancement pending |
|||
if: github.event.label.name == 'enhancement' |
|||
uses: actions-cool/issues-helper@v3 |
|||
with: |
|||
actions: 'remove-labels' |
|||
token: ${{ secrets.GITHUB_TOKEN }} |
|||
issue-number: ${{ github.event.issue.number }} |
|||
labels: 'enhancement: pending triage' |
|||
|
|||
- name: remove bug pending |
|||
if: github.event.label.name == 'bug' |
|||
uses: actions-cool/issues-helper@v3 |
|||
with: |
|||
actions: 'remove-labels' |
|||
token: ${{ secrets.GITHUB_TOKEN }} |
|||
issue-number: ${{ github.event.issue.number }} |
|||
labels: 'bug: pending triage' |
|||
|
|||
- name: needs reproduction |
|||
if: github.event.label.name == 'needs reproduction' |
|||
uses: actions-cool/issues-helper@v3 |
|||
with: |
|||
actions: 'create-comment, remove-labels' |
|||
token: ${{ secrets.GITHUB_TOKEN }} |
|||
issue-number: ${{ github.event.issue.number }} |
|||
body: | |
|||
Hello @${{ github.event.issue.user.login }}. Please provide the complete reproduction steps and code. Issues labeled by `needs reproduction` will be closed if no activities in 3 days. |
|||
labels: 'bug: pending triage' |
|||
@ -0,0 +1,24 @@ |
|||
name: Lock Threads |
|||
|
|||
on: |
|||
schedule: |
|||
- cron: '0 0 * * *' |
|||
workflow_dispatch: |
|||
|
|||
permissions: |
|||
issues: write |
|||
pull-requests: write |
|||
|
|||
jobs: |
|||
action: |
|||
if: github.repository == 'vbenjs/vue-vben-admin' |
|||
runs-on: ubuntu-latest |
|||
steps: |
|||
- uses: dessant/lock-threads@v5 |
|||
with: |
|||
github-token: ${{ secrets.GITHUB_TOKEN }} |
|||
issue-inactive-days: '14' |
|||
issue-lock-reason: '' |
|||
pr-inactive-days: '30' |
|||
pr-lock-reason: '' |
|||
process-only: 'issues, prs' |
|||
@ -0,0 +1,80 @@ |
|||
name: Create Release Tag |
|||
|
|||
on: |
|||
push: |
|||
tags: |
|||
- 'v*.*.*' # Push events to matching v*, i.e. v1.0, v20.15.10 |
|||
|
|||
env: |
|||
HUSKY: '0' |
|||
|
|||
permissions: |
|||
pull-requests: write |
|||
contents: write |
|||
|
|||
jobs: |
|||
build: |
|||
name: Create Release |
|||
if: github.repository == 'vbenjs/vue-vben-admin' |
|||
runs-on: ubuntu-latest |
|||
strategy: |
|||
matrix: |
|||
node-version: [22] |
|||
steps: |
|||
- name: Checkout code |
|||
uses: actions/checkout@v6 |
|||
with: |
|||
fetch-depth: 0 |
|||
|
|||
# - name: Checkout code |
|||
# uses: actions/checkout@v6 |
|||
# with: |
|||
# fetch-depth: 0 |
|||
|
|||
# - name: Install pnpm |
|||
# uses: pnpm/action-setup@v4 |
|||
|
|||
# - name: Use Node.js ${{ matrix.node-version }} |
|||
# uses: actions/setup-node@v4 |
|||
# with: |
|||
# node-version: ${{ matrix.node-version }} |
|||
# cache: "pnpm" |
|||
|
|||
# - name: Install dependencies |
|||
# run: pnpm install --frozen-lockfile |
|||
|
|||
# - name: Test and Build |
|||
# run: | |
|||
# pnpm run test |
|||
# pnpm run build |
|||
|
|||
- name: version |
|||
id: version |
|||
run: | |
|||
tag=${GITHUB_REF/refs\/tags\//} |
|||
version=${tag#v} |
|||
major=${version%%.*} |
|||
echo "tag=${tag}" >> $GITHUB_OUTPUT |
|||
echo "version=${version}" >> $GITHUB_OUTPUT |
|||
echo "major=${major}" >> $GITHUB_OUTPUT |
|||
|
|||
- uses: release-drafter/release-drafter@v6 |
|||
with: |
|||
version: ${{ steps.version.outputs.version }} |
|||
publish: true |
|||
env: |
|||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
|||
|
|||
# - name: force update major tag |
|||
# run: | |
|||
# git tag v${{ steps.version.outputs.major }} ${{ steps.version.outputs.tag }} -f |
|||
# git push origin refs/tags/v${{ steps.version.outputs.major }} -f |
|||
|
|||
# - name: Create Release for Tag |
|||
# id: release_tag |
|||
# uses: ncipollo/release-action@v1 |
|||
# with: |
|||
# token: ${{ secrets.GITHUB_TOKEN }} |
|||
# generateReleaseNotes: "true" |
|||
# body: | |
|||
# > Please refer to [CHANGELOG.md](https://github.com/vbenjs/vue-vben-admin/blob/main/CHANGELOG.md) for details. |
|||
@ -0,0 +1,19 @@ |
|||
name: Rerun workflow |
|||
|
|||
on: |
|||
workflow_dispatch: |
|||
inputs: |
|||
run_id: |
|||
description: The workflow id to relanch |
|||
required: true |
|||
jobs: |
|||
rerun: |
|||
runs-on: ubuntu-latest |
|||
steps: |
|||
- name: rerun ${{ inputs.run_id }} |
|||
env: |
|||
GH_REPO: ${{ github.repository }} |
|||
GH_TOKEN: ${{ github.token }} |
|||
run: | |
|||
gh run watch ${{ inputs.run_id }} > /dev/null 2>&1 |
|||
gh run rerun ${{ inputs.run_id }} --failed |
|||
@ -0,0 +1,41 @@ |
|||
name: Semantic Pull Request |
|||
|
|||
on: |
|||
pull_request_target: |
|||
types: |
|||
- opened |
|||
- edited |
|||
- synchronize |
|||
|
|||
jobs: |
|||
main: |
|||
name: Semantic Pull Request |
|||
if: github.repository == 'vbenjs/vue-vben-admin' |
|||
runs-on: ubuntu-latest |
|||
steps: |
|||
- name: Validate PR title |
|||
uses: amannn/action-semantic-pull-request@v5 |
|||
with: |
|||
wip: true |
|||
subjectPattern: ^(?![A-Z]).+$ |
|||
subjectPatternError: | |
|||
The subject "{subject}" found in the pull request title "{title}" |
|||
didn't match the configured pattern. Please ensure that the subject |
|||
doesn't start with an uppercase character. |
|||
requireScope: false |
|||
types: | |
|||
fix |
|||
feat |
|||
docs |
|||
style |
|||
refactor |
|||
perf |
|||
test |
|||
build |
|||
ci |
|||
chore |
|||
revert |
|||
types |
|||
release |
|||
env: |
|||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
|||
@ -0,0 +1,19 @@ |
|||
name: 'Close stale issues' |
|||
|
|||
on: |
|||
schedule: |
|||
- cron: '0 1 * * *' |
|||
|
|||
jobs: |
|||
stale: |
|||
if: github.repository == 'vbenjs/vue-vben-admin' |
|||
runs-on: ubuntu-latest |
|||
steps: |
|||
- uses: actions/stale@v9 |
|||
with: |
|||
repo-token: ${{ secrets.GITHUB_TOKEN }} |
|||
stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days' |
|||
stale-pr-message: 'This PR is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days' |
|||
exempt-issue-labels: 'bug,enhancement' |
|||
days-before-stale: 60 |
|||
days-before-close: 7 |
|||
@ -0,0 +1,30 @@ |
|||
{ |
|||
"recommendations": [ |
|||
// Vue 3 的语言支持 |
|||
"Vue.volar", |
|||
// 将 ESLint JavaScript 集成到 VS Code 中。 |
|||
"dbaeumer.vscode-eslint", |
|||
// Visual Studio Code 的官方 Stylelint 扩展 |
|||
"stylelint.vscode-stylelint", |
|||
// 使用 Prettier 的代码格式化程序 |
|||
"esbenp.prettier-vscode", |
|||
// 支持 dotenv 文件语法 |
|||
"mikestead.dotenv", |
|||
// 源代码的拼写检查器 |
|||
"streetsidesoftware.code-spell-checker", |
|||
// Tailwind CSS 的官方 VS Code 插件 |
|||
"bradlc.vscode-tailwindcss", |
|||
// iconify 图标插件 |
|||
"antfu.iconify", |
|||
// i18n 插件 |
|||
"Lokalise.i18n-ally", |
|||
// CSS 变量提示 |
|||
"vunguyentuan.vscode-css-variables", |
|||
// 在 package.json 中显示 PNPM catalog 的版本 |
|||
"antfu.pnpm-catalog-lens" |
|||
], |
|||
"unwantedRecommendations": [ |
|||
// 和 volar 冲突 |
|||
"octref.vetur" |
|||
] |
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
{ |
|||
"import": { |
|||
"scope": "javascript,typescript", |
|||
"prefix": "im", |
|||
"body": ["import { $2 } from '$1';"], |
|||
"description": "Import a module", |
|||
}, |
|||
"export-all": { |
|||
"scope": "javascript,typescript", |
|||
"prefix": "ex", |
|||
"body": ["export * from '$1';"], |
|||
"description": "Export a module", |
|||
}, |
|||
"vue-script-setup": { |
|||
"scope": "vue", |
|||
"prefix": "<sc", |
|||
"body": [ |
|||
"<script setup lang=\"ts\">", |
|||
"const props = defineProps<{", |
|||
" modelValue?: boolean,", |
|||
"}>()", |
|||
"$1", |
|||
"</script>", |
|||
"", |
|||
"<template>", |
|||
" <div>", |
|||
" <slot/>", |
|||
" </div>", |
|||
"</template>", |
|||
], |
|||
}, |
|||
"vue-computed": { |
|||
"scope": "javascript,typescript,vue", |
|||
"prefix": "com", |
|||
"body": ["computed(() => { $1 })"], |
|||
}, |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
{ |
|||
"$schema": "https://json.schemastore.org/launchsettings.json", |
|||
"version": "0.2.0", |
|||
"configurations": [ |
|||
{ |
|||
"type": "chrome", |
|||
"name": "vben admin playground dev", |
|||
"request": "launch", |
|||
"url": "http://localhost:5555", |
|||
"env": { "NODE_ENV": "development" }, |
|||
"sourceMaps": true, |
|||
"webRoot": "${workspaceFolder}/playground" |
|||
}, |
|||
{ |
|||
"type": "chrome", |
|||
"name": "vben admin antd dev", |
|||
"request": "launch", |
|||
"url": "http://localhost:5666", |
|||
"env": { "NODE_ENV": "development" }, |
|||
"sourceMaps": true, |
|||
"webRoot": "${workspaceFolder}/apps/web-antd" |
|||
}, |
|||
{ |
|||
"type": "chrome", |
|||
"name": "vben admin ele dev", |
|||
"request": "launch", |
|||
"url": "http://localhost:5777", |
|||
"env": { "NODE_ENV": "development" }, |
|||
"sourceMaps": true, |
|||
"webRoot": "${workspaceFolder}/apps/web-ele" |
|||
}, |
|||
{ |
|||
"type": "chrome", |
|||
"name": "vben admin naive dev", |
|||
"request": "launch", |
|||
"url": "http://localhost:5888", |
|||
"env": { "NODE_ENV": "development" }, |
|||
"sourceMaps": true, |
|||
"webRoot": "${workspaceFolder}/apps/web-naive" |
|||
} |
|||
] |
|||
} |
|||
@ -0,0 +1,231 @@ |
|||
{ |
|||
"tailwindCSS.experimental.configFile": "internal/tailwind-config/src/index.ts", |
|||
// workbench |
|||
"workbench.list.smoothScrolling": true, |
|||
"workbench.startupEditor": "newUntitledFile", |
|||
"workbench.tree.indent": 10, |
|||
"workbench.editor.highlightModifiedTabs": true, |
|||
"workbench.editor.closeOnFileDelete": true, |
|||
"workbench.editor.limit.enabled": true, |
|||
"workbench.editor.limit.perEditorGroup": true, |
|||
"workbench.editor.limit.value": 5, |
|||
|
|||
// editor |
|||
"editor.tabSize": 2, |
|||
"editor.detectIndentation": false, |
|||
"editor.cursorBlinking": "expand", |
|||
"editor.largeFileOptimizations": true, |
|||
"editor.accessibilitySupport": "off", |
|||
"editor.cursorSmoothCaretAnimation": "on", |
|||
"editor.guides.bracketPairs": "active", |
|||
"editor.inlineSuggest.enabled": true, |
|||
"editor.suggestSelection": "recentlyUsedByPrefix", |
|||
"editor.acceptSuggestionOnEnter": "smart", |
|||
"editor.suggest.snippetsPreventQuickSuggestions": false, |
|||
"editor.stickyScroll.enabled": true, |
|||
"editor.hover.sticky": true, |
|||
"editor.suggest.insertMode": "replace", |
|||
"editor.bracketPairColorization.enabled": true, |
|||
"editor.autoClosingBrackets": "beforeWhitespace", |
|||
"editor.autoClosingDelete": "always", |
|||
"editor.autoClosingOvertype": "always", |
|||
"editor.autoClosingQuotes": "beforeWhitespace", |
|||
"editor.wordSeparators": "`~!@#%^&*()=+[{]}\\|;:'\",.<>/?", |
|||
"editor.codeActionsOnSave": { |
|||
"source.fixAll.eslint": "explicit", |
|||
"source.fixAll.stylelint": "explicit", |
|||
"source.organizeImports": "never" |
|||
}, |
|||
"editor.defaultFormatter": "esbenp.prettier-vscode", |
|||
"[html]": { |
|||
"editor.defaultFormatter": "esbenp.prettier-vscode" |
|||
}, |
|||
"[css]": { |
|||
"editor.defaultFormatter": "esbenp.prettier-vscode" |
|||
}, |
|||
"[scss]": { |
|||
"editor.defaultFormatter": "esbenp.prettier-vscode" |
|||
}, |
|||
"[javascript]": { |
|||
"editor.defaultFormatter": "esbenp.prettier-vscode" |
|||
}, |
|||
"[typescript]": { |
|||
"editor.defaultFormatter": "esbenp.prettier-vscode" |
|||
}, |
|||
"[json]": { |
|||
"editor.defaultFormatter": "esbenp.prettier-vscode" |
|||
}, |
|||
"[markdown]": { |
|||
"editor.defaultFormatter": "esbenp.prettier-vscode" |
|||
}, |
|||
"[jsonc]": { |
|||
"editor.defaultFormatter": "esbenp.prettier-vscode" |
|||
}, |
|||
"[vue]": { |
|||
"editor.defaultFormatter": "esbenp.prettier-vscode" |
|||
}, |
|||
// extensions |
|||
"extensions.ignoreRecommendations": true, |
|||
|
|||
// terminal |
|||
"terminal.integrated.cursorBlinking": true, |
|||
"terminal.integrated.persistentSessionReviveProcess": "never", |
|||
"terminal.integrated.tabs.enabled": true, |
|||
"terminal.integrated.scrollback": 10000, |
|||
"terminal.integrated.stickyScroll.enabled": true, |
|||
|
|||
// files |
|||
"files.eol": "\n", |
|||
"files.insertFinalNewline": true, |
|||
"files.simpleDialog.enable": true, |
|||
"files.associations": { |
|||
"*.ejs": "html", |
|||
"*.art": "html", |
|||
"**/tsconfig.json": "jsonc", |
|||
"*.json": "jsonc", |
|||
"package.json": "json" |
|||
}, |
|||
|
|||
"files.exclude": { |
|||
"**/.eslintcache": true, |
|||
"**/bower_components": true, |
|||
"**/.turbo": true, |
|||
"**/.idea": true, |
|||
"**/.vitepress": true, |
|||
"**/tmp": true, |
|||
"**/.git": true, |
|||
"**/.svn": true, |
|||
"**/.hg": true, |
|||
"**/CVS": true, |
|||
"**/.stylelintcache": true, |
|||
"**/.DS_Store": true, |
|||
"**/vite.config.mts.*": true, |
|||
"**/tea.yaml": true |
|||
}, |
|||
"files.watcherExclude": { |
|||
"**/.git/objects/**": true, |
|||
"**/.git/subtree-cache/**": true, |
|||
"**/.vscode/**": true, |
|||
"**/node_modules/**": true, |
|||
"**/tmp/**": true, |
|||
"**/bower_components/**": true, |
|||
"**/dist/**": true, |
|||
"**/yarn.lock": true |
|||
}, |
|||
|
|||
"typescript.tsserver.exclude": ["**/node_modules", "**/dist", "**/.turbo"], |
|||
|
|||
// search |
|||
"search.searchEditor.singleClickBehaviour": "peekDefinition", |
|||
"search.followSymlinks": false, |
|||
// 在使用搜索功能时,将这些文件夹/文件排除在外 |
|||
"search.exclude": { |
|||
"**/node_modules": true, |
|||
"**/*.log": true, |
|||
"**/*.log*": true, |
|||
"**/bower_components": true, |
|||
"**/dist": true, |
|||
"**/elehukouben": true, |
|||
"**/.git": true, |
|||
"**/.github": true, |
|||
"**/.gitignore": true, |
|||
"**/.svn": true, |
|||
"**/.DS_Store": true, |
|||
"**/.vitepress/cache": true, |
|||
"**/.idea": true, |
|||
"**/.vscode": false, |
|||
"**/.yarn": true, |
|||
"**/tmp": true, |
|||
"*.xml": true, |
|||
"out": true, |
|||
"dist": true, |
|||
"node_modules": true, |
|||
"CHANGELOG.md": true, |
|||
"**/pnpm-lock.yaml": true, |
|||
"**/yarn.lock": true |
|||
}, |
|||
|
|||
"debug.onTaskErrors": "debugAnyway", |
|||
"diffEditor.ignoreTrimWhitespace": false, |
|||
"npm.packageManager": "pnpm", |
|||
|
|||
"css.validate": false, |
|||
"less.validate": false, |
|||
"scss.validate": false, |
|||
|
|||
// extension |
|||
"emmet.showSuggestionsAsSnippets": true, |
|||
"emmet.triggerExpansionOnTab": false, |
|||
|
|||
"errorLens.enabledDiagnosticLevels": ["warning", "error"], |
|||
"errorLens.excludeBySource": ["cSpell", "Grammarly", "eslint"], |
|||
|
|||
"stylelint.enable": true, |
|||
"stylelint.packageManager": "pnpm", |
|||
"stylelint.validate": ["css", "less", "postcss", "scss", "vue"], |
|||
"stylelint.customSyntax": "postcss-html", |
|||
"stylelint.snippet": ["css", "less", "postcss", "scss", "vue"], |
|||
|
|||
"typescript.inlayHints.enumMemberValues.enabled": true, |
|||
"typescript.preferences.preferTypeOnlyAutoImports": true, |
|||
"typescript.preferences.includePackageJsonAutoImports": "on", |
|||
|
|||
"eslint.validate": [ |
|||
"javascript", |
|||
"typescript", |
|||
"javascriptreact", |
|||
"typescriptreact", |
|||
"vue", |
|||
"html", |
|||
"markdown", |
|||
"json", |
|||
"jsonc", |
|||
"json5", |
|||
"yaml" |
|||
], |
|||
|
|||
"tailwindCSS.experimental.classRegex": [ |
|||
["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"] |
|||
], |
|||
|
|||
"github.copilot.enable": { |
|||
"*": true, |
|||
"markdown": true, |
|||
"plaintext": false, |
|||
"yaml": false |
|||
}, |
|||
|
|||
"cssVariables.lookupFiles": ["packages/core/base/design/src/**/*.css"], |
|||
|
|||
"i18n-ally.localesPaths": [ |
|||
"packages/locales/src/langs", |
|||
"playground/src/locales/langs", |
|||
"apps/*/src/locales/langs" |
|||
], |
|||
"i18n-ally.pathMatcher": "{locale}/{namespace}.{ext}", |
|||
"i18n-ally.enabledParsers": ["json"], |
|||
"i18n-ally.sourceLanguage": "en", |
|||
"i18n-ally.displayLanguage": "zh-CN", |
|||
"i18n-ally.enabledFrameworks": ["vue", "react"], |
|||
"i18n-ally.keystyle": "nested", |
|||
"i18n-ally.sortKeys": true, |
|||
"i18n-ally.namespace": true, |
|||
|
|||
// 控制相关文件嵌套展示 |
|||
"explorer.fileNesting.enabled": true, |
|||
"explorer.fileNesting.expand": false, |
|||
"explorer.fileNesting.patterns": { |
|||
"*.ts": "$(capture).test.ts, $(capture).test.tsx, $(capture).spec.ts, $(capture).spec.tsx, $(capture).d.ts", |
|||
"*.tsx": "$(capture).test.ts, $(capture).test.tsx, $(capture).spec.ts, $(capture).spec.tsx,$(capture).d.ts", |
|||
"*.env": "$(capture).env.*", |
|||
"README.md": "README*,CHANGELOG*,LICENSE,CNAME", |
|||
"package.json": "pnpm-lock.yaml,pnpm-workspace.yaml,.gitattributes,.gitignore,.gitpod.yml,.npmrc,.browserslistrc,.node-version,.git*,.tazerc.json", |
|||
"eslint.config.mjs": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.*,.prettierrc.*,stylelint.config.*,.lintstagedrc.mjs,cspell.json,lefthook.yml", |
|||
"tailwind.config.mjs": "postcss.*" |
|||
}, |
|||
"commentTranslate.hover.enabled": false, |
|||
"commentTranslate.multiLineMerge": true, |
|||
"vue.server.hybridMode": true, |
|||
"typescript.tsdk": "node_modules/typescript/lib", |
|||
"oxc.enable": false |
|||
} |
|||
@ -0,0 +1,153 @@ |
|||
import { execSync } from 'node:child_process'; |
|||
|
|||
import { getPackagesSync } from '@vben/node-utils'; |
|||
|
|||
const { packages } = getPackagesSync(); |
|||
|
|||
const allowedScopes = [ |
|||
...packages.map((pkg) => pkg.packageJson.name), |
|||
'project', |
|||
'style', |
|||
'lint', |
|||
'ci', |
|||
'dev', |
|||
'deploy', |
|||
'other', |
|||
]; |
|||
|
|||
// precomputed scope
|
|||
const scopeComplete = execSync('git status --porcelain || true') |
|||
.toString() |
|||
.trim() |
|||
.split('\n') |
|||
.find((r) => ~r.indexOf('M src')) |
|||
?.replaceAll(/(\/)/g, '%%') |
|||
?.match(/src%%((\w|-)*)/)?.[1] |
|||
?.replace(/s$/, ''); |
|||
|
|||
/** |
|||
* @type {import('cz-git').UserConfig} |
|||
*/ |
|||
const userConfig = { |
|||
extends: ['@commitlint/config-conventional'], |
|||
plugins: ['commitlint-plugin-function-rules'], |
|||
prompt: { |
|||
/** @use `pnpm commit :f` */ |
|||
alias: { |
|||
b: 'build: bump dependencies', |
|||
c: 'chore: update config', |
|||
f: 'docs: fix typos', |
|||
r: 'docs: update README', |
|||
s: 'style: update code format', |
|||
}, |
|||
allowCustomIssuePrefixs: false, |
|||
// scopes: [...scopes, 'mock'],
|
|||
allowEmptyIssuePrefixs: false, |
|||
customScopesAlign: scopeComplete ? 'bottom' : 'top', |
|||
defaultScope: scopeComplete, |
|||
// English
|
|||
typesAppend: [ |
|||
{ name: 'workflow: workflow improvements', value: 'workflow' }, |
|||
{ name: 'types: type definition file changes', value: 'types' }, |
|||
], |
|||
|
|||
// 中英文对照版
|
|||
// messages: {
|
|||
// type: '选择你要提交的类型 :',
|
|||
// scope: '选择一个提交范围 (可选):',
|
|||
// customScope: '请输入自定义的提交范围 :',
|
|||
// subject: '填写简短精炼的变更描述 :\n',
|
|||
// body: '填写更加详细的变更描述 (可选)。使用 "|" 换行 :\n',
|
|||
// breaking: '列举非兼容性重大的变更 (可选)。使用 "|" 换行 :\n',
|
|||
// footerPrefixsSelect: '选择关联issue前缀 (可选):',
|
|||
// customFooterPrefixs: '输入自定义issue前缀 :',
|
|||
// footer: '列举关联issue (可选) 例如: #31, #I3244 :\n',
|
|||
// confirmCommit: '是否提交或修改commit ?',
|
|||
// },
|
|||
// types: [
|
|||
// { value: 'feat', name: 'feat: 新增功能' },
|
|||
// { value: 'fix', name: 'fix: 修复缺陷' },
|
|||
// { value: 'docs', name: 'docs: 文档变更' },
|
|||
// { value: 'style', name: 'style: 代码格式' },
|
|||
// { value: 'refactor', name: 'refactor: 代码重构' },
|
|||
// { value: 'perf', name: 'perf: 性能优化' },
|
|||
// { value: 'test', name: 'test: 添加疏漏测试或已有测试改动' },
|
|||
// { value: 'build', name: 'build: 构建流程、外部依赖变更 (如升级 npm 包、修改打包配置等)' },
|
|||
// { value: 'ci', name: 'ci: 修改 CI 配置、脚本' },
|
|||
// { value: 'revert', name: 'revert: 回滚 commit' },
|
|||
// { value: 'chore', name: 'chore: 对构建过程或辅助工具和库的更改 (不影响源文件、测试用例)' },
|
|||
// { value: 'wip', name: 'wip: 正在开发中' },
|
|||
// { value: 'workflow', name: 'workflow: 工作流程改进' },
|
|||
// { value: 'types', name: 'types: 类型定义文件修改' },
|
|||
// ],
|
|||
// emptyScopesAlias: 'empty: 不填写',
|
|||
// customScopesAlias: 'custom: 自定义',
|
|||
}, |
|||
rules: { |
|||
/** |
|||
* type[scope]: [function] description |
|||
* |
|||
* ^^^^^^^^^^^^^^ empty line. |
|||
* - Something here |
|||
*/ |
|||
'body-leading-blank': [2, 'always'], |
|||
/** |
|||
* type[scope]: [function] description |
|||
* |
|||
* - something here |
|||
* |
|||
* ^^^^^^^^^^^^^^ |
|||
*/ |
|||
'footer-leading-blank': [1, 'always'], |
|||
/** |
|||
* type[scope]: [function] description |
|||
* ^^^^^ |
|||
*/ |
|||
'function-rules/scope-enum': [ |
|||
2, // level: error
|
|||
'always', |
|||
(parsed) => { |
|||
if (!parsed.scope || allowedScopes.includes(parsed.scope)) { |
|||
return [true]; |
|||
} |
|||
|
|||
return [false, `scope must be one of ${allowedScopes.join(', ')}`]; |
|||
}, |
|||
], |
|||
/** |
|||
* type[scope]: [function] description [No more than 108 characters] |
|||
* ^^^^^ |
|||
*/ |
|||
'header-max-length': [2, 'always', 108], |
|||
|
|||
'scope-enum': [0], |
|||
'subject-case': [0], |
|||
'subject-empty': [2, 'never'], |
|||
'type-empty': [2, 'never'], |
|||
/** |
|||
* type[scope]: [function] description |
|||
* ^^^^ |
|||
*/ |
|||
'type-enum': [ |
|||
2, |
|||
'always', |
|||
[ |
|||
'feat', |
|||
'fix', |
|||
'perf', |
|||
'style', |
|||
'docs', |
|||
'test', |
|||
'refactor', |
|||
'build', |
|||
'ci', |
|||
'chore', |
|||
'revert', |
|||
'types', |
|||
'release', |
|||
], |
|||
], |
|||
}, |
|||
}; |
|||
|
|||
export default userConfig; |
|||
@ -0,0 +1,33 @@ |
|||
{ |
|||
"name": "@vben/commitlint-config", |
|||
"version": "5.6.0", |
|||
"private": true, |
|||
"homepage": "https://github.com/vbenjs/vue-vben-admin", |
|||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git+https://github.com/vbenjs/vue-vben-admin.git", |
|||
"directory": "internal/lint-configs/commitlint-config" |
|||
}, |
|||
"license": "MIT", |
|||
"type": "module", |
|||
"files": [ |
|||
"dist" |
|||
], |
|||
"main": "./index.mjs", |
|||
"module": "./index.mjs", |
|||
"exports": { |
|||
".": { |
|||
"import": "./index.mjs", |
|||
"default": "./index.mjs" |
|||
} |
|||
}, |
|||
"dependencies": { |
|||
"@commitlint/cli": "catalog:", |
|||
"@commitlint/config-conventional": "catalog:", |
|||
"@vben/node-utils": "workspace:*", |
|||
"commitlint-plugin-function-rules": "catalog:", |
|||
"cz-git": "catalog:", |
|||
"czg": "catalog:" |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
import { defineBuildConfig } from 'unbuild'; |
|||
|
|||
export default defineBuildConfig({ |
|||
clean: true, |
|||
declaration: true, |
|||
entries: ['src/index'], |
|||
}); |
|||
@ -0,0 +1,59 @@ |
|||
{ |
|||
"name": "@vben/eslint-config", |
|||
"version": "5.6.0", |
|||
"private": true, |
|||
"homepage": "https://github.com/vbenjs/vue-vben-admin", |
|||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git+https://github.com/vbenjs/vue-vben-admin.git", |
|||
"directory": "internal/lint-configs/eslint-config" |
|||
}, |
|||
"license": "MIT", |
|||
"type": "module", |
|||
"scripts": { |
|||
"stub": "pnpm unbuild --stub" |
|||
}, |
|||
"files": [ |
|||
"dist" |
|||
], |
|||
"main": "./dist/index.mjs", |
|||
"module": "./dist/index.mjs", |
|||
"types": "./dist/index.d.ts", |
|||
"exports": { |
|||
".": { |
|||
"types": "./dist/index.d.ts", |
|||
"import": "./dist/index.mjs" |
|||
} |
|||
}, |
|||
"dependencies": { |
|||
"eslint-config-turbo": "catalog:", |
|||
"eslint-plugin-command": "catalog:", |
|||
"eslint-plugin-import-x": "catalog:" |
|||
}, |
|||
"devDependencies": { |
|||
"@eslint/js": "catalog:", |
|||
"@types/eslint": "catalog:", |
|||
"@typescript-eslint/eslint-plugin": "catalog:", |
|||
"@typescript-eslint/parser": "catalog:", |
|||
"eslint": "catalog:", |
|||
"eslint-plugin-eslint-comments": "catalog:", |
|||
"eslint-plugin-jsdoc": "catalog:", |
|||
"eslint-plugin-jsonc": "catalog:", |
|||
"eslint-plugin-n": "catalog:", |
|||
"eslint-plugin-no-only-tests": "catalog:", |
|||
"eslint-plugin-perfectionist": "catalog:", |
|||
"eslint-plugin-pnpm": "catalog:", |
|||
"eslint-plugin-prettier": "catalog:", |
|||
"eslint-plugin-regexp": "catalog:", |
|||
"eslint-plugin-unicorn": "catalog:", |
|||
"eslint-plugin-unused-imports": "catalog:", |
|||
"eslint-plugin-vitest": "catalog:", |
|||
"eslint-plugin-vue": "catalog:", |
|||
"eslint-plugin-yml": "catalog:", |
|||
"globals": "catalog:", |
|||
"jsonc-eslint-parser": "catalog:", |
|||
"vue-eslint-parser": "catalog:", |
|||
"yaml-eslint-parser": "catalog:" |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
import createCommand from 'eslint-plugin-command/config'; |
|||
|
|||
export async function command() { |
|||
return [ |
|||
{ |
|||
...createCommand(), |
|||
}, |
|||
]; |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
import type { Linter } from 'eslint'; |
|||
|
|||
import { interopDefault } from '../util'; |
|||
|
|||
export async function comments(): Promise<Linter.Config[]> { |
|||
const [pluginComments] = await Promise.all([ |
|||
// @ts-expect-error - no types
|
|||
interopDefault(import('eslint-plugin-eslint-comments')), |
|||
] as const); |
|||
|
|||
return [ |
|||
{ |
|||
plugins: { |
|||
'eslint-comments': pluginComments, |
|||
}, |
|||
rules: { |
|||
'eslint-comments/no-aggregating-enable': 'error', |
|||
'eslint-comments/no-duplicate-disable': 'error', |
|||
'eslint-comments/no-unlimited-disable': 'error', |
|||
'eslint-comments/no-unused-enable': 'error', |
|||
}, |
|||
}, |
|||
]; |
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
import type { Linter } from 'eslint'; |
|||
|
|||
export async function disableds(): Promise<Linter.Config[]> { |
|||
return [ |
|||
{ |
|||
files: ['**/__tests__/**/*.?([cm])[jt]s?(x)'], |
|||
name: 'disables/test', |
|||
rules: { |
|||
'@typescript-eslint/ban-ts-comment': 'off', |
|||
'no-console': 'off', |
|||
}, |
|||
}, |
|||
{ |
|||
files: ['**/*.d.ts'], |
|||
name: 'disables/dts', |
|||
rules: { |
|||
'@typescript-eslint/triple-slash-reference': 'off', |
|||
}, |
|||
}, |
|||
{ |
|||
files: ['**/*.js', '**/*.mjs', '**/*.cjs'], |
|||
name: 'disables/js', |
|||
rules: { |
|||
'@typescript-eslint/explicit-module-boundary-types': 'off', |
|||
}, |
|||
}, |
|||
]; |
|||
} |
|||
@ -0,0 +1,54 @@ |
|||
import type { Linter } from 'eslint'; |
|||
|
|||
export async function ignores(): Promise<Linter.Config[]> { |
|||
return [ |
|||
{ |
|||
ignores: [ |
|||
'**/node_modules', |
|||
'**/dist', |
|||
'**/dist-*', |
|||
'**/*-dist', |
|||
'**/.husky', |
|||
'**/.nitro', |
|||
'**/.output', |
|||
'**/Dockerfile', |
|||
'**/package-lock.json', |
|||
'**/yarn.lock', |
|||
'**/pnpm-lock.yaml', |
|||
'**/bun.lockb', |
|||
'**/output', |
|||
'**/coverage', |
|||
'**/temp', |
|||
'**/.temp', |
|||
'**/tmp', |
|||
'**/.tmp', |
|||
'**/.history', |
|||
'**/.turbo', |
|||
'**/.nuxt', |
|||
'**/.next', |
|||
'**/.vercel', |
|||
'**/.changeset', |
|||
'**/.idea', |
|||
'**/.cache', |
|||
'**/.output', |
|||
'**/.vite-inspect', |
|||
|
|||
'**/CHANGELOG*.md', |
|||
'**/*.min.*', |
|||
'**/LICENSE*', |
|||
'**/__snapshots__', |
|||
'**/*.snap', |
|||
'**/fixtures/**', |
|||
'**/.vitepress/cache/**', |
|||
'**/auto-import?(s).d.ts', |
|||
'**/components.d.ts', |
|||
'**/vite.config.mts.*', |
|||
'**/*.sh', |
|||
'**/*.ttf', |
|||
'**/*.woff', |
|||
'**/.github', |
|||
'**/lefthook.yml', |
|||
], |
|||
}, |
|||
]; |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
import type { Linter } from 'eslint'; |
|||
|
|||
import * as pluginImport from 'eslint-plugin-import-x'; |
|||
|
|||
export async function importPluginConfig(): Promise<Linter.Config[]> { |
|||
return [ |
|||
{ |
|||
plugins: { |
|||
// @ts-expect-error - This is a dynamic import
|
|||
import: pluginImport, |
|||
}, |
|||
rules: { |
|||
'import/consistent-type-specifier-style': ['error', 'prefer-top-level'], |
|||
'import/first': 'error', |
|||
'import/newline-after-import': 'error', |
|||
'import/no-duplicates': 'error', |
|||
'import/no-mutable-exports': 'error', |
|||
'import/no-named-default': 'error', |
|||
'import/no-self-import': 'error', |
|||
'import/no-unresolved': 'off', |
|||
'import/no-webpack-loader-syntax': 'error', |
|||
}, |
|||
}, |
|||
]; |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
export * from './command'; |
|||
export * from './comments'; |
|||
export * from './disableds'; |
|||
export * from './ignores'; |
|||
export * from './import'; |
|||
export * from './javascript'; |
|||
export * from './jsdoc'; |
|||
export * from './jsonc'; |
|||
export * from './node'; |
|||
export * from './perfectionist'; |
|||
export * from './pnpm'; |
|||
export * from './prettier'; |
|||
export * from './regexp'; |
|||
export * from './test'; |
|||
export * from './turbo'; |
|||
export * from './typescript'; |
|||
export * from './unicorn'; |
|||
export * from './vue'; |
|||
export * from './yaml'; |
|||
@ -0,0 +1,241 @@ |
|||
import type { Linter } from 'eslint'; |
|||
|
|||
import js from '@eslint/js'; |
|||
import pluginUnusedImports from 'eslint-plugin-unused-imports'; |
|||
import globals from 'globals'; |
|||
|
|||
export async function javascript(): Promise<Linter.Config[]> { |
|||
return [ |
|||
{ |
|||
languageOptions: { |
|||
ecmaVersion: 'latest', |
|||
globals: { |
|||
...globals.browser, |
|||
...globals.es2021, |
|||
...globals.node, |
|||
document: 'readonly', |
|||
navigator: 'readonly', |
|||
window: 'readonly', |
|||
}, |
|||
parserOptions: { |
|||
ecmaFeatures: { |
|||
jsx: true, |
|||
}, |
|||
ecmaVersion: 'latest', |
|||
sourceType: 'module', |
|||
}, |
|||
sourceType: 'module', |
|||
}, |
|||
linterOptions: { |
|||
reportUnusedDisableDirectives: true, |
|||
}, |
|||
plugins: { |
|||
'unused-imports': pluginUnusedImports, |
|||
}, |
|||
rules: { |
|||
...js.configs.recommended.rules, |
|||
'accessor-pairs': [ |
|||
'error', |
|||
{ enforceForClassMembers: true, setWithoutGet: true }, |
|||
], |
|||
'array-callback-return': 'error', |
|||
'block-scoped-var': 'error', |
|||
'constructor-super': 'error', |
|||
'default-case-last': 'error', |
|||
'dot-notation': ['error', { allowKeywords: true }], |
|||
eqeqeq: ['error', 'always'], |
|||
'keyword-spacing': 'off', |
|||
|
|||
'new-cap': [ |
|||
'error', |
|||
{ capIsNew: false, newIsCap: true, properties: true }, |
|||
], |
|||
'no-alert': 'error', |
|||
'no-array-constructor': 'error', |
|||
'no-async-promise-executor': 'error', |
|||
'no-caller': 'error', |
|||
'no-case-declarations': 'error', |
|||
'no-class-assign': 'error', |
|||
'no-compare-neg-zero': 'error', |
|||
'no-cond-assign': ['error', 'always'], |
|||
'no-console': ['error', { allow: ['warn', 'error'] }], |
|||
'no-const-assign': 'error', |
|||
'no-control-regex': 'error', |
|||
'no-debugger': 'error', |
|||
'no-delete-var': 'error', |
|||
'no-dupe-args': 'error', |
|||
'no-dupe-class-members': 'error', |
|||
'no-dupe-keys': 'error', |
|||
'no-duplicate-case': 'error', |
|||
'no-empty': ['error', { allowEmptyCatch: true }], |
|||
'no-empty-character-class': 'error', |
|||
'no-empty-function': 'off', |
|||
'no-empty-pattern': 'error', |
|||
'no-eval': 'error', |
|||
'no-ex-assign': 'error', |
|||
'no-extend-native': 'error', |
|||
'no-extra-bind': 'error', |
|||
'no-extra-boolean-cast': 'error', |
|||
'no-fallthrough': 'error', |
|||
'no-func-assign': 'error', |
|||
'no-global-assign': 'error', |
|||
'no-implied-eval': 'error', |
|||
'no-import-assign': 'error', |
|||
'no-invalid-regexp': 'error', |
|||
'no-irregular-whitespace': 'error', |
|||
'no-iterator': 'error', |
|||
'no-labels': ['error', { allowLoop: false, allowSwitch: false }], |
|||
'no-lone-blocks': 'error', |
|||
'no-loss-of-precision': 'error', |
|||
'no-misleading-character-class': 'error', |
|||
'no-multi-str': 'error', |
|||
'no-new': 'error', |
|||
'no-new-func': 'error', |
|||
'no-new-object': 'error', |
|||
'no-new-symbol': 'error', |
|||
'no-new-wrappers': 'error', |
|||
'no-obj-calls': 'error', |
|||
'no-octal': 'error', |
|||
'no-octal-escape': 'error', |
|||
'no-proto': 'error', |
|||
'no-prototype-builtins': 'error', |
|||
'no-redeclare': ['error', { builtinGlobals: false }], |
|||
'no-regex-spaces': 'error', |
|||
'no-restricted-globals': [ |
|||
'error', |
|||
{ message: 'Use `globalThis` instead.', name: 'global' }, |
|||
{ message: 'Use `globalThis` instead.', name: 'self' }, |
|||
], |
|||
'no-restricted-properties': [ |
|||
'error', |
|||
{ |
|||
message: |
|||
'Use `Object.getPrototypeOf` or `Object.setPrototypeOf` instead.', |
|||
property: '__proto__', |
|||
}, |
|||
{ |
|||
message: 'Use `Object.defineProperty` instead.', |
|||
property: '__defineGetter__', |
|||
}, |
|||
{ |
|||
message: 'Use `Object.defineProperty` instead.', |
|||
property: '__defineSetter__', |
|||
}, |
|||
{ |
|||
message: 'Use `Object.getOwnPropertyDescriptor` instead.', |
|||
property: '__lookupGetter__', |
|||
}, |
|||
{ |
|||
message: 'Use `Object.getOwnPropertyDescriptor` instead.', |
|||
property: '__lookupSetter__', |
|||
}, |
|||
], |
|||
'no-restricted-syntax': [ |
|||
'error', |
|||
'DebuggerStatement', |
|||
'LabeledStatement', |
|||
'WithStatement', |
|||
'TSEnumDeclaration[const=true]', |
|||
'TSExportAssignment', |
|||
], |
|||
'no-self-assign': ['error', { props: true }], |
|||
'no-self-compare': 'error', |
|||
'no-sequences': 'error', |
|||
'no-shadow-restricted-names': 'error', |
|||
'no-sparse-arrays': 'error', |
|||
'no-template-curly-in-string': 'error', |
|||
'no-this-before-super': 'error', |
|||
'no-throw-literal': 'error', |
|||
'no-undef': 'off', |
|||
'no-undef-init': 'error', |
|||
'no-unexpected-multiline': 'error', |
|||
'no-unmodified-loop-condition': 'error', |
|||
'no-unneeded-ternary': ['error', { defaultAssignment: false }], |
|||
'no-unreachable': 'error', |
|||
'no-unreachable-loop': 'error', |
|||
'no-unsafe-finally': 'error', |
|||
'no-unsafe-negation': 'error', |
|||
'no-unused-expressions': [ |
|||
'error', |
|||
{ |
|||
allowShortCircuit: true, |
|||
allowTaggedTemplates: true, |
|||
allowTernary: true, |
|||
}, |
|||
], |
|||
'no-unused-vars': [ |
|||
'error', |
|||
{ |
|||
args: 'none', |
|||
caughtErrors: 'none', |
|||
ignoreRestSiblings: true, |
|||
vars: 'all', |
|||
}, |
|||
], |
|||
'no-use-before-define': [ |
|||
'error', |
|||
{ classes: false, functions: false, variables: false }, |
|||
], |
|||
'no-useless-backreference': 'error', |
|||
'no-useless-call': 'error', |
|||
'no-useless-catch': 'error', |
|||
'no-useless-computed-key': 'error', |
|||
'no-useless-constructor': 'error', |
|||
'no-useless-rename': 'error', |
|||
'no-useless-return': 'error', |
|||
'no-var': 'error', |
|||
'no-with': 'error', |
|||
'object-shorthand': [ |
|||
'error', |
|||
'always', |
|||
{ avoidQuotes: true, ignoreConstructors: false }, |
|||
], |
|||
'one-var': ['error', { initialized: 'never' }], |
|||
'prefer-arrow-callback': [ |
|||
'error', |
|||
{ |
|||
allowNamedFunctions: false, |
|||
allowUnboundThis: true, |
|||
}, |
|||
], |
|||
'prefer-const': [ |
|||
'error', |
|||
{ |
|||
destructuring: 'all', |
|||
ignoreReadBeforeAssign: true, |
|||
}, |
|||
], |
|||
'prefer-exponentiation-operator': 'error', |
|||
|
|||
'prefer-promise-reject-errors': 'error', |
|||
'prefer-regex-literals': ['error', { disallowRedundantWrapping: true }], |
|||
'prefer-rest-params': 'error', |
|||
'prefer-spread': 'error', |
|||
'prefer-template': 'error', |
|||
'space-before-function-paren': 'off', |
|||
'spaced-comment': 'error', |
|||
'symbol-description': 'error', |
|||
'unicode-bom': ['error', 'never'], |
|||
|
|||
'unused-imports/no-unused-imports': 'error', |
|||
'unused-imports/no-unused-vars': [ |
|||
'error', |
|||
{ |
|||
args: 'after-used', |
|||
argsIgnorePattern: '^_', |
|||
vars: 'all', |
|||
varsIgnorePattern: '^_', |
|||
}, |
|||
], |
|||
'use-isnan': [ |
|||
'error', |
|||
{ enforceForIndexOf: true, enforceForSwitchCase: true }, |
|||
], |
|||
'valid-typeof': ['error', { requireStringLiterals: true }], |
|||
|
|||
'vars-on-top': 'error', |
|||
yoda: ['error', 'never'], |
|||
}, |
|||
}, |
|||
]; |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
import type { Linter } from 'eslint'; |
|||
|
|||
import { interopDefault } from '../util'; |
|||
|
|||
export async function jsdoc(): Promise<Linter.Config[]> { |
|||
const [pluginJsdoc] = await Promise.all([ |
|||
interopDefault(import('eslint-plugin-jsdoc')), |
|||
] as const); |
|||
|
|||
return [ |
|||
{ |
|||
plugins: { |
|||
jsdoc: pluginJsdoc, |
|||
}, |
|||
rules: { |
|||
'jsdoc/check-access': 'warn', |
|||
'jsdoc/check-param-names': 'warn', |
|||
'jsdoc/check-property-names': 'warn', |
|||
'jsdoc/check-types': 'warn', |
|||
'jsdoc/empty-tags': 'warn', |
|||
'jsdoc/implements-on-classes': 'warn', |
|||
'jsdoc/no-defaults': 'warn', |
|||
'jsdoc/no-multi-asterisks': 'warn', |
|||
'jsdoc/require-param-name': 'warn', |
|||
'jsdoc/require-property': 'warn', |
|||
'jsdoc/require-property-description': 'warn', |
|||
'jsdoc/require-property-name': 'warn', |
|||
'jsdoc/require-returns-check': 'warn', |
|||
'jsdoc/require-returns-description': 'warn', |
|||
'jsdoc/require-yields-check': 'warn', |
|||
}, |
|||
}, |
|||
]; |
|||
} |
|||
@ -0,0 +1,274 @@ |
|||
import type { Linter } from 'eslint'; |
|||
|
|||
import { interopDefault } from '../util'; |
|||
|
|||
export async function jsonc(): Promise<Linter.Config[]> { |
|||
const [pluginJsonc, parserJsonc] = await Promise.all([ |
|||
interopDefault(import('eslint-plugin-jsonc')), |
|||
interopDefault(import('jsonc-eslint-parser')), |
|||
] as const); |
|||
|
|||
return [ |
|||
{ |
|||
files: ['**/*.json', '**/*.json5', '**/*.jsonc', '*.code-workspace'], |
|||
languageOptions: { |
|||
parser: parserJsonc as any, |
|||
}, |
|||
plugins: { |
|||
jsonc: pluginJsonc as any, |
|||
}, |
|||
rules: { |
|||
'jsonc/no-bigint-literals': 'error', |
|||
'jsonc/no-binary-expression': 'error', |
|||
'jsonc/no-binary-numeric-literals': 'error', |
|||
'jsonc/no-dupe-keys': 'error', |
|||
'jsonc/no-escape-sequence-in-identifier': 'error', |
|||
'jsonc/no-floating-decimal': 'error', |
|||
'jsonc/no-hexadecimal-numeric-literals': 'error', |
|||
'jsonc/no-infinity': 'error', |
|||
'jsonc/no-multi-str': 'error', |
|||
'jsonc/no-nan': 'error', |
|||
'jsonc/no-number-props': 'error', |
|||
'jsonc/no-numeric-separators': 'error', |
|||
'jsonc/no-octal': 'error', |
|||
'jsonc/no-octal-escape': 'error', |
|||
'jsonc/no-octal-numeric-literals': 'error', |
|||
'jsonc/no-parenthesized': 'error', |
|||
'jsonc/no-plus-sign': 'error', |
|||
'jsonc/no-regexp-literals': 'error', |
|||
'jsonc/no-sparse-arrays': 'error', |
|||
'jsonc/no-template-literals': 'error', |
|||
'jsonc/no-undefined-value': 'error', |
|||
'jsonc/no-unicode-codepoint-escapes': 'error', |
|||
'jsonc/no-useless-escape': 'error', |
|||
'jsonc/space-unary-ops': 'error', |
|||
'jsonc/valid-json-number': 'error', |
|||
'jsonc/vue-custom-block/no-parsing-error': 'error', |
|||
}, |
|||
}, |
|||
sortTsconfig(), |
|||
sortPackageJson(), |
|||
sortCspellJson(), |
|||
]; |
|||
} |
|||
|
|||
function sortPackageJson(): Linter.Config { |
|||
return { |
|||
files: ['**/package.json'], |
|||
rules: { |
|||
'jsonc/sort-array-values': [ |
|||
'error', |
|||
{ |
|||
order: { type: 'asc' }, |
|||
pathPattern: '^files$|^pnpm.neverBuiltDependencies$', |
|||
}, |
|||
], |
|||
'jsonc/sort-keys': [ |
|||
'error', |
|||
{ |
|||
order: [ |
|||
'name', |
|||
'version', |
|||
'description', |
|||
'private', |
|||
'keywords', |
|||
'homepage', |
|||
'bugs', |
|||
'repository', |
|||
'license', |
|||
'author', |
|||
'contributors', |
|||
'categories', |
|||
'funding', |
|||
'type', |
|||
'scripts', |
|||
'files', |
|||
'sideEffects', |
|||
'bin', |
|||
'main', |
|||
'module', |
|||
'unpkg', |
|||
'jsdelivr', |
|||
'types', |
|||
'typesVersions', |
|||
'imports', |
|||
'exports', |
|||
'publishConfig', |
|||
'icon', |
|||
'activationEvents', |
|||
'contributes', |
|||
'peerDependencies', |
|||
'peerDependenciesMeta', |
|||
'dependencies', |
|||
'optionalDependencies', |
|||
'devDependencies', |
|||
'engines', |
|||
'packageManager', |
|||
'pnpm', |
|||
'overrides', |
|||
'resolutions', |
|||
'husky', |
|||
'simple-git-hooks', |
|||
'lint-staged', |
|||
'eslintConfig', |
|||
], |
|||
pathPattern: '^$', |
|||
}, |
|||
{ |
|||
order: { type: 'asc' }, |
|||
pathPattern: '^(?:dev|peer|optional|bundled)?[Dd]ependencies(Meta)?$', |
|||
}, |
|||
{ |
|||
order: { type: 'asc' }, |
|||
pathPattern: '^(?:resolutions|overrides|pnpm.overrides)$', |
|||
}, |
|||
{ |
|||
order: ['types', 'import', 'require', 'default'], |
|||
pathPattern: '^exports.*$', |
|||
}, |
|||
], |
|||
}, |
|||
}; |
|||
} |
|||
|
|||
function sortCspellJson(): Linter.Config { |
|||
return { |
|||
files: ['**/cspell.json', '**/.cspell.json'], |
|||
rules: { |
|||
'jsonc/sort-array-values': [ |
|||
'error', |
|||
{ |
|||
order: { type: 'asc' }, |
|||
pathPattern: '^words$|^ignorePaths$', |
|||
}, |
|||
], |
|||
}, |
|||
}; |
|||
} |
|||
|
|||
function sortTsconfig(): Linter.Config { |
|||
return { |
|||
files: [ |
|||
'**/tsconfig.json', |
|||
'**/tsconfig.*.json', |
|||
'internal/tsconfig/*.json', |
|||
], |
|||
rules: { |
|||
'jsonc/sort-keys': [ |
|||
'error', |
|||
{ |
|||
order: [ |
|||
'extends', |
|||
'compilerOptions', |
|||
'references', |
|||
'files', |
|||
'include', |
|||
'exclude', |
|||
], |
|||
pathPattern: '^$', |
|||
}, |
|||
{ |
|||
order: [ |
|||
/* Projects */ |
|||
'incremental', |
|||
'composite', |
|||
'tsBuildInfoFile', |
|||
'disableSourceOfProjectReferenceRedirect', |
|||
'disableSolutionSearching', |
|||
'disableReferencedProjectLoad', |
|||
/* Language and Environment */ |
|||
'target', |
|||
'jsx', |
|||
'jsxFactory', |
|||
'jsxFragmentFactory', |
|||
'jsxImportSource', |
|||
'lib', |
|||
'moduleDetection', |
|||
'noLib', |
|||
'reactNamespace', |
|||
'useDefineForClassFields', |
|||
'emitDecoratorMetadata', |
|||
'experimentalDecorators', |
|||
/* Modules */ |
|||
'baseUrl', |
|||
'rootDir', |
|||
'rootDirs', |
|||
'customConditions', |
|||
'module', |
|||
'moduleResolution', |
|||
'moduleSuffixes', |
|||
'noResolve', |
|||
'paths', |
|||
'resolveJsonModule', |
|||
'resolvePackageJsonExports', |
|||
'resolvePackageJsonImports', |
|||
'typeRoots', |
|||
'types', |
|||
'allowArbitraryExtensions', |
|||
'allowImportingTsExtensions', |
|||
'allowUmdGlobalAccess', |
|||
/* JavaScript Support */ |
|||
'allowJs', |
|||
'checkJs', |
|||
'maxNodeModuleJsDepth', |
|||
/* Type Checking */ |
|||
'strict', |
|||
'strictBindCallApply', |
|||
'strictFunctionTypes', |
|||
'strictNullChecks', |
|||
'strictPropertyInitialization', |
|||
'allowUnreachableCode', |
|||
'allowUnusedLabels', |
|||
'alwaysStrict', |
|||
'exactOptionalPropertyTypes', |
|||
'noFallthroughCasesInSwitch', |
|||
'noImplicitAny', |
|||
'noImplicitOverride', |
|||
'noImplicitReturns', |
|||
'noImplicitThis', |
|||
'noPropertyAccessFromIndexSignature', |
|||
'noUncheckedIndexedAccess', |
|||
'noUnusedLocals', |
|||
'noUnusedParameters', |
|||
'useUnknownInCatchVariables', |
|||
/* Emit */ |
|||
'declaration', |
|||
'declarationDir', |
|||
'declarationMap', |
|||
'downlevelIteration', |
|||
'emitBOM', |
|||
'emitDeclarationOnly', |
|||
'importHelpers', |
|||
'importsNotUsedAsValues', |
|||
'inlineSourceMap', |
|||
'inlineSources', |
|||
'mapRoot', |
|||
'newLine', |
|||
'noEmit', |
|||
'noEmitHelpers', |
|||
'noEmitOnError', |
|||
'outDir', |
|||
'outFile', |
|||
'preserveConstEnums', |
|||
'preserveValueImports', |
|||
'removeComments', |
|||
'sourceMap', |
|||
'sourceRoot', |
|||
'stripInternal', |
|||
/* Interop Constraints */ |
|||
'allowSyntheticDefaultImports', |
|||
'esModuleInterop', |
|||
'forceConsistentCasingInFileNames', |
|||
'isolatedModules', |
|||
'preserveSymlinks', |
|||
'verbatimModuleSyntax', |
|||
/* Completeness */ |
|||
'skipDefaultLibCheck', |
|||
'skipLibCheck', |
|||
], |
|||
pathPattern: '^compilerOptions$', |
|||
}, |
|||
], |
|||
}, |
|||
}; |
|||
} |
|||
@ -0,0 +1,57 @@ |
|||
import type { Linter } from 'eslint'; |
|||
|
|||
import { interopDefault } from '../util'; |
|||
|
|||
export async function node(): Promise<Linter.Config[]> { |
|||
const pluginNode = await interopDefault(import('eslint-plugin-n')); |
|||
|
|||
return [ |
|||
{ |
|||
plugins: { |
|||
n: pluginNode, |
|||
}, |
|||
rules: { |
|||
'n/handle-callback-err': ['error', '^(err|error)$'], |
|||
'n/no-deprecated-api': 'error', |
|||
'n/no-exports-assign': 'error', |
|||
'n/no-extraneous-import': [ |
|||
'error', |
|||
{ |
|||
allowModules: [ |
|||
'unbuild', |
|||
'@vben/vite-config', |
|||
'vitest', |
|||
'vite', |
|||
'@vue/test-utils', |
|||
'@vben/tailwind-config', |
|||
'@playwright/test', |
|||
], |
|||
}, |
|||
], |
|||
'n/no-new-require': 'error', |
|||
'n/no-path-concat': 'error', |
|||
// 'n/no-unpublished-import': 'off',
|
|||
'n/no-unsupported-features/es-syntax': [ |
|||
'error', |
|||
{ |
|||
ignores: [], |
|||
version: '>=20.12.0', |
|||
}, |
|||
], |
|||
'n/prefer-global/buffer': ['error', 'never'], |
|||
// 'n/no-missing-import': 'off',
|
|||
'n/prefer-global/process': ['error', 'never'], |
|||
'n/process-exit-as-throw': 'error', |
|||
}, |
|||
}, |
|||
{ |
|||
files: [ |
|||
'scripts/**/*.?([cm])[jt]s?(x)', |
|||
'internal/**/*.?([cm])[jt]s?(x)', |
|||
], |
|||
rules: { |
|||
'n/prefer-global/process': 'off', |
|||
}, |
|||
}, |
|||
]; |
|||
} |
|||
@ -0,0 +1,88 @@ |
|||
import type { Linter } from 'eslint'; |
|||
|
|||
import { interopDefault } from '../util'; |
|||
|
|||
export async function perfectionist(): Promise<Linter.Config[]> { |
|||
const perfectionistPlugin = await interopDefault( |
|||
import('eslint-plugin-perfectionist'), |
|||
); |
|||
|
|||
return [ |
|||
perfectionistPlugin.configs['recommended-natural'], |
|||
{ |
|||
rules: { |
|||
'perfectionist/sort-exports': [ |
|||
'error', |
|||
{ |
|||
order: 'asc', |
|||
type: 'natural', |
|||
}, |
|||
], |
|||
'perfectionist/sort-imports': [ |
|||
'error', |
|||
{ |
|||
customGroups: { |
|||
type: { |
|||
'vben-core-type': ['^@vben-core/.+'], |
|||
'vben-type': ['^@vben/.+'], |
|||
'vue-type': ['^vue$', '^vue-.+', '^@vue/.+'], |
|||
}, |
|||
value: { |
|||
vben: ['^@vben/.+'], |
|||
'vben-core': ['^@vben-core/.+'], |
|||
vue: ['^vue$', '^vue-.+', '^@vue/.+'], |
|||
}, |
|||
}, |
|||
environment: 'node', |
|||
groups: [ |
|||
['external-type', 'builtin-type', 'type'], |
|||
'vue-type', |
|||
'vben-type', |
|||
'vben-core-type', |
|||
['parent-type', 'sibling-type', 'index-type'], |
|||
['internal-type'], |
|||
'builtin', |
|||
'vue', |
|||
'vben', |
|||
'vben-core', |
|||
'external', |
|||
'internal', |
|||
['parent', 'sibling', 'index'], |
|||
'side-effect', |
|||
'side-effect-style', |
|||
'style', |
|||
'object', |
|||
'unknown', |
|||
], |
|||
internalPattern: ['^#/.+'], |
|||
newlinesBetween: 'always', |
|||
order: 'asc', |
|||
type: 'natural', |
|||
}, |
|||
], |
|||
'perfectionist/sort-modules': 'off', |
|||
'perfectionist/sort-named-exports': [ |
|||
'error', |
|||
{ |
|||
order: 'asc', |
|||
type: 'natural', |
|||
}, |
|||
], |
|||
'perfectionist/sort-objects': [ |
|||
'off', |
|||
{ |
|||
customGroups: { |
|||
items: 'items', |
|||
list: 'list', |
|||
children: 'children', |
|||
}, |
|||
groups: ['unknown', 'items', 'list', 'children'], |
|||
ignorePattern: ['children'], |
|||
order: 'asc', |
|||
type: 'natural', |
|||
}, |
|||
], |
|||
}, |
|||
}, |
|||
]; |
|||
} |
|||
@ -0,0 +1,41 @@ |
|||
import type { Linter } from 'eslint'; |
|||
|
|||
import { interopDefault } from '../util'; |
|||
|
|||
export async function pnpm(): Promise<Linter.Config[]> { |
|||
const [pluginPnpm, parserPnpm, parserJsonc] = await Promise.all([ |
|||
interopDefault(import('eslint-plugin-pnpm')), |
|||
interopDefault(import('yaml-eslint-parser')), |
|||
interopDefault(import('jsonc-eslint-parser')), |
|||
] as const); |
|||
|
|||
return [ |
|||
{ |
|||
files: ['package.json', '**/package.json'], |
|||
languageOptions: { |
|||
parser: parserJsonc, |
|||
}, |
|||
plugins: { |
|||
pnpm: pluginPnpm, |
|||
}, |
|||
rules: { |
|||
'pnpm/json-enforce-catalog': 'error', |
|||
'pnpm/json-prefer-workspace-settings': 'error', |
|||
'pnpm/json-valid-catalog': 'error', |
|||
}, |
|||
}, |
|||
{ |
|||
files: ['pnpm-workspace.yaml'], |
|||
languageOptions: { |
|||
parser: parserPnpm, |
|||
}, |
|||
plugins: { |
|||
pnpm: pluginPnpm, |
|||
}, |
|||
rules: { |
|||
'pnpm/yaml-no-duplicate-catalog-item': 'error', |
|||
'pnpm/yaml-no-unused-catalog-item': 'error', |
|||
}, |
|||
}, |
|||
]; |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
import type { Linter } from 'eslint'; |
|||
|
|||
import { interopDefault } from '../util'; |
|||
|
|||
export async function prettier(): Promise<Linter.Config[]> { |
|||
const [pluginPrettier] = await Promise.all([ |
|||
interopDefault(import('eslint-plugin-prettier')), |
|||
] as const); |
|||
return [ |
|||
{ |
|||
plugins: { |
|||
prettier: pluginPrettier, |
|||
}, |
|||
rules: { |
|||
'prettier/prettier': 'error', |
|||
}, |
|||
}, |
|||
]; |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
import type { Linter } from 'eslint'; |
|||
|
|||
import { interopDefault } from '../util'; |
|||
|
|||
export async function regexp(): Promise<Linter.Config[]> { |
|||
const [pluginRegexp] = await Promise.all([ |
|||
interopDefault(import('eslint-plugin-regexp')), |
|||
] as const); |
|||
|
|||
return [ |
|||
{ |
|||
plugins: { |
|||
regexp: pluginRegexp, |
|||
}, |
|||
rules: { |
|||
...pluginRegexp.configs.recommended.rules, |
|||
}, |
|||
}, |
|||
]; |
|||
} |
|||
@ -0,0 +1,45 @@ |
|||
import type { Linter } from 'eslint'; |
|||
|
|||
import { interopDefault } from '../util'; |
|||
|
|||
export async function test(): Promise<Linter.Config[]> { |
|||
const [pluginTest, pluginNoOnlyTests] = await Promise.all([ |
|||
interopDefault(import('eslint-plugin-vitest')), |
|||
// @ts-expect-error - no types
|
|||
interopDefault(import('eslint-plugin-no-only-tests')), |
|||
] as const); |
|||
|
|||
return [ |
|||
{ |
|||
files: [ |
|||
`**/__tests__/**/*.?([cm])[jt]s?(x)`, |
|||
`**/*.spec.?([cm])[jt]s?(x)`, |
|||
`**/*.test.?([cm])[jt]s?(x)`, |
|||
`**/*.bench.?([cm])[jt]s?(x)`, |
|||
`**/*.benchmark.?([cm])[jt]s?(x)`, |
|||
], |
|||
plugins: { |
|||
test: { |
|||
...pluginTest, |
|||
rules: { |
|||
...pluginTest.rules, |
|||
...pluginNoOnlyTests.rules, |
|||
}, |
|||
}, |
|||
}, |
|||
rules: { |
|||
'no-console': 'off', |
|||
'node/prefer-global/process': 'off', |
|||
'test/consistent-test-it': [ |
|||
'error', |
|||
{ fn: 'it', withinDescribe: 'it' }, |
|||
], |
|||
'test/no-identical-title': 'error', |
|||
'test/no-import-node-test': 'error', |
|||
'test/no-only-tests': 'error', |
|||
'test/prefer-hooks-in-order': 'error', |
|||
'test/prefer-lowercase-title': 'error', |
|||
}, |
|||
}, |
|||
]; |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
import type { Linter } from 'eslint'; |
|||
|
|||
import { interopDefault } from '../util'; |
|||
|
|||
export async function turbo(): Promise<Linter.Config[]> { |
|||
const [pluginTurbo] = await Promise.all([ |
|||
interopDefault(import('eslint-config-turbo')), |
|||
] as const); |
|||
|
|||
return [ |
|||
{ |
|||
plugins: { |
|||
turbo: pluginTurbo, |
|||
}, |
|||
}, |
|||
]; |
|||
} |
|||
@ -0,0 +1,71 @@ |
|||
import type { Linter } from 'eslint'; |
|||
|
|||
import { interopDefault } from '../util'; |
|||
|
|||
export async function typescript(): Promise<Linter.Config[]> { |
|||
const [pluginTs, parserTs] = await Promise.all([ |
|||
interopDefault(import('@typescript-eslint/eslint-plugin')), |
|||
interopDefault(import('@typescript-eslint/parser')), |
|||
] as const); |
|||
|
|||
return [ |
|||
{ |
|||
files: ['**/*.?([cm])[jt]s?(x)'], |
|||
languageOptions: { |
|||
parser: parserTs, |
|||
parserOptions: { |
|||
createDefaultProgram: false, |
|||
ecmaFeatures: { |
|||
jsx: true, |
|||
}, |
|||
ecmaVersion: 'latest', |
|||
extraFileExtensions: ['.vue'], |
|||
jsxPragma: 'React', |
|||
project: './tsconfig.*.json', |
|||
sourceType: 'module', |
|||
}, |
|||
}, |
|||
plugins: { |
|||
'@typescript-eslint': pluginTs as any, |
|||
}, |
|||
rules: { |
|||
...pluginTs.configs['eslint-recommended']?.overrides?.[0]?.rules, |
|||
...pluginTs.configs.strict?.rules, |
|||
'@typescript-eslint/ban-ts-comment': [ |
|||
'error', |
|||
{ |
|||
'ts-check': false, |
|||
'ts-expect-error': 'allow-with-description', |
|||
'ts-ignore': 'allow-with-description', |
|||
'ts-nocheck': 'allow-with-description', |
|||
}, |
|||
], |
|||
|
|||
// '@typescript-eslint/consistent-type-definitions': ['warn', 'interface'],
|
|||
'@typescript-eslint/consistent-type-definitions': 'off', |
|||
'@typescript-eslint/explicit-function-return-type': 'off', |
|||
'@typescript-eslint/explicit-module-boundary-types': 'off', |
|||
'@typescript-eslint/no-empty-function': [ |
|||
'error', |
|||
{ |
|||
allow: ['arrowFunctions', 'functions', 'methods'], |
|||
}, |
|||
], |
|||
'@typescript-eslint/no-explicit-any': 'off', |
|||
'@typescript-eslint/no-namespace': 'off', |
|||
'@typescript-eslint/no-non-null-assertion': 'error', |
|||
'@typescript-eslint/no-unused-expressions': 'off', |
|||
'@typescript-eslint/no-unused-vars': [ |
|||
'error', |
|||
{ |
|||
argsIgnorePattern: '^_', |
|||
varsIgnorePattern: '^_', |
|||
}, |
|||
], |
|||
'@typescript-eslint/no-use-before-define': 'off', |
|||
'@typescript-eslint/no-var-requires': 'error', |
|||
'unused-imports/no-unused-vars': 'off', |
|||
}, |
|||
}, |
|||
]; |
|||
} |
|||
@ -0,0 +1,45 @@ |
|||
import type { Linter } from 'eslint'; |
|||
|
|||
import { interopDefault } from '../util'; |
|||
|
|||
export async function unicorn(): Promise<Linter.Config[]> { |
|||
const [pluginUnicorn] = await Promise.all([ |
|||
interopDefault(import('eslint-plugin-unicorn')), |
|||
] as const); |
|||
|
|||
return [ |
|||
{ |
|||
plugins: { |
|||
unicorn: pluginUnicorn, |
|||
}, |
|||
rules: { |
|||
...pluginUnicorn.configs.recommended.rules, |
|||
|
|||
'unicorn/better-regex': 'off', |
|||
'unicorn/consistent-destructuring': 'off', |
|||
'unicorn/consistent-function-scoping': 'off', |
|||
'unicorn/expiring-todo-comments': 'off', |
|||
'unicorn/filename-case': 'off', |
|||
'unicorn/import-style': 'off', |
|||
'unicorn/no-array-for-each': 'off', |
|||
'unicorn/no-null': 'off', |
|||
'unicorn/no-useless-undefined': 'off', |
|||
'unicorn/prefer-at': 'off', |
|||
'unicorn/prefer-dom-node-text-content': 'off', |
|||
'unicorn/prefer-export-from': ['error', { ignoreUsedVariables: true }], |
|||
'unicorn/prefer-global-this': 'off', |
|||
'unicorn/prefer-top-level-await': 'off', |
|||
'unicorn/prevent-abbreviations': 'off', |
|||
}, |
|||
}, |
|||
{ |
|||
files: [ |
|||
'scripts/**/*.?([cm])[jt]s?(x)', |
|||
'internal/**/*.?([cm])[jt]s?(x)', |
|||
], |
|||
rules: { |
|||
'unicorn/no-process-exit': 'off', |
|||
}, |
|||
}, |
|||
]; |
|||
} |
|||
@ -0,0 +1,152 @@ |
|||
import type { Linter } from 'eslint'; |
|||
|
|||
import { interopDefault } from '../util'; |
|||
|
|||
export async function vue(): Promise<Linter.Config[]> { |
|||
const [pluginVue, parserVue, parserTs] = await Promise.all([ |
|||
interopDefault(import('eslint-plugin-vue')), |
|||
interopDefault(import('vue-eslint-parser')), |
|||
interopDefault(import('@typescript-eslint/parser')), |
|||
] as const); |
|||
|
|||
const flatEssential = pluginVue.configs?.['flat/essential'] || []; |
|||
const flatStronglyRecommended = |
|||
pluginVue.configs?.['flat/strongly-recommended'] || []; |
|||
const flatRecommended = pluginVue.configs?.['flat/recommended'] || []; |
|||
|
|||
return [ |
|||
...flatEssential, |
|||
...flatStronglyRecommended, |
|||
...flatRecommended, |
|||
{ |
|||
files: ['**/*.vue'], |
|||
languageOptions: { |
|||
// globals: {
|
|||
// computed: 'readonly',
|
|||
// defineEmits: 'readonly',
|
|||
// defineExpose: 'readonly',
|
|||
// defineProps: 'readonly',
|
|||
// onMounted: 'readonly',
|
|||
// onUnmounted: 'readonly',
|
|||
// reactive: 'readonly',
|
|||
// ref: 'readonly',
|
|||
// shallowReactive: 'readonly',
|
|||
// shallowRef: 'readonly',
|
|||
// toRef: 'readonly',
|
|||
// toRefs: 'readonly',
|
|||
// watch: 'readonly',
|
|||
// watchEffect: 'readonly',
|
|||
// },
|
|||
parser: parserVue, |
|||
parserOptions: { |
|||
ecmaFeatures: { |
|||
jsx: true, |
|||
}, |
|||
extraFileExtensions: ['.vue'], |
|||
parser: parserTs, |
|||
sourceType: 'module', |
|||
}, |
|||
}, |
|||
plugins: { |
|||
vue: pluginVue, |
|||
}, |
|||
processor: pluginVue.processors?.['.vue'], |
|||
rules: { |
|||
...pluginVue.configs?.base?.rules, |
|||
|
|||
'vue/attribute-hyphenation': [ |
|||
'error', |
|||
'always', |
|||
{ |
|||
ignore: [], |
|||
}, |
|||
], |
|||
'vue/attributes-order': 'off', |
|||
'vue/block-order': [ |
|||
'error', |
|||
{ |
|||
order: ['script', 'template', 'style'], |
|||
}, |
|||
], |
|||
'vue/component-name-in-template-casing': ['error', 'PascalCase'], |
|||
'vue/component-options-name-casing': ['error', 'PascalCase'], |
|||
'vue/custom-event-name-casing': ['error', 'camelCase'], |
|||
'vue/define-macros-order': [ |
|||
'error', |
|||
{ |
|||
order: [ |
|||
'defineOptions', |
|||
'defineProps', |
|||
'defineEmits', |
|||
'defineSlots', |
|||
], |
|||
}, |
|||
], |
|||
'vue/dot-location': ['error', 'property'], |
|||
'vue/dot-notation': ['error', { allowKeywords: true }], |
|||
'vue/eqeqeq': ['error', 'smart'], |
|||
'vue/html-closing-bracket-newline': 'error', |
|||
'vue/html-indent': 'off', |
|||
// 'vue/html-indent': ['error', 2],
|
|||
'vue/html-quotes': ['error', 'double'], |
|||
'vue/html-self-closing': [ |
|||
'error', |
|||
{ |
|||
html: { |
|||
component: 'always', |
|||
normal: 'never', |
|||
void: 'always', |
|||
}, |
|||
math: 'always', |
|||
svg: 'always', |
|||
}, |
|||
], |
|||
'vue/max-attributes-per-line': 'off', |
|||
'vue/multi-word-component-names': 'off', |
|||
'vue/multiline-html-element-content-newline': 'error', |
|||
'vue/no-empty-pattern': 'error', |
|||
'vue/no-extra-parens': ['error', 'functions'], |
|||
'vue/no-irregular-whitespace': 'error', |
|||
'vue/no-loss-of-precision': 'error', |
|||
'vue/no-reserved-component-names': 'off', |
|||
'vue/no-restricted-syntax': [ |
|||
'error', |
|||
'DebuggerStatement', |
|||
'LabeledStatement', |
|||
'WithStatement', |
|||
], |
|||
'vue/no-restricted-v-bind': ['error', '/^v-/'], |
|||
'vue/no-sparse-arrays': 'error', |
|||
'vue/no-unused-refs': 'error', |
|||
'vue/no-useless-v-bind': 'error', |
|||
'vue/object-shorthand': [ |
|||
'error', |
|||
'always', |
|||
{ |
|||
avoidQuotes: true, |
|||
ignoreConstructors: false, |
|||
}, |
|||
], |
|||
'vue/one-component-per-file': 'error', |
|||
'vue/prefer-import-from-vue': 'error', |
|||
'vue/prefer-separate-static-class': 'error', |
|||
'vue/prefer-template': 'error', |
|||
'vue/prop-name-casing': ['error', 'camelCase'], |
|||
'vue/require-default-prop': 'error', |
|||
'vue/require-explicit-emits': 'error', |
|||
'vue/require-prop-types': 'off', |
|||
'vue/singleline-html-element-content-newline': 'off', |
|||
'vue/space-infix-ops': 'error', |
|||
'vue/space-unary-ops': ['error', { nonwords: false, words: true }], |
|||
'vue/v-on-event-hyphenation': [ |
|||
'error', |
|||
'always', |
|||
{ |
|||
autofix: true, |
|||
ignore: [], |
|||
}, |
|||
], |
|||
}, |
|||
}, |
|||
]; |
|||
} |
|||
@ -0,0 +1,87 @@ |
|||
import type { Linter } from 'eslint'; |
|||
|
|||
import { interopDefault } from '../util'; |
|||
|
|||
export async function yaml(): Promise<Linter.Config[]> { |
|||
const [pluginYaml, parserYaml] = await Promise.all([ |
|||
interopDefault(import('eslint-plugin-yml')), |
|||
interopDefault(import('yaml-eslint-parser')), |
|||
] as const); |
|||
|
|||
return [ |
|||
{ |
|||
files: ['**/*.y?(a)ml'], |
|||
plugins: { |
|||
yaml: pluginYaml as any, |
|||
}, |
|||
languageOptions: { |
|||
parser: parserYaml, |
|||
}, |
|||
rules: { |
|||
'style/spaced-comment': 'off', |
|||
|
|||
'yaml/block-mapping': 'error', |
|||
'yaml/block-sequence': 'error', |
|||
'yaml/no-empty-key': 'error', |
|||
'yaml/no-empty-sequence-entry': 'error', |
|||
'yaml/no-irregular-whitespace': 'error', |
|||
'yaml/plain-scalar': 'error', |
|||
|
|||
'yaml/vue-custom-block/no-parsing-error': 'error', |
|||
|
|||
'yaml/block-mapping-question-indicator-newline': 'error', |
|||
'yaml/block-sequence-hyphen-indicator-newline': 'error', |
|||
'yaml/flow-mapping-curly-newline': 'error', |
|||
'yaml/flow-mapping-curly-spacing': 'error', |
|||
'yaml/flow-sequence-bracket-newline': 'error', |
|||
'yaml/flow-sequence-bracket-spacing': 'error', |
|||
'yaml/indent': ['error', 2], |
|||
'yaml/key-spacing': 'error', |
|||
'yaml/no-tab-indent': 'error', |
|||
'yaml/quotes': [ |
|||
'error', |
|||
{ |
|||
avoidEscape: true, |
|||
prefer: 'single', |
|||
}, |
|||
], |
|||
'yaml/spaced-comment': 'error', |
|||
}, |
|||
}, |
|||
{ |
|||
files: ['pnpm-workspace.yaml'], |
|||
rules: { |
|||
'yaml/sort-keys': [ |
|||
'error', |
|||
{ |
|||
order: [ |
|||
'packages', |
|||
'overrides', |
|||
'patchedDependencies', |
|||
'hoistPattern', |
|||
'catalog', |
|||
'catalogs', |
|||
|
|||
'allowedDeprecatedVersions', |
|||
'allowNonAppliedPatches', |
|||
'configDependencies', |
|||
'ignoredBuiltDependencies', |
|||
'ignoredOptionalDependencies', |
|||
'neverBuiltDependencies', |
|||
'onlyBuiltDependencies', |
|||
'onlyBuiltDependenciesFile', |
|||
'packageExtensions', |
|||
'peerDependencyRules', |
|||
'supportedArchitectures', |
|||
], |
|||
pathPattern: '^$', |
|||
}, |
|||
{ |
|||
order: { type: 'asc' }, |
|||
pathPattern: '.*', |
|||
}, |
|||
], |
|||
}, |
|||
}, |
|||
]; |
|||
} |
|||
@ -0,0 +1,168 @@ |
|||
import type { Linter } from 'eslint'; |
|||
|
|||
const restrictedImportIgnores = [ |
|||
'**/vite.config.mts', |
|||
'**/tailwind.config.mjs', |
|||
'**/postcss.config.mjs', |
|||
]; |
|||
|
|||
const customConfig: Linter.Config[] = [ |
|||
// shadcn-ui 内部组件是自动生成的,不做太多限制
|
|||
{ |
|||
files: ['packages/@core/ui-kit/shadcn-ui/**/**'], |
|||
rules: { |
|||
'vue/require-default-prop': 'off', |
|||
}, |
|||
}, |
|||
{ |
|||
files: [ |
|||
'apps/**/**', |
|||
'packages/effects/**/**', |
|||
'packages/utils/**/**', |
|||
'packages/types/**/**', |
|||
'packages/locales/**/**', |
|||
], |
|||
ignores: restrictedImportIgnores, |
|||
rules: { |
|||
'perfectionist/sort-interfaces': 'off', |
|||
'perfectionist/sort-objects': 'off', |
|||
}, |
|||
}, |
|||
{ |
|||
files: ['**/**.vue'], |
|||
ignores: restrictedImportIgnores, |
|||
rules: { |
|||
'perfectionist/sort-objects': 'off', |
|||
}, |
|||
}, |
|||
{ |
|||
// apps内部的一些基础规则
|
|||
files: ['apps/**/**'], |
|||
ignores: restrictedImportIgnores, |
|||
rules: { |
|||
'no-restricted-imports': [ |
|||
'error', |
|||
{ |
|||
patterns: [ |
|||
{ |
|||
group: ['#/api/*'], |
|||
message: |
|||
'The #/api package cannot be imported, please use the @core package itself', |
|||
}, |
|||
{ |
|||
group: ['#/layouts/*'], |
|||
message: |
|||
'The #/layouts package cannot be imported, please use the @core package itself', |
|||
}, |
|||
{ |
|||
group: ['#/locales/*'], |
|||
message: |
|||
'The #/locales package cannot be imported, please use the @core package itself', |
|||
}, |
|||
{ |
|||
group: ['#/stores/*'], |
|||
message: |
|||
'The #/stores package cannot be imported, please use the @core package itself', |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
'perfectionist/sort-interfaces': 'off', |
|||
}, |
|||
}, |
|||
{ |
|||
// @core内部组件,不能引入@vben/* 里面的包
|
|||
files: ['packages/@core/**/**'], |
|||
ignores: restrictedImportIgnores, |
|||
rules: { |
|||
'no-restricted-imports': [ |
|||
'error', |
|||
{ |
|||
patterns: [ |
|||
{ |
|||
group: ['@vben/*'], |
|||
message: |
|||
'The @core package cannot import the @vben package, please use the @core package itself', |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
}, |
|||
}, |
|||
{ |
|||
// @core/shared内部组件,不能引入@vben/* 或者 @vben-core/* 里面的包
|
|||
files: ['packages/@core/base/**/**'], |
|||
ignores: restrictedImportIgnores, |
|||
rules: { |
|||
'no-restricted-imports': [ |
|||
'error', |
|||
{ |
|||
patterns: [ |
|||
{ |
|||
group: ['@vben/*', '@vben-core/*'], |
|||
message: |
|||
'The @vben-core/shared package cannot import the @vben package, please use the @core/shared package itself', |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
}, |
|||
}, |
|||
|
|||
{ |
|||
// 不能引入@vben/*里面的包
|
|||
files: [ |
|||
'packages/types/**/**', |
|||
'packages/utils/**/**', |
|||
'packages/icons/**/**', |
|||
'packages/constants/**/**', |
|||
'packages/styles/**/**', |
|||
'packages/stores/**/**', |
|||
'packages/preferences/**/**', |
|||
'packages/locales/**/**', |
|||
], |
|||
ignores: restrictedImportIgnores, |
|||
rules: { |
|||
'no-restricted-imports': [ |
|||
'error', |
|||
{ |
|||
patterns: [ |
|||
{ |
|||
group: ['@vben/*'], |
|||
message: |
|||
'The @vben package cannot be imported, please use the @core package itself', |
|||
}, |
|||
], |
|||
}, |
|||
], |
|||
}, |
|||
}, |
|||
// 后端模拟代码,不需要太多规则
|
|||
{ |
|||
files: ['apps/backend-mock/**/**', 'docs/**/**'], |
|||
rules: { |
|||
'@typescript-eslint/no-extraneous-class': 'off', |
|||
'n/no-extraneous-import': 'off', |
|||
'n/prefer-global/buffer': 'off', |
|||
'n/prefer-global/process': 'off', |
|||
'no-console': 'off', |
|||
'unicorn/prefer-module': 'off', |
|||
}, |
|||
}, |
|||
{ |
|||
files: ['**/**/playwright.config.ts'], |
|||
rules: { |
|||
'n/prefer-global/buffer': 'off', |
|||
'n/prefer-global/process': 'off', |
|||
'no-console': 'off', |
|||
}, |
|||
}, |
|||
{ |
|||
files: ['internal/**/**', 'scripts/**/**'], |
|||
rules: { |
|||
'no-console': 'off', |
|||
}, |
|||
}, |
|||
]; |
|||
|
|||
export { customConfig }; |
|||
@ -0,0 +1,64 @@ |
|||
import type { Linter } from 'eslint'; |
|||
|
|||
import { |
|||
command, |
|||
comments, |
|||
disableds, |
|||
ignores, |
|||
importPluginConfig, |
|||
javascript, |
|||
jsdoc, |
|||
jsonc, |
|||
node, |
|||
perfectionist, |
|||
pnpm, |
|||
prettier, |
|||
regexp, |
|||
test, |
|||
turbo, |
|||
typescript, |
|||
unicorn, |
|||
vue, |
|||
yaml, |
|||
} from './configs'; |
|||
import { customConfig } from './custom-config'; |
|||
|
|||
type FlatConfig = Linter.Config; |
|||
|
|||
type FlatConfigPromise = |
|||
| FlatConfig |
|||
| FlatConfig[] |
|||
| Promise<FlatConfig> |
|||
| Promise<FlatConfig[]>; |
|||
|
|||
async function defineConfig(config: FlatConfig[] = []) { |
|||
const configs: FlatConfigPromise[] = [ |
|||
vue(), |
|||
javascript(), |
|||
ignores(), |
|||
prettier(), |
|||
typescript(), |
|||
jsonc(), |
|||
disableds(), |
|||
importPluginConfig(), |
|||
node(), |
|||
perfectionist(), |
|||
comments(), |
|||
jsdoc(), |
|||
unicorn(), |
|||
test(), |
|||
regexp(), |
|||
command(), |
|||
turbo(), |
|||
yaml(), |
|||
pnpm(), |
|||
...customConfig, |
|||
...config, |
|||
]; |
|||
|
|||
const resolved = await Promise.all(configs); |
|||
|
|||
return resolved.flat(); |
|||
} |
|||
|
|||
export { defineConfig }; |
|||
@ -0,0 +1,8 @@ |
|||
export type Awaitable<T> = Promise<T> | T; |
|||
|
|||
export async function interopDefault<T>( |
|||
m: Awaitable<T>, |
|||
): Promise<T extends { default: infer U } ? U : T> { |
|||
const resolved = await m; |
|||
return (resolved as any).default || resolved; |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
{ |
|||
"$schema": "https://json.schemastore.org/tsconfig", |
|||
"extends": "@vben/tsconfig/node.json", |
|||
"include": ["src"], |
|||
"exclude": ["node_modules"] |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
export default { |
|||
endOfLine: 'auto', |
|||
overrides: [ |
|||
{ |
|||
files: ['*.json5'], |
|||
options: { |
|||
quoteProps: 'preserve', |
|||
singleQuote: false, |
|||
}, |
|||
}, |
|||
], |
|||
plugins: ['prettier-plugin-tailwindcss'], |
|||
printWidth: 80, |
|||
proseWrap: 'never', |
|||
semi: true, |
|||
singleQuote: true, |
|||
trailingComma: 'all', |
|||
}; |
|||
@ -0,0 +1,28 @@ |
|||
{ |
|||
"name": "@vben/prettier-config", |
|||
"version": "5.6.0", |
|||
"private": true, |
|||
"homepage": "https://github.com/vbenjs/vue-vben-admin", |
|||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git+https://github.com/vbenjs/vue-vben-admin.git", |
|||
"directory": "internal/lint-configs/prettier-config" |
|||
}, |
|||
"license": "MIT", |
|||
"type": "module", |
|||
"files": [ |
|||
"dist" |
|||
], |
|||
"main": "./index.mjs", |
|||
"module": "./index.mjs", |
|||
"exports": { |
|||
".": { |
|||
"default": "./index.mjs" |
|||
} |
|||
}, |
|||
"dependencies": { |
|||
"prettier": "catalog:", |
|||
"prettier-plugin-tailwindcss": "catalog:" |
|||
} |
|||
} |
|||
@ -0,0 +1,142 @@ |
|||
export default { |
|||
extends: ['stylelint-config-standard', 'stylelint-config-recess-order'], |
|||
ignoreFiles: [ |
|||
'**/*.js', |
|||
'**/*.jsx', |
|||
'**/*.tsx', |
|||
'**/*.ts', |
|||
'**/*.json', |
|||
'**/*.md', |
|||
], |
|||
overrides: [ |
|||
{ |
|||
customSyntax: 'postcss-html', |
|||
files: ['*.(html|vue)', '**/*.(html|vue)'], |
|||
rules: { |
|||
'selector-pseudo-class-no-unknown': [ |
|||
true, |
|||
{ |
|||
ignorePseudoClasses: ['global', 'deep'], |
|||
}, |
|||
], |
|||
'selector-pseudo-element-no-unknown': [ |
|||
true, |
|||
{ |
|||
ignorePseudoElements: ['v-deep', 'v-global', 'v-slotted'], |
|||
}, |
|||
], |
|||
}, |
|||
}, |
|||
{ |
|||
customSyntax: 'postcss-scss', |
|||
extends: [ |
|||
'stylelint-config-recommended-scss', |
|||
'stylelint-config-recommended-vue/scss', |
|||
], |
|||
files: ['*.scss', '**/*.scss'], |
|||
}, |
|||
], |
|||
plugins: [ |
|||
'stylelint-order', |
|||
'@stylistic/stylelint-plugin', |
|||
'stylelint-prettier', |
|||
'stylelint-scss', |
|||
], |
|||
rules: { |
|||
'at-rule-no-deprecated': null, |
|||
'at-rule-no-unknown': [ |
|||
true, |
|||
{ |
|||
ignoreAtRules: [ |
|||
'extends', |
|||
'ignores', |
|||
'include', |
|||
'mixin', |
|||
'if', |
|||
'else', |
|||
'media', |
|||
'for', |
|||
'at-root', |
|||
'tailwind', |
|||
'apply', |
|||
'variants', |
|||
'responsive', |
|||
'screen', |
|||
'function', |
|||
'each', |
|||
'use', |
|||
'forward', |
|||
'return', |
|||
], |
|||
}, |
|||
], |
|||
'font-family-no-missing-generic-family-keyword': null, |
|||
'function-no-unknown': null, |
|||
'import-notation': null, |
|||
'media-feature-range-notation': null, |
|||
'named-grid-areas-no-invalid': null, |
|||
'nesting-selector-no-missing-scoping-root': null, |
|||
'no-descending-specificity': null, |
|||
'no-empty-source': null, |
|||
'order/order': [ |
|||
[ |
|||
'dollar-variables', |
|||
'custom-properties', |
|||
'at-rules', |
|||
'declarations', |
|||
{ |
|||
name: 'supports', |
|||
type: 'at-rule', |
|||
}, |
|||
{ |
|||
name: 'media', |
|||
type: 'at-rule', |
|||
}, |
|||
{ |
|||
name: 'include', |
|||
type: 'at-rule', |
|||
}, |
|||
'rules', |
|||
], |
|||
{ severity: 'error' }, |
|||
], |
|||
'prettier/prettier': true, |
|||
'rule-empty-line-before': [ |
|||
'always', |
|||
{ |
|||
ignore: ['after-comment', 'first-nested'], |
|||
}, |
|||
], |
|||
'scss/at-rule-no-unknown': [ |
|||
true, |
|||
{ |
|||
ignoreAtRules: [ |
|||
'extends', |
|||
'ignores', |
|||
'include', |
|||
'mixin', |
|||
'if', |
|||
'else', |
|||
'media', |
|||
'for', |
|||
'at-root', |
|||
'tailwind', |
|||
'apply', |
|||
'variants', |
|||
'responsive', |
|||
'screen', |
|||
'function', |
|||
'each', |
|||
'use', |
|||
'forward', |
|||
'return', |
|||
], |
|||
}, |
|||
], |
|||
'scss/operator-no-newline-after': null, |
|||
'selector-class-pattern': |
|||
'^(?:(?:o|c|u|t|s|is|has|_|js|qa)-)?[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*(?:__[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*)?(?:--[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*)?(?:[.+])?$', |
|||
|
|||
'selector-not-notation': null, |
|||
}, |
|||
}; |
|||
@ -0,0 +1,43 @@ |
|||
{ |
|||
"name": "@vben/stylelint-config", |
|||
"version": "5.6.0", |
|||
"private": true, |
|||
"homepage": "https://github.com/vbenjs/vue-vben-admin", |
|||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git+https://github.com/vbenjs/vue-vben-admin.git", |
|||
"directory": "internal/lint-configs/stylelint-config" |
|||
}, |
|||
"license": "MIT", |
|||
"type": "module", |
|||
"files": [ |
|||
"dist" |
|||
], |
|||
"main": "./index.mjs", |
|||
"module": "./index.mjs", |
|||
"exports": { |
|||
".": { |
|||
"import": "./index.mjs", |
|||
"default": "./index.mjs" |
|||
} |
|||
}, |
|||
"dependencies": { |
|||
"@stylistic/stylelint-plugin": "catalog:", |
|||
"stylelint-config-recess-order": "catalog:", |
|||
"stylelint-scss": "catalog:" |
|||
}, |
|||
"devDependencies": { |
|||
"postcss": "catalog:", |
|||
"postcss-html": "catalog:", |
|||
"postcss-scss": "catalog:", |
|||
"prettier": "catalog:", |
|||
"stylelint": "catalog:", |
|||
"stylelint-config-recommended": "catalog:", |
|||
"stylelint-config-recommended-scss": "catalog:", |
|||
"stylelint-config-recommended-vue": "catalog:", |
|||
"stylelint-config-standard": "catalog:", |
|||
"stylelint-order": "catalog:", |
|||
"stylelint-prettier": "catalog:" |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
import { defineBuildConfig } from 'unbuild'; |
|||
|
|||
export default defineBuildConfig({ |
|||
clean: true, |
|||
declaration: true, |
|||
entries: ['src/index'], |
|||
}); |
|||
@ -0,0 +1,43 @@ |
|||
{ |
|||
"name": "@vben/node-utils", |
|||
"version": "5.6.0", |
|||
"private": true, |
|||
"homepage": "https://github.com/vbenjs/vue-vben-admin", |
|||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git+https://github.com/vbenjs/vue-vben-admin.git", |
|||
"directory": "internal/node-utils" |
|||
}, |
|||
"license": "MIT", |
|||
"type": "module", |
|||
"scripts": { |
|||
"stub": "pnpm unbuild --stub" |
|||
}, |
|||
"files": [ |
|||
"dist" |
|||
], |
|||
"main": "./dist/index.mjs", |
|||
"module": "./dist/index.mjs", |
|||
"types": "./dist/index.d.ts", |
|||
"exports": { |
|||
".": { |
|||
"types": "./src/index.ts", |
|||
"import": "./dist/index.mjs", |
|||
"default": "./dist/index.mjs" |
|||
} |
|||
}, |
|||
"dependencies": { |
|||
"@changesets/git": "catalog:", |
|||
"@manypkg/get-packages": "catalog:", |
|||
"chalk": "catalog:", |
|||
"consola": "catalog:", |
|||
"dayjs": "catalog:", |
|||
"execa": "catalog:", |
|||
"find-up": "catalog:", |
|||
"ora": "catalog:", |
|||
"pkg-types": "catalog:", |
|||
"prettier": "catalog:", |
|||
"rimraf": "catalog:" |
|||
} |
|||
} |
|||
@ -0,0 +1,52 @@ |
|||
import { createHash } from 'node:crypto'; |
|||
|
|||
import { describe, expect, it } from 'vitest'; |
|||
|
|||
import { generatorContentHash } from '../hash'; |
|||
|
|||
describe('generatorContentHash', () => { |
|||
it('should generate an MD5 hash for the content', () => { |
|||
const content = 'example content'; |
|||
const expectedHash = createHash('md5') |
|||
.update(content, 'utf8') |
|||
.digest('hex'); |
|||
const actualHash = generatorContentHash(content); |
|||
expect(actualHash).toBe(expectedHash); |
|||
}); |
|||
|
|||
it('should generate an MD5 hash with specified length', () => { |
|||
const content = 'example content'; |
|||
const hashLength = 10; |
|||
const generatedHash = generatorContentHash(content, hashLength); |
|||
expect(generatedHash).toHaveLength(hashLength); |
|||
}); |
|||
|
|||
it('should correctly generate the hash with specified length', () => { |
|||
const content = 'example content'; |
|||
const hashLength = 8; |
|||
const expectedHash = createHash('md5') |
|||
.update(content, 'utf8') |
|||
.digest('hex') |
|||
.slice(0, hashLength); |
|||
const generatedHash = generatorContentHash(content, hashLength); |
|||
expect(generatedHash).toBe(expectedHash); |
|||
}); |
|||
|
|||
it('should return full hash if hash length parameter is not provided', () => { |
|||
const content = 'example content'; |
|||
const expectedHash = createHash('md5') |
|||
.update(content, 'utf8') |
|||
.digest('hex'); |
|||
const actualHash = generatorContentHash(content); |
|||
expect(actualHash).toBe(expectedHash); |
|||
}); |
|||
|
|||
it('should handle empty content', () => { |
|||
const content = ''; |
|||
const expectedHash = createHash('md5') |
|||
.update(content, 'utf8') |
|||
.digest('hex'); |
|||
const actualHash = generatorContentHash(content); |
|||
expect(actualHash).toBe(expectedHash); |
|||
}); |
|||
}); |
|||
@ -0,0 +1,67 @@ |
|||
// pathUtils.test.ts
|
|||
|
|||
import { describe, expect, it } from 'vitest'; |
|||
|
|||
import { toPosixPath } from '../path'; |
|||
|
|||
describe('toPosixPath', () => { |
|||
// 测试 Windows 风格路径到 POSIX 风格路径的转换
|
|||
it('converts Windows-style paths to POSIX paths', () => { |
|||
const windowsPath = String.raw`C:\Users\Example\file.txt`; |
|||
const expectedPosixPath = 'C:/Users/Example/file.txt'; |
|||
expect(toPosixPath(windowsPath)).toBe(expectedPosixPath); |
|||
}); |
|||
|
|||
// 确认 POSIX 风格路径不会被改变
|
|||
it('leaves POSIX-style paths unchanged', () => { |
|||
const posixPath = '/home/user/file.txt'; |
|||
expect(toPosixPath(posixPath)).toBe(posixPath); |
|||
}); |
|||
|
|||
// 测试带有多个分隔符的路径
|
|||
it('converts paths with mixed separators', () => { |
|||
const mixedPath = String.raw`C:/Users\Example\file.txt`; |
|||
const expectedPosixPath = 'C:/Users/Example/file.txt'; |
|||
expect(toPosixPath(mixedPath)).toBe(expectedPosixPath); |
|||
}); |
|||
|
|||
// 测试空字符串
|
|||
it('handles empty strings', () => { |
|||
const emptyPath = ''; |
|||
expect(toPosixPath(emptyPath)).toBe(''); |
|||
}); |
|||
|
|||
// 测试仅包含分隔符的路径
|
|||
it('handles path with only separators', () => { |
|||
const separatorsPath = '\\\\\\'; |
|||
const expectedPosixPath = '///'; |
|||
expect(toPosixPath(separatorsPath)).toBe(expectedPosixPath); |
|||
}); |
|||
|
|||
// 测试不包含任何分隔符的路径
|
|||
it('handles path without separators', () => { |
|||
const noSeparatorPath = 'file.txt'; |
|||
expect(toPosixPath(noSeparatorPath)).toBe('file.txt'); |
|||
}); |
|||
|
|||
// 测试以分隔符结尾的路径
|
|||
it('handles path ending with a separator', () => { |
|||
const endingSeparatorPath = 'C:\\Users\\Example\\'; |
|||
const expectedPosixPath = 'C:/Users/Example/'; |
|||
expect(toPosixPath(endingSeparatorPath)).toBe(expectedPosixPath); |
|||
}); |
|||
|
|||
// 测试以分隔符开头的路径
|
|||
it('handles path starting with a separator', () => { |
|||
const startingSeparatorPath = String.raw`\Users\Example`; |
|||
const expectedPosixPath = '/Users/Example'; |
|||
expect(toPosixPath(startingSeparatorPath)).toBe(expectedPosixPath); |
|||
}); |
|||
|
|||
// 测试包含非法字符的路径
|
|||
it('handles path with invalid characters', () => { |
|||
const invalidCharsPath = String.raw`C:\Us*?ers\Ex<ample>|file.txt`; |
|||
const expectedPosixPath = 'C:/Us*?ers/Ex<ample>|file.txt'; |
|||
expect(toPosixPath(invalidCharsPath)).toBe(expectedPosixPath); |
|||
}); |
|||
}); |
|||
@ -0,0 +1,6 @@ |
|||
enum UNICODE { |
|||
FAILURE = '\u2716', // ✖
|
|||
SUCCESS = '\u2714', // ✔
|
|||
} |
|||
|
|||
export { UNICODE }; |
|||
@ -0,0 +1,12 @@ |
|||
import dayjs from 'dayjs'; |
|||
import timezone from 'dayjs/plugin/timezone'; |
|||
import utc from 'dayjs/plugin/utc'; |
|||
|
|||
dayjs.extend(utc); |
|||
dayjs.extend(timezone); |
|||
|
|||
dayjs.tz.setDefault('Asia/Shanghai'); |
|||
|
|||
const dateUtil = dayjs; |
|||
|
|||
export { dateUtil }; |
|||
@ -0,0 +1,39 @@ |
|||
import { promises as fs } from 'node:fs'; |
|||
import { dirname } from 'node:path'; |
|||
|
|||
export async function outputJSON( |
|||
filePath: string, |
|||
data: any, |
|||
spaces: number = 2, |
|||
) { |
|||
try { |
|||
const dir = dirname(filePath); |
|||
await fs.mkdir(dir, { recursive: true }); |
|||
const jsonData = JSON.stringify(data, null, spaces); |
|||
await fs.writeFile(filePath, jsonData, 'utf8'); |
|||
} catch (error) { |
|||
console.error('Error writing JSON file:', error); |
|||
throw error; |
|||
} |
|||
} |
|||
|
|||
export async function ensureFile(filePath: string) { |
|||
try { |
|||
const dir = dirname(filePath); |
|||
await fs.mkdir(dir, { recursive: true }); |
|||
await fs.writeFile(filePath, '', { flag: 'a' }); |
|||
} catch (error) { |
|||
console.error('Error ensuring file:', error); |
|||
throw error; |
|||
} |
|||
} |
|||
|
|||
export async function readJSON(filePath: string) { |
|||
try { |
|||
const data = await fs.readFile(filePath, 'utf8'); |
|||
return JSON.parse(data); |
|||
} catch (error) { |
|||
console.error('Error reading JSON file:', error); |
|||
throw error; |
|||
} |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
import path from 'node:path'; |
|||
|
|||
import { execa } from 'execa'; |
|||
|
|||
export * from '@changesets/git'; |
|||
|
|||
/** |
|||
* 获取暂存区文件 |
|||
*/ |
|||
async function getStagedFiles(): Promise<string[]> { |
|||
try { |
|||
const { stdout } = await execa('git', [ |
|||
'-c', |
|||
'submodule.recurse=false', |
|||
'diff', |
|||
'--staged', |
|||
'--diff-filter=ACMR', |
|||
'--name-only', |
|||
'--ignore-submodules', |
|||
'-z', |
|||
]); |
|||
|
|||
let changedList = stdout ? stdout.replace(/\0$/, '').split('\0') : []; |
|||
changedList = changedList.map((item) => path.resolve(process.cwd(), item)); |
|||
const changedSet = new Set(changedList); |
|||
changedSet.delete(''); |
|||
return [...changedSet]; |
|||
} catch (error) { |
|||
console.error('Failed to get staged files:', error); |
|||
return []; |
|||
} |
|||
} |
|||
|
|||
export { getStagedFiles }; |
|||
@ -0,0 +1,18 @@ |
|||
import { createHash } from 'node:crypto'; |
|||
|
|||
/** |
|||
* 生产基于内容的 hash,可自定义长度 |
|||
* @param content |
|||
* @param hashLSize |
|||
*/ |
|||
function generatorContentHash(content: string, hashLSize?: number) { |
|||
const hash = createHash('md5').update(content, 'utf8').digest('hex'); |
|||
|
|||
if (hashLSize) { |
|||
return hash.slice(0, hashLSize); |
|||
} |
|||
|
|||
return hash; |
|||
} |
|||
|
|||
export { generatorContentHash }; |
|||
@ -0,0 +1,19 @@ |
|||
export * from './constants'; |
|||
export * from './date'; |
|||
export * from './fs'; |
|||
export * from './git'; |
|||
export { getStagedFiles, add as gitAdd } from './git'; |
|||
export { generatorContentHash } from './hash'; |
|||
export * from './monorepo'; |
|||
export { toPosixPath } from './path'; |
|||
export { prettierFormat } from './prettier'; |
|||
export * from './spinner'; |
|||
export type { Package } from '@manypkg/get-packages'; |
|||
export { default as colors } from 'chalk'; |
|||
export { consola } from 'consola'; |
|||
export * from 'execa'; |
|||
|
|||
export { default as fs } from 'node:fs/promises'; |
|||
|
|||
export { type PackageJson, readPackageJSON } from 'pkg-types'; |
|||
export { rimraf } from 'rimraf'; |
|||
@ -0,0 +1,46 @@ |
|||
import { dirname } from 'node:path'; |
|||
|
|||
import { |
|||
getPackages as getPackagesFunc, |
|||
getPackagesSync as getPackagesSyncFunc, |
|||
} from '@manypkg/get-packages'; |
|||
import { findUpSync } from 'find-up'; |
|||
|
|||
/** |
|||
* 查找大仓的根目录 |
|||
* @param cwd |
|||
*/ |
|||
function findMonorepoRoot(cwd: string = process.cwd()) { |
|||
const lockFile = findUpSync('pnpm-lock.yaml', { |
|||
cwd, |
|||
type: 'file', |
|||
}); |
|||
return dirname(lockFile || ''); |
|||
} |
|||
|
|||
/** |
|||
* 获取大仓的所有包 |
|||
*/ |
|||
function getPackagesSync() { |
|||
const root = findMonorepoRoot(); |
|||
return getPackagesSyncFunc(root); |
|||
} |
|||
|
|||
/** |
|||
* 获取大仓的所有包 |
|||
*/ |
|||
async function getPackages() { |
|||
const root = findMonorepoRoot(); |
|||
|
|||
return await getPackagesFunc(root); |
|||
} |
|||
|
|||
/** |
|||
* 获取大仓指定的包 |
|||
*/ |
|||
async function getPackage(pkgName: string) { |
|||
const { packages } = await getPackages(); |
|||
return packages.find((pkg) => pkg.packageJson.name === pkgName); |
|||
} |
|||
|
|||
export { findMonorepoRoot, getPackage, getPackages, getPackagesSync }; |
|||
@ -0,0 +1,11 @@ |
|||
import { posix } from 'node:path'; |
|||
|
|||
/** |
|||
* 将给定的文件路径转换为 POSIX 风格。 |
|||
* @param {string} pathname - 原始文件路径。 |
|||
*/ |
|||
function toPosixPath(pathname: string) { |
|||
return pathname.split(`\\`).join(posix.sep); |
|||
} |
|||
|
|||
export { toPosixPath }; |
|||
@ -0,0 +1,21 @@ |
|||
import fs from 'node:fs/promises'; |
|||
|
|||
import { format, getFileInfo, resolveConfig } from 'prettier'; |
|||
|
|||
async function prettierFormat(filepath: string) { |
|||
const prettierOptions = await resolveConfig(filepath, {}); |
|||
|
|||
const fileInfo = await getFileInfo(filepath); |
|||
|
|||
const input = await fs.readFile(filepath, 'utf8'); |
|||
const output = await format(input, { |
|||
...prettierOptions, |
|||
parser: fileInfo.inferredParser as any, |
|||
}); |
|||
if (output !== input) { |
|||
await fs.writeFile(filepath, output, 'utf8'); |
|||
} |
|||
return output; |
|||
} |
|||
|
|||
export { prettierFormat }; |
|||
@ -0,0 +1,26 @@ |
|||
import type { Ora } from 'ora'; |
|||
|
|||
import ora from 'ora'; |
|||
|
|||
interface SpinnerOptions { |
|||
failedText?: string; |
|||
successText?: string; |
|||
title: string; |
|||
} |
|||
export async function spinner<T>( |
|||
{ failedText, successText, title }: SpinnerOptions, |
|||
callback: () => Promise<T>, |
|||
): Promise<T> { |
|||
const loading: Ora = ora(title).start(); |
|||
|
|||
try { |
|||
const result = await callback(); |
|||
loading.succeed(successText || 'Success!'); |
|||
return result; |
|||
} catch (error) { |
|||
loading.fail(failedText || 'Failed!'); |
|||
throw error; |
|||
} finally { |
|||
loading.stop(); |
|||
} |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
{ |
|||
"$schema": "https://json.schemastore.org/tsconfig", |
|||
"extends": "@vben/tsconfig/node.json", |
|||
"include": ["src"], |
|||
"exclude": ["node_modules"] |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
import { defineBuildConfig } from 'unbuild'; |
|||
|
|||
export default defineBuildConfig({ |
|||
clean: true, |
|||
declaration: true, |
|||
entries: ['src/index', './src/postcss.config'], |
|||
rollup: { |
|||
emitCJS: true, |
|||
}, |
|||
}); |
|||
@ -0,0 +1,67 @@ |
|||
{ |
|||
"name": "@vben/tailwind-config", |
|||
"version": "5.6.0", |
|||
"private": true, |
|||
"homepage": "https://github.com/vbenjs/vue-vben-admin", |
|||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git+https://github.com/vbenjs/vue-vben-admin.git", |
|||
"directory": "internal/tailwind-config" |
|||
}, |
|||
"license": "MIT", |
|||
"type": "module", |
|||
"scripts": { |
|||
"stub": "pnpm unbuild --stub" |
|||
}, |
|||
"files": [ |
|||
"dist" |
|||
], |
|||
"main": "./dist/index.mjs", |
|||
"module": "./dist/index.mjs", |
|||
"types": "./dist/index.d.ts", |
|||
"typesVersions": { |
|||
"*": { |
|||
"*": [ |
|||
"./dist/*", |
|||
"./*" |
|||
] |
|||
} |
|||
}, |
|||
"exports": { |
|||
".": { |
|||
"types": "./src/index.ts", |
|||
"import": "./dist/index.mjs", |
|||
"require": "./dist/index.cjs" |
|||
}, |
|||
"./postcss": { |
|||
"types": "./src/postcss.config.ts", |
|||
"import": "./dist/postcss.config.mjs", |
|||
"require": "./dist/postcss.config.cjs", |
|||
"default": "./dist/postcss.config.mjs" |
|||
}, |
|||
"./*": "./*" |
|||
}, |
|||
"peerDependencies": { |
|||
"tailwindcss": "^3.4.3" |
|||
}, |
|||
"dependencies": { |
|||
"@iconify/json": "catalog:", |
|||
"@iconify/tailwind": "catalog:", |
|||
"@manypkg/get-packages": "catalog:", |
|||
"@tailwindcss/nesting": "catalog:", |
|||
"@tailwindcss/typography": "catalog:", |
|||
"autoprefixer": "catalog:", |
|||
"cssnano": "catalog:", |
|||
"jiti": "catalog:", |
|||
"postcss": "catalog:", |
|||
"postcss-antd-fixes": "catalog:", |
|||
"postcss-import": "catalog:", |
|||
"postcss-preset-env": "catalog:", |
|||
"tailwindcss": "catalog:", |
|||
"tailwindcss-animate": "catalog:" |
|||
}, |
|||
"devDependencies": { |
|||
"@types/postcss-import": "catalog:" |
|||
} |
|||
} |
|||
@ -0,0 +1,266 @@ |
|||
import type { Config } from 'tailwindcss'; |
|||
|
|||
import path from 'node:path'; |
|||
|
|||
import { addDynamicIconSelectors } from '@iconify/tailwind'; |
|||
import { getPackagesSync } from '@manypkg/get-packages'; |
|||
import typographyPlugin from '@tailwindcss/typography'; |
|||
import animate from 'tailwindcss-animate'; |
|||
|
|||
import { enterAnimationPlugin } from './plugins/entry'; |
|||
|
|||
// import defaultTheme from 'tailwindcss/defaultTheme';
|
|||
|
|||
const { packages } = getPackagesSync(process.cwd()); |
|||
|
|||
const tailwindPackages: string[] = []; |
|||
|
|||
packages.forEach((pkg) => { |
|||
// apps目录下和 @vben-core/tailwind-ui 包需要使用到 tailwindcss ui
|
|||
// if (fs.existsSync(path.join(pkg.dir, 'tailwind.config.mjs'))) {
|
|||
tailwindPackages.push(pkg.dir); |
|||
// }
|
|||
}); |
|||
|
|||
const shadcnUiColors = { |
|||
accent: { |
|||
DEFAULT: 'hsl(var(--accent))', |
|||
foreground: 'hsl(var(--accent-foreground))', |
|||
hover: 'hsl(var(--accent-hover))', |
|||
lighter: 'has(val(--accent-lighter))', |
|||
}, |
|||
background: { |
|||
deep: 'hsl(var(--background-deep))', |
|||
DEFAULT: 'hsl(var(--background))', |
|||
}, |
|||
border: { |
|||
DEFAULT: 'hsl(var(--border))', |
|||
}, |
|||
card: { |
|||
DEFAULT: 'hsl(var(--card))', |
|||
foreground: 'hsl(var(--card-foreground))', |
|||
}, |
|||
destructive: { |
|||
...createColorsPalette('destructive'), |
|||
DEFAULT: 'hsl(var(--destructive))', |
|||
}, |
|||
|
|||
foreground: { |
|||
DEFAULT: 'hsl(var(--foreground))', |
|||
}, |
|||
|
|||
input: { |
|||
background: 'hsl(var(--input-background))', |
|||
DEFAULT: 'hsl(var(--input))', |
|||
}, |
|||
muted: { |
|||
DEFAULT: 'hsl(var(--muted))', |
|||
foreground: 'hsl(var(--muted-foreground))', |
|||
}, |
|||
popover: { |
|||
DEFAULT: 'hsl(var(--popover))', |
|||
foreground: 'hsl(var(--popover-foreground))', |
|||
}, |
|||
primary: { |
|||
...createColorsPalette('primary'), |
|||
DEFAULT: 'hsl(var(--primary))', |
|||
}, |
|||
|
|||
ring: 'hsl(var(--ring))', |
|||
secondary: { |
|||
DEFAULT: 'hsl(var(--secondary))', |
|||
desc: 'hsl(var(--secondary-desc))', |
|||
foreground: 'hsl(var(--secondary-foreground))', |
|||
}, |
|||
}; |
|||
|
|||
const customColors = { |
|||
green: { |
|||
...createColorsPalette('green'), |
|||
foreground: 'hsl(var(--success-foreground))', |
|||
}, |
|||
header: { |
|||
DEFAULT: 'hsl(var(--header))', |
|||
}, |
|||
heavy: { |
|||
DEFAULT: 'hsl(var(--heavy))', |
|||
foreground: 'hsl(var(--heavy-foreground))', |
|||
}, |
|||
main: { |
|||
DEFAULT: 'hsl(var(--main))', |
|||
}, |
|||
overlay: { |
|||
content: 'hsl(var(--overlay-content))', |
|||
DEFAULT: 'hsl(var(--overlay))', |
|||
}, |
|||
red: { |
|||
...createColorsPalette('red'), |
|||
foreground: 'hsl(var(--destructive-foreground))', |
|||
}, |
|||
sidebar: { |
|||
deep: 'hsl(var(--sidebar-deep))', |
|||
DEFAULT: 'hsl(var(--sidebar))', |
|||
}, |
|||
success: { |
|||
...createColorsPalette('success'), |
|||
DEFAULT: 'hsl(var(--success))', |
|||
}, |
|||
warning: { |
|||
...createColorsPalette('warning'), |
|||
DEFAULT: 'hsl(var(--warning))', |
|||
}, |
|||
yellow: { |
|||
...createColorsPalette('yellow'), |
|||
foreground: 'hsl(var(--warning-foreground))', |
|||
}, |
|||
}; |
|||
|
|||
export default { |
|||
content: [ |
|||
'./index.html', |
|||
...tailwindPackages.map((item) => |
|||
path.join(item, 'src/**/*.{vue,js,ts,jsx,tsx,svelte,astro,html}'), |
|||
), |
|||
], |
|||
darkMode: 'selector', |
|||
plugins: [ |
|||
animate, |
|||
typographyPlugin, |
|||
addDynamicIconSelectors(), |
|||
enterAnimationPlugin, |
|||
], |
|||
prefix: '', |
|||
theme: { |
|||
container: { |
|||
center: true, |
|||
padding: '2rem', |
|||
screens: { |
|||
'2xl': '1400px', |
|||
}, |
|||
}, |
|||
extend: { |
|||
animation: { |
|||
'accordion-down': 'accordion-down 0.2s ease-out', |
|||
'accordion-up': 'accordion-up 0.2s ease-out', |
|||
'collapsible-down': 'collapsible-down 0.2s ease-in-out', |
|||
'collapsible-up': 'collapsible-up 0.2s ease-in-out', |
|||
float: 'float 5s linear 0ms infinite', |
|||
}, |
|||
|
|||
animationDuration: { |
|||
'2000': '2000ms', |
|||
'3000': '3000ms', |
|||
}, |
|||
borderRadius: { |
|||
lg: 'var(--radius)', |
|||
md: 'calc(var(--radius) - 2px)', |
|||
sm: 'calc(var(--radius) - 4px)', |
|||
xl: 'calc(var(--radius) + 4px)', |
|||
}, |
|||
boxShadow: { |
|||
float: `0 6px 16px 0 rgb(0 0 0 / 8%),
|
|||
0 3px 6px -4px rgb(0 0 0 / 12%), |
|||
0 9px 28px 8px rgb(0 0 0 / 5%)`,
|
|||
}, |
|||
colors: { |
|||
...customColors, |
|||
...shadcnUiColors, |
|||
}, |
|||
fontFamily: { |
|||
sans: [ |
|||
'var(--font-family)', |
|||
// ...defaultTheme.fontFamily.sans
|
|||
], |
|||
}, |
|||
keyframes: { |
|||
'accordion-down': { |
|||
from: { height: '0' }, |
|||
to: { height: 'var(--reka-accordion-content-height)' }, |
|||
}, |
|||
'accordion-up': { |
|||
from: { height: 'var(--reka-accordion-content-height)' }, |
|||
to: { height: '0' }, |
|||
}, |
|||
'collapsible-down': { |
|||
from: { height: '0' }, |
|||
to: { height: 'var(--reka-collapsible-content-height)' }, |
|||
}, |
|||
'collapsible-up': { |
|||
from: { height: 'var(--reka-collapsible-content-height)' }, |
|||
to: { height: '0' }, |
|||
}, |
|||
float: { |
|||
'0%': { transform: 'translateY(0)' }, |
|||
'50%': { transform: 'translateY(-20px)' }, |
|||
'100%': { transform: 'translateY(0)' }, |
|||
}, |
|||
}, |
|||
zIndex: { |
|||
'100': '100', |
|||
'1000': '1000', |
|||
}, |
|||
}, |
|||
}, |
|||
safelist: ['dark'], |
|||
} as Config; |
|||
|
|||
function createColorsPalette(name: string) { |
|||
// backgroundLightest: '#EFF6FF', // Tailwind CSS 默认的 `blue-50`
|
|||
// backgroundLighter: '#DBEAFE', // Tailwind CSS 默认的 `blue-100`
|
|||
// backgroundLight: '#BFDBFE', // Tailwind CSS 默认的 `blue-200`
|
|||
// borderLight: '#93C5FD', // Tailwind CSS 默认的 `blue-300`
|
|||
// border: '#60A5FA', // Tailwind CSS 默认的 `blue-400`
|
|||
// main: '#3B82F6', // Tailwind CSS 默认的 `blue-500`
|
|||
// hover: '#2563EB', // Tailwind CSS 默认的 `blue-600`
|
|||
// active: '#1D4ED8', // Tailwind CSS 默认的 `blue-700`
|
|||
// backgroundDark: '#1E40AF', // Tailwind CSS 默认的 `blue-800`
|
|||
// backgroundDarker: '#1E3A8A', // Tailwind CSS 默认的 `blue-900`
|
|||
// backgroundDarkest: '#172554', // Tailwind CSS 默认的 `blue-950`
|
|||
|
|||
// • backgroundLightest (#EFF6FF): 适用于最浅的背景色,可能用于非常轻微的阴影或卡片的背景。
|
|||
// • backgroundLighter (#DBEAFE): 适用于略浅的背景色,通常用于次要背景或略浅的区域。
|
|||
// • backgroundLight (#BFDBFE): 适用于浅色背景,可能用于输入框或表单区域的背景。
|
|||
// • borderLight (#93C5FD): 适用于浅色边框,可能用于输入框或卡片的边框。
|
|||
// • border (#60A5FA): 适用于普通边框,可能用于按钮或卡片的边框。
|
|||
// • main (#3B82F6): 适用于主要的主题色,通常用于按钮、链接或主要的强调色。
|
|||
// • hover (#2563EB): 适用于鼠标悬停状态下的颜色,例如按钮悬停时的背景色或边框色。
|
|||
// • active (#1D4ED8): 适用于激活状态下的颜色,例如按钮按下时的背景色或边框色。
|
|||
// • backgroundDark (#1E40AF): 适用于深色背景,可能用于主要按钮或深色卡片背景。
|
|||
// • backgroundDarker (#1E3A8A): 适用于更深的背景,通常用于头部导航栏或页脚。
|
|||
// • backgroundDarkest (#172554): 适用于最深的背景,可能用于非常深色的区域或极端对比色。
|
|||
|
|||
return { |
|||
50: `hsl(var(--${name}-50))`, |
|||
100: `hsl(var(--${name}-100))`, |
|||
200: `hsl(var(--${name}-200))`, |
|||
300: `hsl(var(--${name}-300))`, |
|||
400: `hsl(var(--${name}-400))`, |
|||
500: `hsl(var(--${name}-500))`, |
|||
600: `hsl(var(--${name}-600))`, |
|||
700: `hsl(var(--${name}-700))`, |
|||
// 800: `hsl(var(--${name}-800))`,
|
|||
// 900: `hsl(var(--${name}-900))`,
|
|||
// 950: `hsl(var(--${name}-950))`,
|
|||
// 激活状态下的颜色,适用于按钮按下时的背景色或边框色。
|
|||
active: `hsl(var(--${name}-700))`, |
|||
// 浅色背景,适用于输入框或表单区域的背景。
|
|||
'background-light': `hsl(var(--${name}-200))`, |
|||
// 适用于略浅的背景色,通常用于次要背景或略浅的区域。
|
|||
'background-lighter': `hsl(var(--${name}-100))`, |
|||
// 最浅的背景色,适用于非常轻微的阴影或卡片的背景。
|
|||
'background-lightest': `hsl(var(--${name}-50))`, |
|||
// 适用于普通边框,可能用于按钮或卡片的边框。
|
|||
border: `hsl(var(--${name}-400))`, |
|||
// 浅色边框,适用于输入框或卡片的边框。
|
|||
'border-light': `hsl(var(--${name}-300))`, |
|||
foreground: `hsl(var(--${name}-foreground))`, |
|||
// 鼠标悬停状态下的颜色,适用于按钮悬停时的背景色或边框色。
|
|||
hover: `hsl(var(--${name}-600))`, |
|||
// 主色文本
|
|||
text: `hsl(var(--${name}-500))`, |
|||
// 主色文本激活态
|
|||
'text-active': `hsl(var(--${name}-700))`, |
|||
// 主色文本悬浮态
|
|||
'text-hover': `hsl(var(--${name}-600))`, |
|||
}; |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
declare module '@tailwindcss/nesting' { |
|||
export default any; |
|||
} |
|||
@ -0,0 +1,53 @@ |
|||
import plugin from 'tailwindcss/plugin.js'; |
|||
|
|||
const enterAnimationPlugin = plugin(({ addUtilities }) => { |
|||
const maxChild = 5; |
|||
const utilities: Record<string, any> = {}; |
|||
for (let i = 1; i <= maxChild; i++) { |
|||
const baseDelay = 0.1; |
|||
const delay = `${baseDelay * i}s`; |
|||
|
|||
utilities[`.enter-x:nth-child(${i})`] = { |
|||
animation: `enter-x-animation 0.3s ease-in-out ${delay} forwards`, |
|||
opacity: '0', |
|||
transform: `translateX(50px)`, |
|||
}; |
|||
|
|||
utilities[`.enter-y:nth-child(${i})`] = { |
|||
animation: `enter-y-animation 0.3s ease-in-out ${delay} forwards`, |
|||
opacity: '0', |
|||
transform: `translateY(50px)`, |
|||
}; |
|||
|
|||
utilities[`.-enter-x:nth-child(${i})`] = { |
|||
animation: `enter-x-animation 0.3s ease-in-out ${delay} forwards`, |
|||
opacity: '0', |
|||
transform: `translateX(-50px)`, |
|||
}; |
|||
|
|||
utilities[`.-enter-y:nth-child(${i})`] = { |
|||
animation: `enter-y-animation 0.3s ease-in-out ${delay} forwards`, |
|||
opacity: '0', |
|||
transform: `translateY(-50px)`, |
|||
}; |
|||
} |
|||
|
|||
// 添加动画关键帧
|
|||
addUtilities(utilities); |
|||
addUtilities({ |
|||
'@keyframes enter-x-animation': { |
|||
to: { |
|||
opacity: '1', |
|||
transform: 'translateX(0)', |
|||
}, |
|||
}, |
|||
'@keyframes enter-y-animation': { |
|||
to: { |
|||
opacity: '1', |
|||
transform: 'translateY(0)', |
|||
}, |
|||
}, |
|||
}); |
|||
}); |
|||
|
|||
export { enterAnimationPlugin }; |
|||
@ -0,0 +1,15 @@ |
|||
import config from '.'; |
|||
|
|||
export default { |
|||
plugins: { |
|||
...(process.env.NODE_ENV === 'production' ? { cssnano: {} } : {}), |
|||
// Specifying the config is not necessary in most cases, but it is included
|
|||
autoprefixer: {}, |
|||
// 修复 element-plus 和 ant-design-vue 的样式和tailwindcss冲突问题
|
|||
'postcss-antd-fixes': { prefixes: ['ant', 'el'] }, |
|||
'postcss-import': {}, |
|||
'postcss-preset-env': {}, |
|||
tailwindcss: { config }, |
|||
'tailwindcss/nesting': {}, |
|||
}, |
|||
}; |
|||
@ -0,0 +1,6 @@ |
|||
{ |
|||
"$schema": "https://json.schemastore.org/tsconfig", |
|||
"extends": "@vben/tsconfig/node.json", |
|||
"include": ["src"], |
|||
"exclude": ["node_modules"] |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
{ |
|||
"$schema": "https://json.schemastore.org/tsconfig", |
|||
"display": "Base", |
|||
"compilerOptions": { |
|||
"composite": false, |
|||
"target": "ESNext", |
|||
|
|||
"moduleDetection": "force", |
|||
"experimentalDecorators": true, |
|||
|
|||
"baseUrl": ".", |
|||
"module": "ESNext", |
|||
|
|||
"moduleResolution": "node", |
|||
"resolveJsonModule": true, |
|||
|
|||
"strict": true, |
|||
"strictNullChecks": true, |
|||
"noFallthroughCasesInSwitch": true, |
|||
"noImplicitAny": true, |
|||
"noImplicitOverride": true, |
|||
"noImplicitThis": true, |
|||
"noUncheckedIndexedAccess": true, |
|||
"noUnusedLocals": true, |
|||
"noUnusedParameters": true, |
|||
|
|||
"inlineSources": false, |
|||
"noEmit": true, |
|||
"removeComments": true, |
|||
"sourceMap": false, |
|||
"allowSyntheticDefaultImports": true, |
|||
"esModuleInterop": true, |
|||
"forceConsistentCasingInFileNames": true, |
|||
"isolatedModules": true, |
|||
"verbatimModuleSyntax": true, |
|||
"skipLibCheck": true, |
|||
"preserveWatchOutput": true |
|||
}, |
|||
"exclude": ["**/node_modules/**", "**/dist/**", "**/.turbo/**"] |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
{ |
|||
"$schema": "https://json.schemastore.org/tsconfig", |
|||
"display": "Web Application", |
|||
"extends": "./base.json", |
|||
"compilerOptions": { |
|||
"jsx": "preserve", |
|||
"lib": ["ESNext", "DOM", "DOM.Iterable"], |
|||
"useDefineForClassFields": true, |
|||
"moduleResolution": "bundler", |
|||
"declaration": true, |
|||
"noEmit": false |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
{ |
|||
"$schema": "https://json.schemastore.org/tsconfig", |
|||
"display": "Node Config", |
|||
"extends": "./base.json", |
|||
"compilerOptions": { |
|||
"composite": false, |
|||
"lib": ["ESNext"], |
|||
"baseUrl": "./", |
|||
"moduleResolution": "bundler", |
|||
"types": ["node"], |
|||
"noImplicitAny": true |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
{ |
|||
"name": "@vben/tsconfig", |
|||
"version": "5.6.0", |
|||
"private": true, |
|||
"homepage": "https://github.com/vbenjs/vue-vben-admin", |
|||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git+https://github.com/vbenjs/vue-vben-admin.git", |
|||
"directory": "internal/tsconfig" |
|||
}, |
|||
"license": "MIT", |
|||
"type": "module", |
|||
"files": [ |
|||
"base.json", |
|||
"library.json", |
|||
"node.json", |
|||
"web-app.json", |
|||
"web.json" |
|||
], |
|||
"dependencies": { |
|||
"@vben/types": "workspace:*", |
|||
"vite": "catalog:" |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"$schema": "https://json.schemastore.org/tsconfig", |
|||
"display": "Web Application", |
|||
"extends": "./web.json", |
|||
"compilerOptions": { |
|||
"types": ["vite/client", "@vben/types/global"] |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
{ |
|||
"$schema": "https://json.schemastore.org/tsconfig", |
|||
"display": "Web Package", |
|||
"extends": "./base.json", |
|||
"compilerOptions": { |
|||
"jsx": "preserve", |
|||
"jsxImportSource": "vue", |
|||
"lib": ["ESNext", "DOM", "DOM.Iterable"], |
|||
"useDefineForClassFields": true, |
|||
"moduleResolution": "bundler", |
|||
"types": ["vite/client"], |
|||
"declaration": false |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
import { defineBuildConfig } from 'unbuild'; |
|||
|
|||
export default defineBuildConfig({ |
|||
clean: true, |
|||
declaration: true, |
|||
entries: ['src/index'], |
|||
}); |
|||
@ -0,0 +1,59 @@ |
|||
{ |
|||
"name": "@vben/vite-config", |
|||
"version": "5.6.0", |
|||
"private": true, |
|||
"homepage": "https://github.com/vbenjs/vue-vben-admin", |
|||
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues", |
|||
"repository": { |
|||
"type": "git", |
|||
"url": "git+https://github.com/vbenjs/vue-vben-admin.git", |
|||
"directory": "internal/vite-config" |
|||
}, |
|||
"license": "MIT", |
|||
"type": "module", |
|||
"scripts": { |
|||
"stub": "pnpm unbuild --stub" |
|||
}, |
|||
"files": [ |
|||
"dist" |
|||
], |
|||
"main": "./dist/index.mjs", |
|||
"module": "./dist/index.mjs", |
|||
"types": "./dist/index.d.ts", |
|||
"exports": { |
|||
".": { |
|||
"types": "./src/index.ts", |
|||
"default": "./dist/index.mjs" |
|||
} |
|||
}, |
|||
"dependencies": { |
|||
"@intlify/unplugin-vue-i18n": "catalog:", |
|||
"@jspm/generator": "catalog:", |
|||
"archiver": "catalog:", |
|||
"cheerio": "catalog:", |
|||
"get-port": "catalog:", |
|||
"html-minifier-terser": "catalog:", |
|||
"nitropack": "catalog:", |
|||
"resolve.exports": "catalog:", |
|||
"vite-plugin-pwa": "catalog:", |
|||
"vite-plugin-vue-devtools": "catalog:" |
|||
}, |
|||
"devDependencies": { |
|||
"@pnpm/workspace.read-manifest": "catalog:", |
|||
"@types/archiver": "catalog:", |
|||
"@types/html-minifier-terser": "catalog:", |
|||
"@vben/node-utils": "workspace:*", |
|||
"@vitejs/plugin-vue": "catalog:", |
|||
"@vitejs/plugin-vue-jsx": "catalog:", |
|||
"dayjs": "catalog:", |
|||
"dotenv": "catalog:", |
|||
"rollup": "catalog:", |
|||
"rollup-plugin-visualizer": "catalog:", |
|||
"sass": "catalog:", |
|||
"vite": "catalog:", |
|||
"vite-plugin-compression": "catalog:", |
|||
"vite-plugin-dts": "catalog:", |
|||
"vite-plugin-html": "catalog:", |
|||
"vite-plugin-lazy-import": "catalog:" |
|||
} |
|||
} |
|||
@ -0,0 +1,125 @@ |
|||
import type { CSSOptions, UserConfig } from 'vite'; |
|||
|
|||
import type { DefineApplicationOptions } from '../typing'; |
|||
|
|||
import path, { relative } from 'node:path'; |
|||
|
|||
import { findMonorepoRoot } from '@vben/node-utils'; |
|||
|
|||
import { NodePackageImporter } from 'sass'; |
|||
import { defineConfig, loadEnv, mergeConfig } from 'vite'; |
|||
|
|||
import { defaultImportmapOptions, getDefaultPwaOptions } from '../options'; |
|||
import { loadApplicationPlugins } from '../plugins'; |
|||
import { loadAndConvertEnv } from '../utils/env'; |
|||
import { getCommonConfig } from './common'; |
|||
|
|||
function defineApplicationConfig(userConfigPromise?: DefineApplicationOptions) { |
|||
return defineConfig(async (config) => { |
|||
const options = await userConfigPromise?.(config); |
|||
const { appTitle, base, port, ...envConfig } = await loadAndConvertEnv(); |
|||
const { command, mode } = config; |
|||
const { application = {}, vite = {} } = options || {}; |
|||
const root = process.cwd(); |
|||
const isBuild = command === 'build'; |
|||
const env = loadEnv(mode, root); |
|||
|
|||
const plugins = await loadApplicationPlugins({ |
|||
archiver: true, |
|||
archiverPluginOptions: {}, |
|||
compress: false, |
|||
compressTypes: ['brotli', 'gzip'], |
|||
devtools: true, |
|||
env, |
|||
extraAppConfig: true, |
|||
html: true, |
|||
i18n: true, |
|||
importmapOptions: defaultImportmapOptions, |
|||
injectAppLoading: true, |
|||
injectMetadata: true, |
|||
isBuild, |
|||
license: true, |
|||
mode, |
|||
nitroMock: !isBuild, |
|||
nitroMockOptions: {}, |
|||
print: !isBuild, |
|||
printInfoMap: { |
|||
'Vben Admin Docs': 'https://doc.vben.pro', |
|||
}, |
|||
pwa: true, |
|||
pwaOptions: getDefaultPwaOptions(appTitle), |
|||
vxeTableLazyImport: true, |
|||
...envConfig, |
|||
...application, |
|||
}); |
|||
|
|||
const { injectGlobalScss = true } = application; |
|||
|
|||
const applicationConfig: UserConfig = { |
|||
base, |
|||
build: { |
|||
rollupOptions: { |
|||
output: { |
|||
assetFileNames: '[ext]/[name]-[hash].[ext]', |
|||
chunkFileNames: 'js/[name]-[hash].js', |
|||
entryFileNames: 'jse/index-[name]-[hash].js', |
|||
}, |
|||
}, |
|||
target: 'es2015', |
|||
}, |
|||
css: createCssOptions(injectGlobalScss), |
|||
esbuild: { |
|||
drop: isBuild |
|||
? [ |
|||
// 'console',
|
|||
'debugger', |
|||
] |
|||
: [], |
|||
legalComments: 'none', |
|||
}, |
|||
plugins, |
|||
server: { |
|||
host: true, |
|||
port, |
|||
warmup: { |
|||
// 预热文件
|
|||
clientFiles: [ |
|||
'./index.html', |
|||
'./src/bootstrap.ts', |
|||
'./src/{views,layouts,router,store,api,adapter}/*', |
|||
], |
|||
}, |
|||
}, |
|||
}; |
|||
|
|||
const mergedCommonConfig = mergeConfig( |
|||
await getCommonConfig(), |
|||
applicationConfig, |
|||
); |
|||
return mergeConfig(mergedCommonConfig, vite); |
|||
}); |
|||
} |
|||
|
|||
function createCssOptions(injectGlobalScss = true): CSSOptions { |
|||
const root = findMonorepoRoot(); |
|||
return { |
|||
preprocessorOptions: injectGlobalScss |
|||
? { |
|||
scss: { |
|||
additionalData: (content: string, filepath: string) => { |
|||
const relativePath = relative(root, filepath); |
|||
// apps下的包注入全局样式
|
|||
if (relativePath.startsWith(`apps${path.sep}`)) { |
|||
return `@use "@vben/styles/global" as *;\n${content}`; |
|||
} |
|||
return content; |
|||
}, |
|||
// api: 'modern',
|
|||
importers: [new NodePackageImporter()], |
|||
}, |
|||
} |
|||
: {}, |
|||
}; |
|||
} |
|||
|
|||
export { defineApplicationConfig }; |
|||
@ -0,0 +1,13 @@ |
|||
import type { UserConfig } from 'vite'; |
|||
|
|||
async function getCommonConfig(): Promise<UserConfig> { |
|||
return { |
|||
build: { |
|||
chunkSizeWarningLimit: 2000, |
|||
reportCompressedSize: false, |
|||
sourcemap: false, |
|||
}, |
|||
}; |
|||
} |
|||
|
|||
export { getCommonConfig }; |
|||
@ -0,0 +1,37 @@ |
|||
import type { DefineConfig, VbenViteConfig } from '../typing'; |
|||
|
|||
import { existsSync } from 'node:fs'; |
|||
import { join } from 'node:path'; |
|||
|
|||
import { defineApplicationConfig } from './application'; |
|||
import { defineLibraryConfig } from './library'; |
|||
|
|||
export * from './application'; |
|||
export * from './library'; |
|||
|
|||
function defineConfig( |
|||
userConfigPromise?: DefineConfig, |
|||
type: 'application' | 'auto' | 'library' = 'auto', |
|||
): VbenViteConfig { |
|||
let projectType = type; |
|||
|
|||
// 根据包是否存在 index.html,自动判断类型
|
|||
if (projectType === 'auto') { |
|||
const htmlPath = join(process.cwd(), 'index.html'); |
|||
projectType = existsSync(htmlPath) ? 'application' : 'library'; |
|||
} |
|||
|
|||
switch (projectType) { |
|||
case 'application': { |
|||
return defineApplicationConfig(userConfigPromise); |
|||
} |
|||
case 'library': { |
|||
return defineLibraryConfig(userConfigPromise); |
|||
} |
|||
default: { |
|||
throw new Error(`Unsupported project type: ${projectType}`); |
|||
} |
|||
} |
|||
} |
|||
|
|||
export { defineConfig }; |
|||
@ -0,0 +1,59 @@ |
|||
import type { ConfigEnv, UserConfig } from 'vite'; |
|||
|
|||
import type { DefineLibraryOptions } from '../typing'; |
|||
|
|||
import { readPackageJSON } from '@vben/node-utils'; |
|||
|
|||
import { defineConfig, mergeConfig } from 'vite'; |
|||
|
|||
import { loadLibraryPlugins } from '../plugins'; |
|||
import { getCommonConfig } from './common'; |
|||
|
|||
function defineLibraryConfig(userConfigPromise?: DefineLibraryOptions) { |
|||
return defineConfig(async (config: ConfigEnv) => { |
|||
const options = await userConfigPromise?.(config); |
|||
const { command, mode } = config; |
|||
const { library = {}, vite = {} } = options || {}; |
|||
const root = process.cwd(); |
|||
const isBuild = command === 'build'; |
|||
|
|||
const plugins = await loadLibraryPlugins({ |
|||
dts: false, |
|||
injectMetadata: true, |
|||
isBuild, |
|||
mode, |
|||
...library, |
|||
}); |
|||
|
|||
const { dependencies = {}, peerDependencies = {} } = |
|||
await readPackageJSON(root); |
|||
|
|||
const externalPackages = [ |
|||
...Object.keys(dependencies), |
|||
...Object.keys(peerDependencies), |
|||
]; |
|||
|
|||
const packageConfig: UserConfig = { |
|||
build: { |
|||
lib: { |
|||
entry: 'src/index.ts', |
|||
fileName: () => 'index.mjs', |
|||
formats: ['es'], |
|||
}, |
|||
rollupOptions: { |
|||
external: (id) => { |
|||
return externalPackages.some( |
|||
(pkg) => id === pkg || id.startsWith(`${pkg}/`), |
|||
); |
|||
}, |
|||
}, |
|||
}, |
|||
plugins, |
|||
}; |
|||
const commonConfig = await getCommonConfig(); |
|||
const mergedConmonConfig = mergeConfig(commonConfig, packageConfig); |
|||
return mergeConfig(mergedConmonConfig, vite); |
|||
}); |
|||
} |
|||
|
|||
export { defineLibraryConfig }; |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue