├── .about
├── CONTRIBUTING.md
├── DESIGN.md
├── en-US
│ ├── CONTRIBUTING.md
│ ├── DESIGN.md
│ └── README.md
└── use-this-template.png
├── .editorconfig
├── .gitattributes
├── .gitignore
├── .idea
├── .gitignore
├── dprintProjectConfig.xml
├── dprintUserConfig.xml
├── inspectionProfiles
│ └── Project_Default.xml
├── jsLinters
│ └── eslint.xml
├── modules.xml
├── project.iml
└── vcs.xml
├── .node-version
├── .vscode
├── extensions.json
├── launch.json
└── settings.json
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── apis
├── package.json
└── src
│ ├── index.share.d.ts
│ ├── index.ts
│ └── userModel.ts
├── dprint.json
├── eslint.config.mjs
├── package.json
├── packages
└── utils
│ ├── package.json
│ ├── src
│ ├── bar.browser.ts
│ ├── bar.node.ts
│ ├── bar.ts
│ ├── index.ts
│ ├── readFile.browser.ts
│ └── readFile.node.ts
│ └── tests
│ ├── echoFooStr.ts
│ ├── index.spec.ts
│ ├── readFile.browser.spec.ts
│ └── readFile.node.spec.ts
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
├── scripts
├── echo-hi.ts
└── rename-project-and-reset-author.sh
├── tsconfig.json
├── tsconfigs
├── tsconfig.base.json
├── tsconfig.browser.json
├── tsconfig.browser.spec.json
├── tsconfig.default.json
├── tsconfig.default.spec.json
├── tsconfig.node.json
└── tsconfig.node.spec.json
├── vitest.config.ts
├── vitest.workspace.ts
└── website
├── index.html
├── package.json
├── src
├── index.share.d.ts
├── index.ts
└── main.ts
└── vite.config.ts
/.about/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # 如何参与贡献
2 |
3 | TODO...
4 |
--------------------------------------------------------------------------------
/.about/DESIGN.md:
--------------------------------------------------------------------------------
1 | # 设计思路
2 |
3 | ## 引
4 |
5 | [Monorepo 中基建最关键的部分是如何清晰简单的去定义相互依赖关系。](https://monorepo.tools/#what-is-a-monorepo)
6 |
7 | ## 面对的问题
8 |
9 | 开发环境往往是复杂且多样的,比如说:
10 |
11 | - 解耦了的部分需要或者可以单独发布的代码:核心、工具、统一定义等
12 | - 通过组合而形成的各种不同情况上层应用:前端 web 界面、后端服务、命令行工具等
13 | - 与工作空间存在一定依赖关系,为了发布同步和维护方便等目的放在一个仓库中进行维护:文档、脚本等
14 |
15 | 在很多的知名大型项目中他们都采取了 Monorepo 的方式进行管理,但是纵观如此多的项目,他们在一些开发体验上并没有做到极致。我们会面对各种各样的问题:
16 |
17 | - tsconfig 配置维护困难
18 | - 方案不够标准导致依赖外部插件
19 | - 全局的 alias 导致对内部幽灵依赖的检查失效
20 | - 源码跳转失效
21 | - 无法细化导出规则:屏蔽、子路径、禁用等
22 |
23 | 这些问题的根因都是因为我们没有一个统一的标准在这些不同的系统之间将他们的联系起来,而现在!我们有了。
24 |
25 | ## 可用的手段
26 |
27 | 那么在这个全新的时代我们有什么新手段可以解决我们在 Monorepo 开发过程中遇到的各式各样的问题呢?
28 |
29 | - [`exports`](https://nodejs.org/api/packages.html#exports)、[`imports`](https://nodejs.org/api/packages.html#imports)、[`conditions`](https://nodejs.org/api/packages.html#conditional-exports) 等导出特性的支持
30 | - `tsconfig` 的 [`references`](https://www.typescriptlang.org/docs/handbook/project-references.html) 提供了对不同类型文件的编译参数控制
31 | - `tsconfig` 的 [`compilerOptions.moduleResolution`](https://www.typescriptlang.org/tsconfig/moduleResolution.html) 支持了 [bundler](https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/#--moduleresolution-bundler)
32 | - `tsconfig` 的 [`customCondtions`](https://www.typescriptlang.org/tsconfig/#customConditions) 支持了条件导出,可以让用户根据自己的环境使用不同的导出策略
33 | - `vitest` 对于[工作空间](https://vitest.dev/guide/workspace)的支持
34 | - `yarn` 的 [Cross-references](https://yarnpkg.com/features/workspaces#cross-references)、`pnpm` 的 [Workspace protocol](https://pnpm.io/workspaces#workspace-protocol-workspace) 解决工作空间中的依赖管理问题
35 | - 基于 `rollup` 在工作空间的新型构建工具 [jiek](https://github.com/NWYLZW/jiek/blob/master/packages/jiek/README.md)
36 |
37 | ## 具体设计
38 |
39 | 首先从多个角度对我们的 Monorepo 进行规划:
40 |
41 | - 更准确更可靠更具备扩展性的类型
42 | - 按照文件类型对单元测试进行分类配置
43 | - 基于工作空间的依赖以及导出规则而自然而然的构建发布工具和方式
44 | - 基于 antfu 的 eslint 工具,你可以很简单的定义不同类型文件的校验规则
45 |
46 | ### 类型
47 |
48 | 首先我们对**类型体系**内的依赖模块解析按照我们的需要进行了更体系更具备扩展性的规划,以标准的方式来满足我们实际的开发需求,而不需要去使用非标的手段去完成我们的开发需要。
49 |
50 | 在这里我们先来看看我们是如何将我们代码归类的:
51 |
52 | - 运行在浏览器
53 |
54 | 对于这种情况,假设大部分用户正在使用 Bundler 工具:Webpack、Vite 等对自己的代码进行开发。
55 |
56 | - `.browser.ts` 结尾以及 website 目录下为浏览器环境
57 | - `.browser.spec.ts` 结尾的为模拟浏览器环境
58 | - 使用 `moduleResolution: bundler` 激活 bundler 场景下的导出策略
59 | - 添加 `browser` 的 conditional 用于激活特定的 export,针对于浏览器环境你还有需要的 conditional 可以自行添加
60 | - 添加 `dom` 的 lib 用于激活浏览器环境下的类型支持,如果你有其他的需求,可以自行添加
61 |
62 | - 运行在 Node.js
63 |
64 | Node.js 环境本项目使用了 `esbuild-register` 进行编译,所以并没有具体的 bundler,但是因为这里我们选择了 Vitest 作为测试工具,而 Vitest 恰恰基于 Vite,所以关于单元测试实际上是基于 bundler 的。
65 |
66 | 不过虽然我们的直接运行的 ts 并没有 bundler,但是实际上来说 Node.js 18 已经支持了 `exports` 的特性,所以我们可以通过 `exports` 来进行导出。
67 |
68 | - 配置、脚本文件,比如 `vitest.config.ts` 等。这些文件实际上的运行环境是 Node.js,所以这里我们也分类为该运行时
69 | - `.node.ts` 结尾以及 apis 目录下为 Node.js 环境
70 | - `.node.spec.ts` 结尾的为测试环境
71 | - 添加 `node` 的 conditional 用于激活特定的 export,针对于 Node.js 环境你还有需要的 conditional 可以自行添加
72 |
73 | - 俩者皆可运行
74 |
75 | - 有些代码可能会在浏览器和 Node.js 环境下都会运行,对于不满足上述规则的都可以归类于此。
76 | - 有些非运行时的代码,比如说我们项目中需要共用的类型信息,这部分可能在前端和后端都需要使用,但是并不需要存在相应的运行时约束。这个时候我们可以只共享相应的类型数据而不抽象单独的包或者说模块,这样可以拥有一个更轻量级的兼容层。
77 |
78 | 出于上述设计,我们就可以按照不同的文件命名规则来划分不同 tsconfig,决定不同的 `compilerOptions`,同时采用不同的条件导出配置使我们在对应文件时能 resolve 到不同的文件路径。
79 |
80 | ### 构建与发布
81 |
82 | 当我们在 Monorepo 下面进行工作的时候,一个很关键的点就是管理有什么需要构建,以及建立包之间的依赖关系。所以我们需要几个元数据:
83 |
84 | - 定义构建入口,甚至根据一些隐式条件自然而然的控制编译参数
85 | - 定义使用入口,直接与 `exports` 进行映射,开发阶段跳转定义的时候可以直接跳转到源码
86 | - 定义依赖关系,决定什么东西需要 bundle 到产物中,什么是外部依赖
87 | - 定义内部的路径重写,简化跨层级的路径引入
88 |
89 | 在这里我们充分利用了标准中的字段来进行了设计,在下面我以下面的例子简单进行说明:
90 | ```json
91 | {
92 | "name": "c",
93 | // 构建入口与使用入口实际上是同构的
94 | // 我们在开发阶段可以将源码直接设置为入口点,然后按照对应的规则在编译与发布的阶段转化到我们的产物模式
95 | "exports": {
96 | // 设置根入口
97 | ".": "./src/index.ts",
98 | "./foo": {
99 | // 当我们的 esm 和 CommonJS 的入口因为一些设计原因导致不一致时,我们可以使用 import 与 require 来进行区分
100 | // 比如说我们希望 CommonJS 被使用的时候不需要 `require('c').default`
101 | "import": "./src/foo.mts",
102 | "require": "./src/foo.ts"
103 | },
104 | // 支持 glob 匹配递归下的整个目录树
105 | "./bar/*": "./src/bar/*.ts",
106 | "./bor": {
107 | // 假设你正在写一个组件库,你喜欢用户可以可选的引入带样式,亦或是不带样式的产物
108 | // 你可以分流为俩个入口,让用户通过 conditional 来控制
109 | "styless": "./src/bor.styless.ts",
110 | "default": "./src/bor.ts"
111 | }
112 | },
113 | "imports": {
114 | // 类似于你在 `tsconfig.compilerOptions.paths` 中写 `"@/*": ["./src/*"]`
115 | "#/*": "./src/*",
116 | "#internal/*": "./src/internal/*"
117 | },
118 | // 本字段中声明的均不会打包到产物中而是作为外部依赖被引用
119 | "dependencies": {
120 | // 通过 workspace 协议定义的工作空间依赖
121 | // 可以使你不需要再在当前目录创建 tsconfig 定义 references 来重复定义依赖关系
122 | // 同时在发布时也会自动将内容替换为工作空间下对应
123 | "a": "workspace:^",
124 | "foo": "^0.1.0"
125 | },
126 | // 开发依赖如果在项目实际使用的过程中被引入了,由于相应的安装特性,内容会被打包到产物之中
127 | "devDependencies": {
128 | "b": "workspace:^",
129 | "bar": "^0.1.0"
130 | },
131 | // 与 devDependencies 一致
132 | "optionalDependecies": {}
133 | }
134 | ```
135 |
136 | 按照你的需求定义好如上的配置,如果没有特殊的需求,我们就不需要写任何相关的编译配置而可以直接通过相关的指令进行编译以及发布,极大地简化了配置文件的编写。
137 |
138 | ### 工具链
139 |
140 | - Tests: [Vitest](https://vitest.dev/)
141 |
142 | 配置文件位置 `vitest.workspace.ts` 和 `vitest.config.ts`。
143 |
144 | 通过使用 Vitest 的 workspace ,我们可以对测试进行类型的划分,而我们在上面的定义分类的 tsconfig 又很好的契合了这个用法,我们可以直接通过 tsconfig 而直接生成我们的配置。
145 |
146 | - Linter: [ESLint](https://eslint.org/)
147 |
148 | 这里使用 @antfu/eslint-config 作为默认配置,你可以使用 `pnpm dlx @antfu/eslint-config@latest` 调整为你需要的具体项目配置。
149 |
150 | 配置文件位置 `eslint.config.mjs`。
151 |
152 | - Formatter: [Dprint](https://dprint.dev/)
153 |
154 | 这里默认安装与配置了 typescript、json、markdown、toml、css 以及其他的 css 预编译语言的插件,如果有需要可以自行删除安装。
155 |
156 | 配置文件位置 `dprint.json`。
157 |
158 | ## Q&A
159 |
160 | - Q: 为什么不用 tsconfig paths?
161 | - A: 有多点:
162 | - 不够标准为主要原因,由此导致很多 bundler 工具并不默认支持,因此需要用户根据自己的 bundler 去安装相应的插件。
163 | - 在 monorepo 的环境下,如果使用 paths 且存在多份 tsconfig,那么你还需要告诉你的打包器应该用哪个 tsconfig,这样会导致你的打包器的配置变得复杂。
164 | - 没办法利用 conditional exports、imports。导致在部分较为常见场景处理起来不好用,比如无法使用一个路径,根据具体的文件选择不同内容导出。
165 | - 在 monorepo 环境下,如果 tsconfig 的配置复杂,每一个包可能都需要一个 tsconfig,或者有部分包需要一个特殊的 tsconfig,但是 paths 或者 rootdir 或者其他影响路径的配置,都会导致你的 paths 要在每一个这样的场景下复制一遍。
166 |
167 | - Q: 为什么将单元测试单独分开?
168 | - A: 类型污染,单元测试往往会依赖 @types/node 这间接导致你包括了单元测试文件的 tsconfig project 都会被 node 的类型污染,以及其他的类型污染。
169 |
170 | 参考资料:[Ambient Module Declaration](https://www.typescriptlang.org/docs/handbook/modules/reference.html#:~:text=Ambient%20modules.%20TypeScript%20supports%20a%20syntax%20in%20script)
171 |
172 | - Q: 为什么不弄多个 tsconfig 在每个包下面?
173 |
174 | - A: 会导致维护起来十分的困难,如果你有在大型 Monorepo 下面工作的经验,你很容易遇到以下一些情况:
175 | - 每个包下面反复去[配置相同](https://github.com/web-infra-dev/rspack/blob/0db8b9441a8bf9447ce11cc69292df773482cec8/packages/rspack-cli/tsconfig.json#L3-L9)的 tsconfig 编译参数
176 | - 哪怕你在 package.json 下面已经声明了当前包的工作空间内的依赖,你同样还是需要在包下面 tsconfig 中[引用对应 project 的目录](https://github.com/volarjs/volar.js/blob/bfa90aec50b975189f574b47affb619b9e1d679d/packages/language-server/tsconfig.json#L5-L8),才能获取到依赖正确的类型
177 |
178 | 当依赖关系变多变复杂的时候,你的每一个包都需要同时维护俩套依赖定义方式,这显然是不够优雅的。
179 |
180 | - Q: 为什么要有那么多的 tsconfig?
181 |
182 | - A: 已经很少了。对于一个现代化并完善的前端项目来说,我们必然有几个核心需求
183 | - 写 Bundler(Webpack, Rollup, Vite) 的配置文件
184 | - 写运行在浏览器的前端项目文件
185 | - 写不限制使用范围的文件
186 | - 写单元测试文件
187 |
188 | 这些并不单单是一个简单的依赖管理就能把所有的问题解决,我们同时还需要认知每一种文件都有自己特定的环境类型,以及文件的模块引入策略条件,乃至于编译选项的配置。所以我们至少需要 3 * 2 个不同的 tsconfig 来管理这些文件。
189 |
190 | ## 相关
191 |
192 | 一些朋友在看了本项目后推荐的一些相关资料(没想到也有和我有着类似思考方式的):
193 |
194 | - [tshy](https://github.com/isaacs/tshy)
195 | - [TypeScript Monorepo 的多种实践方式](https://github.com/colinhacks/live-typescript-monorepo)
196 | - [Esbuild 中的 project reference 实践方式](https://github.com/evanw/esbuild/issues/1250#issuecomment-1463826174)
197 |
198 | 参考资料:
199 |
200 | - [Monorepo tools](https://monorepo.tools/)
201 | - [Monorepo vs. polyrepo](https://github.com/joelparkerhenderson/monorepo-vs-polyrepo)
202 | - [Monorepo ≠ is different fromMonolith](https://blog.nrwl.io/misconceptions-about-monorepos-monorepo-monolith-df1250d4b03c)
203 | - [Node.js 中的条件导出](https://nodejs.org/api/packages.html#conditional-exports)
204 | - [TypeScript 中的模块解析策略](https://www.typescriptlang.org/docs/handbook/modules/reference.html#the-moduleresolution-compiler-option)
205 |
206 | ## 未来
207 |
208 | - 自动化体系的完善
209 | - 发包
210 | - 部署
211 | - 优化任务流
212 |
213 | 根据目标的依赖关系进行构建任务规划,从而避免整体构建的性能困境与手动规划任务困难的难点
214 | - 不再依赖任何的 PM 工具
215 |
--------------------------------------------------------------------------------
/.about/en-US/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to contribute
2 |
3 | TODO...
4 |
--------------------------------------------------------------------------------
/.about/en-US/DESIGN.md:
--------------------------------------------------------------------------------
1 | # 设计思路
2 |
3 | 出于社区环境对 `exports`、`conditions` 等新特性的支持,我们已经可以使用一套全新的方式去架构我们的 monorepo 项目。
4 |
5 | 基于以下几点:
6 |
7 | - 通过 `tsconfig.json` 的 `references` 来管理不同类型文件的类型相关规则
8 | - 针对于多样化包出口的需求,可采用 `exports` 配合支持的 condition 来实现
9 | - 同时对于不同的测试需求,这里也通过 tsconfig 中的相关约束进行配置生成
10 |
11 | 如此便能实现我们的全新的设计思路。
12 |
13 | ## 项目规范
14 |
15 | 本项目指在对**类型系统**进行规范借鉴,故在技术栈的选型上主要为示范性作用,很多工具链的配置改造成本较低,如果你需要进行自己的技术选型,建议开发过程中按照相应的规则进行调整。
16 |
17 | ### 项目结构
18 |
19 | 本项目侧重于类型系统如何在 monorepo 中进行管理,首先我们看到 `tsconfigs` 目录,我们从不同种类的文件进行划分:
20 |
21 | - 运行在浏览器
22 |
23 | 对于这种情况,假设大部分用户正在使用 Bundler 工具:Webpack、Vite 等对自己的代码进行开发。
24 |
25 | - `.browser.ts` 结尾以及 website 目录下为浏览器环境
26 | - `.browser.spec.ts` 结尾的为模拟浏览器环境
27 | - 使用 `moduleResolution: bundler` 激活 bundler 场景下的导出策略
28 | - 添加 `browser` 的 conditional 用于激活特定的 export,针对于浏览器环境你还有需要的 conditional 可以自行添加
29 | - 添加 `dom` 的 lib 用于激活浏览器环境下的类型支持,如果你有其他的需求,可以自行添加
30 |
31 | - 运行在 Node.js
32 |
33 | Node.js 环境本项目使用了 `esbuild-register` 进行编译,所以并没有具体的 bundler,但是因为这里我们选择了 Vitest 作为测试工具,而 Vitest 恰恰基于 Vite,所以关于单元测试实际上是基于 bundler 的。
34 |
35 | 不过虽然我们的直接运行的 ts 并没有 bundler,但是实际上来说 Node.js 18 已经支持了 `exports` 的特性,所以我们可以通过 `exports` 来进行导出。
36 |
37 | - 配置、脚本文件,比如 `vitest.config.ts` 等。这些文件实际上的运行环境是 Node.js,所以这里我们也分类为该运行时
38 | - `.node.ts` 结尾以及 apis 目录下为 Node.js 环境
39 | - `.node.spec.ts` 结尾的为测试环境
40 | - 添加 `node` 的 conditional 用于激活特定的 export,针对于 Node.js 环境你还有需要的 conditional 可以自行添加
41 |
42 | - 俩者皆可运行
43 |
44 | - 有些代码可能会在浏览器和 Node.js 环境下都会运行,对于不满足上述规则的都可以归类于此。
45 | - 有些非运行时的代码,比如说我们项目中需要共用的类型信息,这部分可能在前端和后端都需要使用,但是并不需要存在相应的运行时约束。这个时候我们可以只共享相应的类型数据而不抽象单独的包或者说模块,这样可以拥有一个更轻量级的兼容层。
46 |
47 | 出于上述考量,我们就可以按照不同的文件命名规则来划分不同 tsconfig,其次在包中导出依赖的时候根据导出文件的使用范围,合理采用不同的条件导出。
48 |
49 | ### 工具链
50 |
51 | - Linter: [ESLint](https://eslint.org/)
52 |
53 | 这里使用 @antfu/eslint-config 作为默认配置,你可以使用 `pnpm dlx @antfu/eslint-config@latest` 调整为你需要的具体项目配置。
54 |
55 | 配置文件位置 `eslint.config.mjs`。
56 |
57 | - Formatter: [Dprint](https://dprint.dev/)
58 |
59 | 这里默认安装与配置了 typescript、json、markdown、toml、css 以及其他的 css 预编译语言的插件,如果有需要可以自行删除安装。
60 |
61 | 配置文件位置 `dprint.json`。
62 |
63 | ## Q&A
64 |
65 | Q: 为什么不用 tsconfig paths?
66 |
67 | A: 有多点:
68 | - 不够标准为主要原因,由此导致很多 bundler 工具并不默认支持,因此需要用户根据自己的 bundler 去安装相应的插件。
69 | - 在 monorepo 的环境下,如果使用 paths 且存在多份 tsconfig,那么你还需要告诉你的打包器应该用哪个 tsconfig,这样会导致你的打包器的配置变得复杂。
70 | - 没办法利用 conditional exports、imports。导致在部分较为常见场景处理起来不好用,比如无法使用一个路径,根据具体的文件选择不同内容导出。
71 | - 在 monorepo 环境下,如果 tsconfig 的配置复杂,每一个包可能都需要一个 tsconfig,或者有部分包需要一个特殊的 tsconfig,但是 paths 或者 rootdir 或者其他影响路径的配置,都会导致你的 paths 要在每一个这样的场景下复制一遍。
72 |
73 | Q: 为什么将单元测试单独分开?
74 |
75 | A: 类型污染,单元测试往往会依赖 @types/node 这间接导致你包括了单元测试文件的 tsconfig project 都会被 node 的类型污染,以及其他的类型污染。
76 |
77 | 参考资料:[Ambient Module Declaration](https://www.typescriptlang.org/docs/handbook/modules/reference.html#:~:text=Ambient%20modules.%20TypeScript%20supports%20a%20syntax%20in%20script)
78 |
79 | Q: 为什么不弄多个 tsconfig 在每个包下面?
80 |
81 | A: 麻烦,你要写多个,然后不断的 extends,维护成本也很高。不是一种好的实践。
82 |
83 | Q: 为什么要有那么多的 tsconfig?
84 |
85 | A: 对于一个现代化并完善的前端项目来说,我们必然有几个核心需求
86 |
87 | - 写 Bundler(Webpack, Rollup, Vite) 的配置文件
88 | - 写运行在浏览器的前端项目文件
89 | - 写不限制使用范围的文件
90 | - 写单元测试文件
91 |
92 | 这些并不单单是一个简单的依赖管理就能把所有的问题解决,我们同时还需要认知每一种文件都有自己特定的环境类型,以及文件的模块引入策略条件,乃至于编译选项的配置。所以我们至少需要 3 * 2 个不同的 tsconfig 来管理这些文件。
93 |
94 | ## 相关
95 |
96 | 一些朋友在看了本项目后推荐的一些相关资料(没想到也有和我有着类似思考方式的):
97 |
98 | - [tshy](https://github.com/isaacs/tshy)
99 | - [TypeScript Monorepo 的多种实践方式](https://github.com/colinhacks/live-typescript-monorepo)
100 | - [Esbuild 中的 project reference 实践方式](https://github.com/evanw/esbuild/issues/1250#issuecomment-1463826174)
101 |
102 | 参考资料:
103 |
104 | - [Node.js 中的条件导出](https://nodejs.org/api/packages.html#conditional-exports)
105 | - [TypeScript 中的模块解析策略](https://www.typescriptlang.org/docs/handbook/modules/reference.html#the-moduleresolution-compiler-option)
106 |
--------------------------------------------------------------------------------
/.about/en-US/README.md:
--------------------------------------------------------------------------------
1 | # TypeScript Web Monorepo Template
2 |
3 | | en-US | [zh-Hans](../../README.md) |
4 |
5 | A template project for rapid development of web applications under a monorepo architecture.
6 |
7 | ## Learn Project
8 |
9 | - [Design](./DESIGN.md)
10 | - [How to contribute](./CONTRIBUTING.md)
11 | - [Code of conduct](../../CODE_OF_CONDUCT.md)
12 |
--------------------------------------------------------------------------------
/.about/use-this-template.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NWYLZW/ts-web-monorepo-template/74dde9c6b55cfc16cca426976b9bba9c4c0b502c/.about/use-this-template.png
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | insert_final_newline = true
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text eol=lf
2 |
3 | *.png -text
4 | *.jpg -text
5 | *.ico -text
6 | *.gif -text
7 | *.webp -text
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ### Node template
2 | # Logs
3 | logs
4 | *.log
5 | npm-debug.log*
6 | yarn-debug.log*
7 | yarn-error.log*
8 | lerna-debug.log*
9 | .pnpm-debug.log*
10 |
11 | # Diagnostic reports (https://nodejs.org/api/report.html)
12 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
13 |
14 | # Runtime data
15 | pids
16 | *.pid
17 | *.seed
18 | *.pid.lock
19 |
20 | # Directory for instrumented libs generated by jscoverage/JSCover
21 | lib-cov
22 |
23 | # Coverage directory used by tools like istanbul
24 | coverage
25 | *.lcov
26 |
27 | # nyc test coverage
28 | .nyc_output
29 |
30 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
31 | .grunt
32 |
33 | # Bower dependency directory (https://bower.io/)
34 | bower_components
35 |
36 | # node-waf configuration
37 | .lock-wscript
38 |
39 | # Compiled binary addons (https://nodejs.org/api/addons.html)
40 | build/Release
41 |
42 | # Dependency directories
43 | node_modules/
44 | jspm_packages/
45 |
46 | # Snowpack dependency directory (https://snowpack.dev/)
47 | web_modules/
48 |
49 | # TypeScript cache
50 | *.tsbuildinfo
51 |
52 | # Optional npm cache directory
53 | .npm
54 |
55 | # Optional eslint cache
56 | .eslintcache
57 |
58 | # Optional stylelint cache
59 | .stylelintcache
60 |
61 | # Microbundle cache
62 | .rpt2_cache/
63 | .rts2_cache_cjs/
64 | .rts2_cache_es/
65 | .rts2_cache_umd/
66 |
67 | # Optional REPL history
68 | .node_repl_history
69 |
70 | # Output of 'npm pack'
71 | *.tgz
72 |
73 | # Yarn Integrity file
74 | .yarn-integrity
75 |
76 | # dotenv environment variable files
77 | .env
78 | .env.development.local
79 | .env.test.local
80 | .env.production.local
81 | .env.local
82 |
83 | # parcel-bundler cache (https://parceljs.org/)
84 | .cache
85 | .parcel-cache
86 |
87 | # Next.js build output
88 | .next
89 | out
90 |
91 | # Nuxt.js build / generate output
92 | .nuxt
93 | dist
94 |
95 | # Gatsby files
96 | .cache/
97 | # Comment in the public line in if your project uses Gatsby and not Next.js
98 | # https://nextjs.org/blog/next-9-1#public-directory-support
99 | # public
100 |
101 | # vuepress build output
102 | .vuepress/dist
103 |
104 | # vuepress v2.x temp and cache directory
105 | .temp
106 | .cache
107 |
108 | # Docusaurus cache and generated files
109 | .docusaurus
110 |
111 | # Serverless directories
112 | .serverless/
113 |
114 | # FuseBox cache
115 | .fusebox/
116 |
117 | # DynamoDB Local files
118 | .dynamodb/
119 |
120 | # TernJS port file
121 | .tern-port
122 |
123 | # Stores VSCode versions used for testing VSCode extensions
124 | .vscode-test
125 |
126 | # yarn v2
127 | .yarn/cache
128 | .yarn/unplugged
129 | .yarn/build-state.yml
130 | .yarn/install-state.gz
131 | .pnp.*
132 |
133 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 |
--------------------------------------------------------------------------------
/.idea/dprintProjectConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/dprintUserConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/jsLinters/eslint.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/project.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.node-version:
--------------------------------------------------------------------------------
1 | v22.11.0
2 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "gplane.dprint2",
4 | "dprint.dprint"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": "Launch website progress",
9 | "type": "node",
10 | "request": "launch",
11 | "runtimeExecutable": "pnpm",
12 | "runtimeArgs": ["--filter", "website", "start"],
13 | "skipFiles": [
14 | "/**"
15 | ]
16 | }
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "typescript.tsdk": "node_modules/typescript/lib",
3 |
4 | // Disable the default formatter, use eslint instead
5 | "prettier.enable": false,
6 | "editor.formatOnSave": false,
7 |
8 | // Auto fix
9 | "editor.codeActionsOnSave": {
10 | "source.fixAll.eslint": "explicit",
11 | "source.organizeImports": "never"
12 | },
13 |
14 | "eslint.options": {
15 | "flags": ["unstable_ts_config"]
16 | },
17 |
18 | "eslint.runtime": "node",
19 |
20 | // Silent the stylistic rules in you IDE, but still auto fix them
21 | "eslint.rules.customizations": [
22 | { "rule": "style/*", "severity": "off", "fixable": true },
23 | { "rule": "format/*", "severity": "off", "fixable": true },
24 | { "rule": "*-indent", "severity": "off", "fixable": true },
25 | { "rule": "*-spacing", "severity": "off", "fixable": true },
26 | { "rule": "*-spaces", "severity": "off", "fixable": true },
27 | { "rule": "*-order", "severity": "off", "fixable": true },
28 | { "rule": "*-dangle", "severity": "off", "fixable": true },
29 | { "rule": "*-newline", "severity": "off", "fixable": true },
30 | { "rule": "*quotes", "severity": "off", "fixable": true },
31 | { "rule": "*semi", "severity": "off", "fixable": true }
32 | ],
33 |
34 | // Enable eslint for all supported languages
35 | "eslint.validate": [
36 | "javascript",
37 | "javascriptreact",
38 | "typescript",
39 | "typescriptreact",
40 | "vue",
41 | "html",
42 | "markdown",
43 | "json",
44 | "json5",
45 | "jsonc",
46 | "yaml",
47 | "toml",
48 | "xml",
49 | "gql",
50 | "graphql",
51 | "astro",
52 | "css",
53 | "less",
54 | "scss",
55 | "pcss",
56 | "postcss"
57 | ],
58 | "editor.defaultFormatter": "gplane.dprint2",
59 |
60 | "search.exclude": {
61 | "**/*.snap": true,
62 | "**/*.svg": true,
63 | "**/.git": true,
64 | "**/.github": false,
65 | "**/.nuxt": true,
66 | "**/.output": true,
67 | "**/.pnpm": true,
68 | "**/.vscode": true,
69 | "**/.yarn": true,
70 | "**/assets": true,
71 | "**/bower_components": true,
72 | "**/dist/**": true,
73 | "**/logs": true,
74 | "**/node_modules": true,
75 | "**/out/**": true,
76 | "**/package-lock.json": true,
77 | "**/pnpm-lock.yaml": true,
78 | "**/public": true,
79 | "**/temp": true,
80 | "**/yarn.lock": true,
81 | "**/CHANGELOG*": true,
82 | "**/LICENSE*": true
83 | },
84 |
85 | // ========== File Nesting ==========
86 | // this might not be up to date with the repo, please check yourself
87 | // https://github.com/antfu/vscode-file-nesting-config
88 | "explorer.fileNesting.enabled": true,
89 | "explorer.fileNesting.expand": false,
90 | "explorer.fileNesting.patterns": {
91 | "*.asax": "$(capture).*.cs, $(capture).*.vb",
92 | "*.ascx": "$(capture).*.cs, $(capture).*.vb",
93 | "*.ashx": "$(capture).*.cs, $(capture).*.vb",
94 | "*.aspx": "$(capture).*.cs, $(capture).*.vb",
95 | "*.bloc.dart": "$(capture).event.dart, $(capture).state.dart",
96 | "*.c": "$(capture).h",
97 | "*.cc": "$(capture).hpp, $(capture).h, $(capture).hxx",
98 | "*.cjs": "$(capture).cjs.map, $(capture).*.cjs, $(capture)_*.cjs",
99 | "*.component.ts": "$(capture).component.html, $(capture).component.spec.ts, $(capture).component.css, $(capture).component.scss, $(capture).component.sass, $(capture).component.less",
100 | "*.cpp": "$(capture).hpp, $(capture).h, $(capture).hxx",
101 | "*.cs": "$(capture).*.cs",
102 | "*.cshtml": "$(capture).cshtml.cs",
103 | "*.csproj": "*.config, *proj.user, appsettings.*, bundleconfig.json",
104 | "*.css": "$(capture).css.map, $(capture).*.css",
105 | "*.cxx": "$(capture).hpp, $(capture).h, $(capture).hxx",
106 | "*.dart": "$(capture).freezed.dart, $(capture).g.dart",
107 | "*.ex": "$(capture).html.eex, $(capture).html.heex, $(capture).html.leex",
108 | "*.go": "$(capture)_test.go",
109 | "*.java": "$(capture).class",
110 | "*.js": "$(capture).js.map, $(capture).*.js, $(capture)_*.js",
111 | "*.jsx": "$(capture).js, $(capture).*.jsx, $(capture)_*.js, $(capture)_*.jsx",
112 | "*.master": "$(capture).*.cs, $(capture).*.vb",
113 | "*.mjs": "$(capture).mjs.map, $(capture).*.mjs, $(capture)_*.mjs",
114 | "*.module.ts": "$(capture).resolver.ts, $(capture).controller.ts, $(capture).service.ts",
115 | "*.pubxml": "$(capture).pubxml.user",
116 | "*.resx": "$(capture).*.resx, $(capture).designer.cs, $(capture).designer.vb",
117 | "*.tex": "$(capture).acn, $(capture).acr, $(capture).alg, $(capture).aux, $(capture).bbl, $(capture).blg, $(capture).fdb_latexmk, $(capture).fls, $(capture).glg, $(capture).glo, $(capture).gls, $(capture).idx, $(capture).ind, $(capture).ist, $(capture).lof, $(capture).log, $(capture).lot, $(capture).out, $(capture).pdf, $(capture).synctex.gz, $(capture).toc, $(capture).xdv",
118 | "*.ts": "$(capture).js, $(capture).d.ts.map, $(capture).*.ts, $(capture)_*.js, $(capture)_*.ts",
119 | "*.tsx": "$(capture).ts, $(capture).*.tsx, $(capture)_*.ts, $(capture)_*.tsx",
120 | "*.vbproj": "*.config, *proj.user, appsettings.*, bundleconfig.json",
121 | "*.vue": "$(capture).*.ts, $(capture).*.js, $(capture).story.vue",
122 | "*.xaml": "$(capture).xaml.cs",
123 | "+layout.svelte": "+layout.ts,+layout.ts,+layout.js,+layout.server.ts,+layout.server.js,+layout.gql",
124 | "+page.svelte": "+page.server.ts,+page.server.js,+page.ts,+page.js,+page.gql",
125 | ".clang-tidy": ".clang-format, .clangd, compile_commands.json",
126 | ".env": "*.env, .env.*, .envrc, env.d.ts",
127 | ".gitignore": ".gitattributes, .gitmodules, .gitmessage, .mailmap, .git-blame*",
128 | ".project": ".classpath",
129 | "BUILD.bazel": "*.bzl, *.bazel, *.bazelrc, bazel.rc, .bazelignore, .bazelproject, WORKSPACE",
130 | "CMakeLists.txt": "*.cmake, *.cmake.in, .cmake-format.yaml, CMakePresets.json",
131 | "I*.cs": "$(capture).cs",
132 | "artisan": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, server.php, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, webpack.mix.js, windi.config.*",
133 | "astro.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*",
134 | "cargo.toml": ".clippy.toml, .rustfmt.toml, cargo.lock, clippy.toml, cross.toml, rust-toolchain.toml, rustfmt.toml",
135 | "composer.json": ".php*.cache, composer.lock, phpunit.xml*, psalm*.xml",
136 | "default.nix": "shell.nix",
137 | "deno.json*": "*.env, .env.*, .envrc, api-extractor.json, deno.lock, env.d.ts, import-map.json, import_map.json, jsconfig.*, tsconfig.*, tsdoc.*",
138 | "dockerfile": ".dockerignore, docker-compose.*, dockerfile*",
139 | "flake.nix": "flake.lock",
140 | "gatsby-config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, gatsby-browser.*, gatsby-node.*, gatsby-ssr.*, gatsby-transformer.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*",
141 | "gemfile": ".ruby-version, gemfile.lock",
142 | "go.mod": ".air*, go.sum",
143 | "go.work": "go.work.sum",
144 | "mix.exs": ".credo.exs, .dialyzer_ignore.exs, .formatter.exs, .iex.exs, .tool-versions, mix.lock",
145 | "next.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, next-env.d.ts, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*",
146 | "nuxt.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*",
147 | "package.json": ".browserslist*, .circleci*, .commitlint*, .cz-config.js, .czrc, .dlint.json, .dprint.json, .editorconfig, .eslint*, .firebase*, .flowconfig, .github*, .gitlab*, .gitpod*, .huskyrc*, .jslint*, .lintstagedrc*, .markdownlint*, .node-version, .nodemon*, .npm*, .nvmrc, .pm2*, .pnp.*, .pnpm*, .prettier*, .releaserc*, .sentry*, .simple-git-hooks*, .stackblitz*, .styleci*, .stylelint*, .tazerc*, .textlint*, .tool-versions, .travis*, .versionrc*, .vscode*, .watchman*, .xo-config*, .yamllint*, .yarnrc*, Procfile, apollo.config.*, appveyor*, azure-pipelines*, bower.json, build.config.*, commitlint*, crowdin*, dangerfile*, dlint.json, dprint.json, eslint*, firebase.json, grunt*, gulp*, jenkins*, lerna*, lint-staged*, nest-cli.*, netlify*, nodemon*, npm-shrinkwrap.json, nx.*, package-lock.json, package.nls*.json, phpcs.xml, pm2.*, pnpm*, prettier*, pullapprove*, pyrightconfig.json, release-tasks.sh, release.config.*, renovate*, rollup.config.*, rspack*, simple-git-hooks*, stylelint*, tslint*, tsup.config.*, turbo*, typedoc*, unlighthouse*, vercel*, vetur.config.*, webpack*, workspace.json, xo.config.*, yarn*",
148 | "pubspec.yaml": ".metadata, .packages, all_lint_rules.yaml, analysis_options.yaml, build.yaml, pubspec.lock, pubspec_overrides.yaml",
149 | "pyproject.toml": ".pdm.toml, pdm.lock, pyproject.toml",
150 | "quasar.conf.js": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, quasar.extensions.json, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*",
151 | "readme*": "authors, backers*, changelog*, citation*, code_of_conduct*, codeowners, contributing*, contributors, copying, credits, governance.md, history.md, license*, maintainers, readme*, security.md, sponsors*",
152 | "remix.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, remix.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*",
153 | "rush.json": ".browserslist*, .circleci*, .commitlint*, .cz-config.js, .czrc, .dlint.json, .dprint.json, .editorconfig, .eslint*, .firebase*, .flowconfig, .github*, .gitlab*, .gitpod*, .huskyrc*, .jslint*, .lintstagedrc*, .markdownlint*, .node-version, .nodemon*, .npm*, .nvmrc, .pm2*, .pnp.*, .pnpm*, .prettier*, .releaserc*, .sentry*, .simple-git-hooks*, .stackblitz*, .styleci*, .stylelint*, .tazerc*, .textlint*, .tool-versions, .travis*, .versionrc*, .vscode*, .watchman*, .xo-config*, .yamllint*, .yarnrc*, Procfile, apollo.config.*, appveyor*, azure-pipelines*, bower.json, build.config.*, commitlint*, crowdin*, dangerfile*, dlint.json, dprint.json, eslint*, firebase.json, grunt*, gulp*, jenkins*, lerna*, lint-staged*, nest-cli.*, netlify*, nodemon*, npm-shrinkwrap.json, nx.*, package-lock.json, package.nls*.json, phpcs.xml, pm2.*, pnpm*, prettier*, pullapprove*, pyrightconfig.json, release-tasks.sh, release.config.*, renovate*, rollup.config.*, rspack*, simple-git-hooks*, stylelint*, tslint*, tsup.config.*, turbo*, typedoc*, unlighthouse*, vercel*, vetur.config.*, webpack*, workspace.json, xo.config.*, yarn*",
154 | "shims.d.ts": "*.d.ts",
155 | "svelte.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, houdini.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, mdsvex.config.js, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vite.config.*, vitest.config.*, webpack.config.*, windi.config.*",
156 | "vite.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*",
157 | "vue.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*"
158 | }
159 | }
160 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our
6 | community a harassment-free experience for everyone, regardless of age, body
7 | size, visible or invisible disability, ethnicity, sex characteristics, gender
8 | identity and expression, level of experience, education, socio-economic status,
9 | nationality, personal appearance, race, religion, or sexual identity
10 | and orientation.
11 |
12 | We pledge to act and interact in ways that contribute to an open, welcoming,
13 | diverse, inclusive, and healthy community.
14 |
15 | ## Our Standards
16 |
17 | Examples of behavior that contributes to a positive environment for our
18 | community include:
19 |
20 | - Demonstrating empathy and kindness toward other people
21 | - Being respectful of differing opinions, viewpoints, and experiences
22 | - Giving and gracefully accepting constructive feedback
23 | - Accepting responsibility and apologizing to those affected by our mistakes,
24 | and learning from the experience
25 | - Focusing on what is best not just for us as individuals, but for the
26 | overall community
27 |
28 | Examples of unacceptable behavior include:
29 |
30 | - The use of sexualized language or imagery, and sexual attention or
31 | advances of any kind
32 | - Trolling, insulting or derogatory comments, and personal or political attacks
33 | - Public or private harassment
34 | - Publishing others' private information, such as a physical or email
35 | address, without their explicit permission
36 | - Other conduct which could reasonably be considered inappropriate in a
37 | professional setting
38 |
39 | ## Enforcement Responsibilities
40 |
41 | Community leaders are responsible for clarifying and enforcing our standards of
42 | acceptable behavior and will take appropriate and fair corrective action in
43 | response to any behavior that they deem inappropriate, threatening, offensive,
44 | or harmful.
45 |
46 | Community leaders have the right and responsibility to remove, edit, or reject
47 | comments, commits, code, wiki edits, issues, and other contributions that are
48 | not aligned to this Code of Conduct, and will communicate reasons for moderation
49 | decisions when appropriate.
50 |
51 | ## Scope
52 |
53 | This Code of Conduct applies within all community spaces, and also applies when
54 | an individual is officially representing the community in public spaces.
55 | Examples of representing our community include using an official e-mail address,
56 | posting via an official social media account, or acting as an appointed
57 | representative at an online or offline event.
58 |
59 | ## Enforcement
60 |
61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 | reported to the community leaders responsible for enforcement at
63 | .
64 | All complaints will be reviewed and investigated promptly and fairly.
65 |
66 | All community leaders are obligated to respect the privacy and security of the
67 | reporter of any incident.
68 |
69 | ## Enforcement Guidelines
70 |
71 | Community leaders will follow these Community Impact Guidelines in determining
72 | the consequences for any action they deem in violation of this Code of Conduct:
73 |
74 | ### 1. Correction
75 |
76 | **Community Impact**: Use of inappropriate language or other behavior deemed
77 | unprofessional or unwelcome in the community.
78 |
79 | **Consequence**: A private, written warning from community leaders, providing
80 | clarity around the nature of the violation and an explanation of why the
81 | behavior was inappropriate. A public apology may be requested.
82 |
83 | ### 2. Warning
84 |
85 | **Community Impact**: A violation through a single incident or series
86 | of actions.
87 |
88 | **Consequence**: A warning with consequences for continued behavior. No
89 | interaction with the people involved, including unsolicited interaction with
90 | those enforcing the Code of Conduct, for a specified period of time. This
91 | includes avoiding interactions in community spaces as well as external channels
92 | like social media. Violating these terms may lead to a temporary or
93 | permanent ban.
94 |
95 | ### 3. Temporary Ban
96 |
97 | **Community Impact**: A serious violation of community standards, including
98 | sustained inappropriate behavior.
99 |
100 | **Consequence**: A temporary ban from any sort of interaction or public
101 | communication with the community for a specified period of time. No public or
102 | private interaction with the people involved, including unsolicited interaction
103 | with those enforcing the Code of Conduct, is allowed during this period.
104 | Violating these terms may lead to a permanent ban.
105 |
106 | ### 4. Permanent Ban
107 |
108 | **Community Impact**: Demonstrating a pattern of violation of community
109 | standards, including sustained inappropriate behavior, harassment of an
110 | individual, or aggression toward or disparagement of classes of individuals.
111 |
112 | **Consequence**: A permanent ban from any sort of public interaction within
113 | the community.
114 |
115 | ## Attribution
116 |
117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118 | version 2.0, available at
119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
120 |
121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct
122 | enforcement ladder](https://github.com/mozilla/diversity).
123 |
124 | [homepage]: https://www.contributor-covenant.org
125 |
126 | For answers to common questions about this code of conduct, see the FAQ at
127 | https://www.contributor-covenant.org/faq. Translations are available at
128 | https://www.contributor-covenant.org/translations.
129 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024-present YiJie
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TypeScript Web Monorepo Template
2 |
3 | | zh-Hans | [en-US](.about/en-US/README.md) |
4 |
5 | 用于在 monorepo 架构下最现代最前沿的快速开发 web 应用的模版项目。
6 |
7 | ## 为什么用我
8 |
9 | - 轻量:未引入框架,只有最基础的工具链,可以灵活决定项目技术栈
10 | - 安全:类型系统的设计更加准确,带来的是完善的检查机制
11 | - 丰富:整理了常见的场景的最佳实践,可以很方便的根据已有内容快速扩张迭代
12 | - 现代:使用支持**最规范**也是**最前沿**的标准来决定项目的组织方式
13 | - 易用:提供了初始化的脚本,可以快速的为项目配置你的元信息,无需手动一个个处理
14 | - 高效:一般的 monorepo 的跨包跳转只能跳转到编译后的内容,本项目可以直接跳转到源码,极大地提高了开发效率
15 |
16 | ## 怎么用我
17 |
18 | ### 初始化
19 |
20 | 1. 点击右上角的 `Use this template` 按钮
21 | 
22 | 2. 根据提示填写你的项目信息
23 | 3. 克隆你的项目到本地
24 | 4. 运行 `./scripts/rename-project-and-reset-author.sh` 脚本,根据提示填写你的项目信息
25 | 5. 运行 `pnpm install` 安装依赖
26 | 6. 运行 `pnpm --filter website start` 启动开发服务器
27 |
28 | ### 同步
29 |
30 | TODO...
31 |
32 | ## 了解本项目
33 |
34 | - [设计](.about/DESIGN.md)
35 | - [如何参与贡献](.about/CONTRIBUTING.md)
36 | - [行为守则](./CODE_OF_CONDUCT.md)
37 |
--------------------------------------------------------------------------------
/apis/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "apis",
3 | "version": "0.1.0",
4 | "author": {
5 | "name": "YiJie"
6 | },
7 | "scripts": {
8 | "start": "node -r esbuild-register src/index.ts"
9 | },
10 | "dependencies": {
11 | "@mono/utils": "workspace:*"
12 | },
13 | "devDependencies": {
14 | "esbuild-register": "^3.6.0"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/apis/src/index.share.d.ts:
--------------------------------------------------------------------------------
1 | import type { User as U0 } from './userModel'
2 |
3 | declare module '@mono/share' {
4 | export type User = U0
5 | export type Strings = 'abc' | 'def'
6 | }
7 |
--------------------------------------------------------------------------------
/apis/src/index.ts:
--------------------------------------------------------------------------------
1 | import { name } from '@mono/utils/readFile'
2 | // ^?
3 | import type { Numbers, Strings } from '@mono/share'
4 |
5 | // eslint-disable-next-line no-console
6 | console.log(name)
7 | // eslint-disable-next-line no-console
8 | console.log('Hello, World!')
9 |
10 | const num: Numbers = 123
11 | // eslint-disable-next-line no-console
12 | console.log(num)
13 | const str: Strings = 'abc'
14 | // eslint-disable-next-line no-console
15 | console.log(str)
16 |
--------------------------------------------------------------------------------
/apis/src/userModel.ts:
--------------------------------------------------------------------------------
1 | export interface User {
2 | name: string
3 | }
4 |
--------------------------------------------------------------------------------
/dprint.json:
--------------------------------------------------------------------------------
1 | {
2 | "typescript": {
3 | "quoteStyle": "preferSingle",
4 | "semiColons": "asi",
5 | "trailingCommas": "never",
6 | "conditionalType.operatorPosition": "nextLine",
7 | "jsx.multiLineParens": "never",
8 | "typeParameters.trailingCommas": "onlyMultiLine",
9 | "module.sortImportDeclarations": "caseSensitive",
10 | "module.sortExportDeclarations": "caseSensitive",
11 | "exportDeclaration.sortNamedExports": "caseSensitive",
12 | "importDeclaration.sortNamedImports": "caseSensitive",
13 | "importDeclaration.sortTypeOnlyImports": "first",
14 | "exportDeclaration.sortTypeOnlyExports": "first"
15 | },
16 | "malva": {
17 | "ignoreCommentDirective": "dprint-ignore",
18 | "quotes": "preferSingle",
19 | "omitNumberLeadingZero": true
20 | },
21 | "json": {
22 | },
23 | "markdown": {
24 | },
25 | "toml": {
26 | },
27 | "excludes": [
28 | "**/node_modules",
29 | "**/*-lock.json"
30 | ],
31 | "plugins": [
32 | "https://plugins.dprint.dev/typescript-0.93.2.wasm",
33 | "https://plugins.dprint.dev/json-0.19.2.wasm",
34 | "https://plugins.dprint.dev/markdown-0.16.4.wasm",
35 | "https://plugins.dprint.dev/toml-0.6.1.wasm",
36 | "https://plugins.dprint.dev/g-plane/malva-v0.4.0.wasm",
37 | "https://plugins.dprint.dev/g-plane/markup_fmt-v0.15.1.wasm"
38 | ]
39 | }
40 |
--------------------------------------------------------------------------------
/eslint.config.mjs:
--------------------------------------------------------------------------------
1 | import config from '@antfu/eslint-config'
2 |
3 | export default config(
4 | {
5 | stylistic: false,
6 | typescript: {
7 | tsconfigPath: './tsconfig.json',
8 | overrides: {
9 | 'ts/no-namespace': 'off',
10 | 'ts/no-empty-object-type': 'off',
11 | 'ts/method-signature-style': 'off',
12 | 'ts/no-use-before-define': 'off',
13 | 'ts/ban-ts-comment': 'off',
14 | 'ts/no-wrapper-object-types': 'off',
15 | 'ts/no-unsafe-function-type': 'off',
16 | 'ts/strict-boolean-expressions': 'off',
17 |
18 | 'import/no-mutable-exports': 'off',
19 | 'perfectionist/sort-imports': 'off',
20 | 'perfectionist/sort-named-imports': 'off'
21 | }
22 | }
23 | },
24 | // test, script and config files
25 | {
26 | files: [
27 | 'packages/*/tests/**/*.{js,ts,tsx}',
28 | 'vitest.config.ts',
29 | 'eslint.config.mjs',
30 | 'vitest.workspace.ts',
31 | 'website/vite.config.ts',
32 | 'scripts/**/*.{js,ts}'
33 | ],
34 | rules: {
35 | 'no-console': 'off'
36 | }
37 | }
38 | )
39 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ts-web-monorepo-template",
3 | "type": "module",
4 | "version": "1.0.0",
5 | "private": true,
6 | "packageManager": "pnpm@9.10.0",
7 | "author": {
8 | "name": "YiJie"
9 | },
10 | "engines": {
11 | "node": ">=18.0.0",
12 | "npm": ">=999.999.999",
13 | "pnpm": ">=9.0.0",
14 | "yarn": ">=999.999.999"
15 | },
16 | "scripts": {
17 | "postinstall": "dprint editor-info",
18 | "rename-project-and-reset-author": "./scripts/rename-project-and-reset-author.sh",
19 | "echo-hi": "node -r esbuild-register ./scripts/echo-hi.ts"
20 | },
21 | "devDependencies": {
22 | "@antfu/eslint-config": "^3.9.2",
23 | "@types/node": "^18.19.45",
24 | "dprint": "^0.47.2",
25 | "esbuild-register": "^3.6.0",
26 | "eslint": "^9.10.0",
27 | "jiek": "^2.2.6",
28 | "rollup-plugin-esbuild": "^6.1.1",
29 | "typescript": "^5.7.2",
30 | "vitest": "^2.0.5"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/packages/utils/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@mono/utils",
3 | "version": "0.1.0",
4 | "author": {
5 | "name": "YiJie"
6 | },
7 | "exports": {
8 | "./package.json": "./package.json",
9 | ".": "./src/index.ts",
10 | "./bar": {
11 | "import": "./src/bar.browser.ts",
12 | "require": "./src/bar.node.ts",
13 | "default": "./src/bar.ts"
14 | },
15 | "./readFile": {
16 | "node": "./src/readFile.node.ts",
17 | "browser": "./src/readFile.browser.ts"
18 | }
19 | },
20 | "files": ["LICENSE", "README.md", "dist", "src"],
21 | "scripts": {
22 | "prepublish": "jb -nm && jk",
23 | "postpublish": "jk"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/packages/utils/src/bar.browser.ts:
--------------------------------------------------------------------------------
1 | export * from './bar'
2 |
--------------------------------------------------------------------------------
/packages/utils/src/bar.node.ts:
--------------------------------------------------------------------------------
1 | export * from './bar'
2 |
--------------------------------------------------------------------------------
/packages/utils/src/bar.ts:
--------------------------------------------------------------------------------
1 | export function bar() {
2 | return 'bar'
3 | }
4 |
--------------------------------------------------------------------------------
/packages/utils/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from '@mono/utils/bar'
2 | export function foo() {
3 | return 'foo'
4 | }
5 |
--------------------------------------------------------------------------------
/packages/utils/src/readFile.browser.ts:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line ts/no-unnecessary-type-assertion
2 | export const name = 'readFile.browser' as const
3 |
--------------------------------------------------------------------------------
/packages/utils/src/readFile.node.ts:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line ts/no-unnecessary-type-assertion
2 | export const name = 'readFile.node' as const
3 |
--------------------------------------------------------------------------------
/packages/utils/tests/echoFooStr.ts:
--------------------------------------------------------------------------------
1 | export function echoFooStr() {
2 | // eslint-disable-next-line no-console
3 | console.log('foo')
4 | }
5 |
--------------------------------------------------------------------------------
/packages/utils/tests/index.spec.ts:
--------------------------------------------------------------------------------
1 | import { foo } from '@mono/utils'
2 | import { describe, expect, it } from 'vitest'
3 | import { echoFooStr } from './echoFooStr'
4 |
5 | describe('mono utils', () => {
6 | it('foo', () => {
7 | echoFooStr()
8 | expect(foo()).toBe('foo')
9 | })
10 | })
11 |
--------------------------------------------------------------------------------
/packages/utils/tests/readFile.browser.spec.ts:
--------------------------------------------------------------------------------
1 | import { name } from '@mono/utils/readFile'
2 | import { describe, expect, expectTypeOf, it } from 'vitest'
3 |
4 | describe('readFile.browser', () => {
5 | it('name', () => {
6 | expect(name).toBe('readFile.browser')
7 | expectTypeOf(name).toEqualTypeOf<'readFile.browser'>()
8 | expectTypeOf(name).not.toEqualTypeOf<'readFile.node'>()
9 | })
10 | })
11 |
--------------------------------------------------------------------------------
/packages/utils/tests/readFile.node.spec.ts:
--------------------------------------------------------------------------------
1 | import { name } from '@mono/utils/readFile'
2 | import { describe, expect, expectTypeOf, it } from 'vitest'
3 |
4 | describe('readFile.node', () => {
5 | it('name', () => {
6 | expect(name).toBe('readFile.node')
7 | expectTypeOf(name).toEqualTypeOf<'readFile.node'>()
8 | expectTypeOf(name).not.toEqualTypeOf<'readFile.browser'>()
9 | })
10 | })
11 |
--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - apis
3 | - website
4 | - packages/*
5 |
--------------------------------------------------------------------------------
/scripts/echo-hi.ts:
--------------------------------------------------------------------------------
1 | console.log('hi')
2 |
--------------------------------------------------------------------------------
/scripts/rename-project-and-reset-author.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # use directory name as project name and let user confirm it or input a new one
4 | echo "Enter the new project name: (default: $(basename "$(pwd)"), press Enter to use default)"
5 | read -r new_project_name
6 | new_project_name=${new_project_name:-$(basename "$(pwd)")}
7 | echo "New project name: $new_project_name"
8 |
9 | # use git config user.name as author name and let user confirm it or input a new one
10 | echo "Enter the new author name: (default: $(git config user.name), press Enter to use default)"
11 | read -r new_author_name
12 | new_author_name=${new_author_name:-$(git config user.name)}
13 | echo "New author name: $new_author_name"
14 |
15 | # replace 'mono' string in this directory all files with new_project_name
16 | grep -rl --exclude-dir={.git,node_modules} --exclude='*.md' 'mono' .\
17 | | xargs sed -i '' -e "s/mono/$new_project_name/g"
18 | # replace 'YiJie' string in this directory all files with new_author_name
19 | grep -rl --exclude-dir={.git,node_modules} --exclude='*.md' 'YiJie' .\
20 | | xargs sed -i '' -e "s/YiJie/$new_author_name/g"
21 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "files": [],
3 | "references": [
4 | { "path": "./tsconfigs/tsconfig.default.json" },
5 | { "path": "./tsconfigs/tsconfig.default.spec.json" },
6 | { "path": "./tsconfigs/tsconfig.browser.json" },
7 | { "path": "./tsconfigs/tsconfig.browser.spec.json" },
8 | { "path": "./tsconfigs/tsconfig.node.json" },
9 | { "path": "./tsconfigs/tsconfig.node.spec.json" }
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/tsconfigs/tsconfig.base.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "rootDir": "..",
5 | "module": "ESNext",
6 | "allowImportingTsExtensions": true,
7 | "strict": true,
8 | "strictNullChecks": true,
9 | "esModuleInterop": true,
10 | "forceConsistentCasingInFileNames": true,
11 | "skipLibCheck": true
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/tsconfigs/tsconfig.browser.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["./tsconfig.base.json"],
3 | "compilerOptions": {
4 | "composite": true,
5 | "target": "esnext",
6 | "lib": ["ES2019", "dom"],
7 | "customConditions": ["browser"],
8 | "module": "esnext",
9 | "moduleResolution": "bundler",
10 | "types": []
11 | },
12 | "references": [
13 | { "path": "./tsconfig.default.json" }
14 | ],
15 | "include": [
16 | "../apis/src/**/*.share.d.ts",
17 | "../website/src/**/*",
18 | "../website/tests/**/*",
19 | "../packages/*/src/**/*.browser.ts"
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/tsconfigs/tsconfig.browser.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["./tsconfig.browser.json"],
3 | "compilerOptions": {
4 | "composite": true
5 | },
6 | "references": [
7 | { "path": "./tsconfig.browser.json" }
8 | ],
9 | "include": [
10 | "../packages/*/tests/**/*.browser.ts",
11 | "../packages/*/tests/**/*.browser.spec.ts"
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/tsconfigs/tsconfig.default.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["./tsconfig.base.json"],
3 | "compilerOptions": {
4 | "composite": true,
5 | "moduleResolution": "bundler"
6 | },
7 | "include": [
8 | "../packages/*/src/**/*.ts"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/tsconfigs/tsconfig.default.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["./tsconfig.default.json"],
3 | "compilerOptions": {
4 | "composite": true
5 | },
6 | "references": [
7 | { "path": "./tsconfig.default.json" }
8 | ],
9 | "include": [
10 | "../packages/*/tests/**/*.ts",
11 | "../packages/*/tests/**/*.spec.ts"
12 | ],
13 | "exclude": [
14 | "../packages/*/tests/**/*.browser.ts",
15 | "../packages/*/tests/**/*.browser.spec.ts",
16 | "../packages/*/tests/**/*.node.ts",
17 | "../packages/*/tests/**/*.node.spec.ts"
18 | ]
19 | }
20 |
--------------------------------------------------------------------------------
/tsconfigs/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["./tsconfig.base.json"],
3 | "compilerOptions": {
4 | "composite": true,
5 | "target": "ESNext",
6 | "customConditions": ["node"],
7 | "module": "NodeNext",
8 | "moduleResolution": "NodeNext",
9 | "resolveJsonModule": true,
10 | "types": ["node"]
11 | },
12 | "references": [
13 | { "path": "./tsconfig.default.json" }
14 | ],
15 | "include": [
16 | "../scripts/**/*.ts",
17 | "../.jiek.config.ts",
18 | "../.jiek.workspace.ts",
19 | "../vitest.config.ts",
20 | "../vitest.workspace.ts",
21 | "../website/vite.config.ts",
22 | "../website/src/**/*.share.d.ts",
23 | "../apis/src/**/*",
24 | "../apis/tests/**/*",
25 | "../packages/*/src/**/*.node.ts"
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/tsconfigs/tsconfig.node.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["./tsconfig.node.json"],
3 | "compilerOptions": {
4 | "composite": true
5 | },
6 | "references": [
7 | { "path": "./tsconfig.node.json" }
8 | ],
9 | "include": [
10 | "../packages/*/tests/**/*.node.ts",
11 | "../packages/*/tests/**/*.node.spec.ts"
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vitest/config'
2 |
3 | export default defineConfig({
4 | })
5 |
--------------------------------------------------------------------------------
/vitest.workspace.ts:
--------------------------------------------------------------------------------
1 | import fs from 'node:fs'
2 | import path from 'node:path'
3 | import process from 'node:process'
4 |
5 | import ts from 'typescript'
6 | import { defineWorkspace } from 'vitest/config'
7 |
8 | const isTestFileGlobExpr = (expr: string) => expr.includes('.spec.')
9 |
10 | const tsconfigPath = ts.findConfigFile(process.cwd(), fs.existsSync)
11 | if (!tsconfigPath) throw new Error('tsconfig.json not found')
12 |
13 | // eslint-disable-next-line ts/no-unsafe-assignment
14 | const { config: tsconfig, error } = ts.readConfigFile(tsconfigPath, p => fs.readFileSync(p, 'utf-8'))
15 | if (error) throw error
16 |
17 | const { projectReferences } = ts.parseJsonConfigFileContent(
18 | tsconfig,
19 | ts.sys,
20 | path.dirname(tsconfigPath),
21 | {},
22 | tsconfigPath
23 | )
24 |
25 | const projects: {
26 | files: string[]
27 | options: ts.CompilerOptions
28 | }[] = []
29 | projectReferences?.forEach(({ path: p }) => {
30 | // eslint-disable-next-line ts/no-unsafe-assignment
31 | const { config: tsconfig, error } = ts.readConfigFile(p, p => fs.readFileSync(p, 'utf-8'))
32 | if (error) throw error
33 | const { options, fileNames, errors } = ts.parseJsonConfigFileContent(tsconfig, ts.sys, path.dirname(p), {}, p)
34 | if (errors.length > 0) {
35 | errors.forEach(e =>
36 | console.warn(`[vitest] ${typeof e.messageText === 'string' ? e.messageText : e.messageText.messageText}`)
37 | )
38 | }
39 | if (fileNames.filter(isTestFileGlobExpr).length > 0) {
40 | projects.push({ files: fileNames, options })
41 | }
42 | })
43 |
44 | export default defineWorkspace(projects.map(({
45 | files,
46 | options
47 | }) => ({
48 | extends: './vitest.config.ts',
49 | test: { include: files },
50 | ssr: {
51 | target: options?.customConditions?.includes('browser')
52 | ? 'webworker'
53 | : 'node'
54 | },
55 | plugins: [
56 | {
57 | name: 'anonymous:overrideConditions',
58 | config: c => {
59 | if (!c.resolve) {
60 | c.resolve = {}
61 | }
62 | if (!c.resolve.conditions) {
63 | c.resolve.conditions = []
64 | }
65 | c.resolve.conditions = options?.customConditions ?? ['default']
66 | }
67 | }
68 | ]
69 | })))
70 |
--------------------------------------------------------------------------------
/website/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | mono
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/website/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "website",
3 | "type": "module",
4 | "version": "0.1.0",
5 | "author": {
6 | "name": "YiJie"
7 | },
8 | "scripts": {
9 | "start": "vite"
10 | },
11 | "imports": {
12 | "#~/*": "./src/*"
13 | },
14 | "dependencies": {
15 | "@mono/utils": "workspace:*"
16 | },
17 | "devDependencies": {
18 | "vite": "^5.4.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/website/src/index.share.d.ts:
--------------------------------------------------------------------------------
1 | declare module '@mono/share' {
2 | export type Numbers = 123 | 456
3 | }
4 |
--------------------------------------------------------------------------------
/website/src/index.ts:
--------------------------------------------------------------------------------
1 | import { foo } from '@mono/utils'
2 | import { bar } from '@mono/utils/bar'
3 | import { name } from '@mono/utils/readFile'
4 | // ^?
5 | import type { Numbers, Strings, User } from '@mono/share'
6 |
7 | import '#~/main.ts'
8 |
9 | // eslint-disable-next-line no-console
10 | console.log(name)
11 | // eslint-disable-next-line no-console
12 | console.log(foo(), bar())
13 |
14 | const num: Numbers = 123
15 | // eslint-disable-next-line no-console
16 | console.log(num)
17 | const str: Strings = 'abc'
18 | // eslint-disable-next-line no-console
19 | console.log(str)
20 |
21 | const user: User = {
22 | name: 'foo'
23 | }
24 | // eslint-disable-next-line no-console
25 | console.log(user.name)
26 |
--------------------------------------------------------------------------------
/website/src/main.ts:
--------------------------------------------------------------------------------
1 | document.querySelector('#app')!.innerHTML = 'Hello, World!'
2 |
--------------------------------------------------------------------------------
/website/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 |
3 | export default defineConfig({
4 | resolve: {
5 | conditions: ['browser', 'module', 'import', 'default']
6 | }
7 | })
8 |
--------------------------------------------------------------------------------