@lark-apaas/fullstack-presets 1.0.14 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,2 @@
1
+ # 全栈技术栈 Presets
2
+ 独立拆分 simple 目录,属于全栈精简版,目前妙搭场景专用。
package/lib/index.d.ts CHANGED
@@ -1,3 +1,9 @@
1
1
  export { createTailwindPreset } from './recommend/tailwind/createTailwindPreset';
2
2
  export { eslintPresets } from './recommend/eslint';
3
3
  export { stylelintPresets } from './recommend/stylelint';
4
+ /**
5
+ * NestJs 精简版本配置(妙搭专用)
6
+ */
7
+ export { createTailwindPreset as createTailwindPresetOfSimple } from './simple/recommend/tailwind/createTailwindPreset';
8
+ export { eslintPresets as eslintPresetsOfSimple } from './simple/recommend/eslint';
9
+ export { stylelintPresets as stylelintPresetsOfSimple } from './simple/recommend/stylelint';
package/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.stylelintPresets = exports.eslintPresets = exports.createTailwindPreset = void 0;
3
+ exports.stylelintPresetsOfSimple = exports.eslintPresetsOfSimple = exports.createTailwindPresetOfSimple = exports.stylelintPresets = exports.eslintPresets = exports.createTailwindPreset = void 0;
4
4
  // Tailwind 配置
5
5
  var createTailwindPreset_1 = require("./recommend/tailwind/createTailwindPreset");
6
6
  Object.defineProperty(exports, "createTailwindPreset", { enumerable: true, get: function () { return createTailwindPreset_1.createTailwindPreset; } });
@@ -10,3 +10,15 @@ Object.defineProperty(exports, "eslintPresets", { enumerable: true, get: functio
10
10
  // Stylelint 配置
11
11
  var stylelint_1 = require("./recommend/stylelint");
12
12
  Object.defineProperty(exports, "stylelintPresets", { enumerable: true, get: function () { return stylelint_1.stylelintPresets; } });
13
+ /**
14
+ * NestJs 精简版本配置(妙搭专用)
15
+ */
16
+ // Tailwind 配置
17
+ var createTailwindPreset_2 = require("./simple/recommend/tailwind/createTailwindPreset");
18
+ Object.defineProperty(exports, "createTailwindPresetOfSimple", { enumerable: true, get: function () { return createTailwindPreset_2.createTailwindPreset; } });
19
+ // Eslint 配置
20
+ var eslint_2 = require("./simple/recommend/eslint");
21
+ Object.defineProperty(exports, "eslintPresetsOfSimple", { enumerable: true, get: function () { return eslint_2.eslintPresets; } });
22
+ // Stylelint 配置
23
+ var stylelint_2 = require("./simple/recommend/stylelint");
24
+ Object.defineProperty(exports, "stylelintPresetsOfSimple", { enumerable: true, get: function () { return stylelint_2.stylelintPresets; } });
@@ -0,0 +1,9 @@
1
+ import { type Configuration } from '@rspack/core';
2
+ export declare function createRecommendRspackConfig(options: {
3
+ enableReactRefresh?: boolean;
4
+ isDev?: boolean;
5
+ /** 是否需要插件解析路由 */
6
+ needRoutes?: boolean;
7
+ /** 运行态模式,默认为全栈模式 */
8
+ runtimeMode?: string;
9
+ }): Configuration;
@@ -0,0 +1,210 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createRecommendRspackConfig = createRecommendRspackConfig;
7
+ const path_1 = __importDefault(require("path"));
8
+ const core_1 = __importDefault(require("@rspack/core"));
9
+ const dev_server_listener_1 = require("../utils/dev-server-listener");
10
+ const RouteParserPlugin = require('../rspack-plugins/route-parser-plugin');
11
+ const SlardarPerformanceMonitorPlugin = require('../rspack-plugins/slardar-performance-monitor-plugin');
12
+ function createRecommendRspackConfig(options) {
13
+ const { enableReactRefresh = false, isDev = true, needRoutes = true, runtimeMode = 'fullstack', } = options;
14
+ return {
15
+ experiments: {
16
+ css: true,
17
+ },
18
+ module: {
19
+ rules: [
20
+ {
21
+ test: /\.svg$/,
22
+ type: 'asset',
23
+ parser: {
24
+ dataUrlCondition: {
25
+ maxSize: 10 * 1024, // 对应vite的assetsInlineLimit
26
+ },
27
+ },
28
+ },
29
+ {
30
+ test: /\.(png|jpe?g|gif|webp|ico)$/,
31
+ type: 'asset',
32
+ parser: {
33
+ dataUrlCondition: {
34
+ maxSize: 10 * 1024, // 对应vite的assetsInlineLimit
35
+ },
36
+ },
37
+ },
38
+ {
39
+ test: /\.css$/,
40
+ use: [
41
+ {
42
+ loader: 'postcss-loader',
43
+ options: {
44
+ postcssOptions: {
45
+ plugins: [
46
+ [
47
+ 'postcss-import',
48
+ {
49
+ resolve: (id, _basedir) => {
50
+ // 只有dev环境需要打包选中精调所需的一些预置样式, prod环境则不打包
51
+ if (id === '@/inspector.dev.css') {
52
+ return isDev
53
+ ? path_1.default.join(_basedir, '/inspector.dev.css')
54
+ : [];
55
+ }
56
+ return id;
57
+ },
58
+ },
59
+ ],
60
+ ],
61
+ },
62
+ },
63
+ },
64
+ ],
65
+ type: 'css',
66
+ },
67
+ {
68
+ test: /\.tsx?$/,
69
+ use: [
70
+ {
71
+ loader: 'builtin:swc-loader',
72
+ options: {
73
+ /**
74
+ * @type {import('@swc/core').JscConfig}
75
+ */
76
+ jsc: {
77
+ parser: {
78
+ syntax: 'typescript',
79
+ jsx: true,
80
+ },
81
+ transform: {
82
+ react: {
83
+ runtime: 'automatic',
84
+ ...(isDev
85
+ ? {
86
+ importSource: path_1.default.dirname(require.resolve('@lark-apaas/miaoda-inspector-jsx-runtime')),
87
+ }
88
+ : {}),
89
+ development: isDev,
90
+ refresh: enableReactRefresh,
91
+ },
92
+ },
93
+ },
94
+ },
95
+ },
96
+ ...(isDev
97
+ ? [require.resolve('@lark-apaas/miaoda-inspector-babel-plugin')]
98
+ : []),
99
+ ],
100
+ },
101
+ ],
102
+ },
103
+ plugins: [
104
+ // 针对 clsx/echarts 等包,让其默认好用
105
+ new core_1.default.NormalModuleReplacementPlugin(/^(clsx|echarts)$/, function (resource) {
106
+ if (!resource.context.endsWith('module-alias')) {
107
+ if (resource.request.endsWith('echarts')) {
108
+ resource.request = require.resolve('../module-alias/echarts.js');
109
+ }
110
+ else {
111
+ resource.request = require.resolve('../module-alias/clsx.js');
112
+ }
113
+ }
114
+ }),
115
+ new core_1.default.DefinePlugin({
116
+ 'process.env.NODE_ENV': JSON.stringify(isDev ? 'development' : 'production'),
117
+ 'process.env.CWD': JSON.stringify(process.cwd()),
118
+ 'process.env.runtimeMode': JSON.stringify(runtimeMode),
119
+ }),
120
+ new core_1.default.optimize.LimitChunkCountPlugin({
121
+ maxChunks: 1,
122
+ }),
123
+ // 全栈模式下,增加性能监控上报脚本注入
124
+ runtimeMode === 'fullstack'
125
+ ? new SlardarPerformanceMonitorPlugin()
126
+ : undefined,
127
+ // 开发环境下,解析路由
128
+ isDev &&
129
+ needRoutes &&
130
+ new RouteParserPlugin({
131
+ appPath: './client/src/app.tsx',
132
+ outputPath: path_1.default.resolve(__dirname, 'dist/client/routes.json'),
133
+ }),
134
+ ],
135
+ optimization: isDev
136
+ ? {}
137
+ : {
138
+ moduleIds: 'deterministic',
139
+ concatenateModules: true,
140
+ minimize: true, // 对应vite的minify配置
141
+ minimizer: [
142
+ new core_1.default.SwcJsMinimizerRspackPlugin({
143
+ minimizerOptions: {
144
+ // 保持不压缩
145
+ minify: !isDev,
146
+ mangle: !isDev,
147
+ format: {
148
+ beautify: isDev,
149
+ comments: false,
150
+ },
151
+ compress: {
152
+ keep_classnames: true,
153
+ keep_fnames: true,
154
+ keep_fargs: !isDev,
155
+ unused: true,
156
+ dead_code: true,
157
+ drop_debugger: true,
158
+ // FIXME: 先临时开始 console.log
159
+ // drop_console: !isDev,
160
+ const_to_let: !isDev,
161
+ booleans_as_integers: !isDev,
162
+ booleans: !isDev,
163
+ // maybe unsafe
164
+ reduce_funcs: !isDev,
165
+ reduce_vars: !isDev,
166
+ },
167
+ },
168
+ }),
169
+ new core_1.default.LightningCssMinimizerRspackPlugin(),
170
+ ],
171
+ sideEffects: true,
172
+ usedExports: true,
173
+ innerGraph: true,
174
+ providedExports: true,
175
+ mergeDuplicateChunks: true,
176
+ splitChunks: false, // 禁用代码分割,保持单文件输出
177
+ },
178
+ devtool: isDev ? 'source-map' : false, // 对应vite的sourcemap配置
179
+ devServer: {
180
+ headers: req => {
181
+ // 获取请求的Origin头
182
+ const requestOrigin = req.headers.origin ?? '';
183
+ // 定义允许的域名白名单
184
+ const allowedOrigins = [
185
+ 'https://miaoda.feishu.cn',
186
+ 'https://miaoda.feishu-boe.cn',
187
+ 'https://miaoda.feishu-pre.cn',
188
+ ];
189
+ // 检查请求的Origin是否在允许的列表中
190
+ const allowedOrigin = allowedOrigins.includes(requestOrigin)
191
+ ? requestOrigin
192
+ : allowedOrigins[0]; // 默认返回第一个允许的域名
193
+ return {
194
+ 'Access-Control-Allow-Origin': allowedOrigin,
195
+ };
196
+ },
197
+ onListening(server) {
198
+ if (runtimeMode === 'fullstack') {
199
+ (0, dev_server_listener_1.listenHmrTiming)(server);
200
+ }
201
+ },
202
+ client: {
203
+ overlay: {
204
+ errors: false,
205
+ warnings: false,
206
+ },
207
+ },
208
+ },
209
+ };
210
+ }
@@ -0,0 +1,29 @@
1
+ declare const _default: {
2
+ name: string;
3
+ languageOptions: {
4
+ ecmaVersion: number;
5
+ parser: any;
6
+ parserOptions: {
7
+ ecmaFeatures: {
8
+ jsx: boolean;
9
+ };
10
+ };
11
+ globals: any;
12
+ };
13
+ plugins: {
14
+ 'react-hooks': any;
15
+ import: any;
16
+ };
17
+ settings: {
18
+ 'import/resolver': {
19
+ node: {
20
+ extensions: string[];
21
+ };
22
+ };
23
+ 'import/parsers': {
24
+ '@typescript-eslint/parser': string[];
25
+ };
26
+ };
27
+ rules: any;
28
+ };
29
+ export default _default;
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const globals = require('globals');
4
+ const reactHooks = require('eslint-plugin-react-hooks');
5
+ const tseslint = require('typescript-eslint');
6
+ const importPlugin = require('eslint-plugin-import');
7
+ exports.default = {
8
+ name: 'fullstack-presets/client-recommend',
9
+ languageOptions: {
10
+ ecmaVersion: 2020,
11
+ parser: tseslint.parser,
12
+ parserOptions: {
13
+ ecmaFeatures: {
14
+ jsx: true,
15
+ },
16
+ },
17
+ globals: {
18
+ ...globals.browser,
19
+ ...globals.node,
20
+ },
21
+ },
22
+ plugins: {
23
+ 'react-hooks': reactHooks,
24
+ import: importPlugin,
25
+ },
26
+ settings: {
27
+ 'import/resolver': {
28
+ node: {
29
+ extensions: ['.js', '.jsx', '.ts', '.tsx'],
30
+ },
31
+ },
32
+ 'import/parsers': {
33
+ '@typescript-eslint/parser': ['.ts', '.tsx'],
34
+ },
35
+ },
36
+ rules: {
37
+ // React Hooks 推荐规则
38
+ ...reactHooks.configs.recommended.rules,
39
+ // TypeScript 规则
40
+ '@typescript-eslint/no-unused-vars': 'off', // 未使用变量检查关闭
41
+ '@typescript-eslint/no-explicit-any': 'off', // 允许使用 any 类型
42
+ '@typescript-eslint/no-empty-interface': 'off', // 允许空接口
43
+ '@typescript-eslint/no-empty-object-type': 'off', // 允许空对象类型
44
+ '@typescript-eslint/no-redeclare': 'error', // 禁止重复声明
45
+ // React 规则
46
+ 'react/jsx-no-undef-props': 'off', // 不检查未定义的 props
47
+ 'react/no-unknown-property': 'off', // 允许未知属性
48
+ 'react-hooks/exhaustive-deps': 'off', // 不强制检查依赖数组
49
+ // JavaScript 基础规则
50
+ 'no-undef': 'off', // 禁止使用未声明的变量
51
+ 'no-console': 'off', // 允许使用 console
52
+ 'prefer-const': 'off', // 不强制使用 const
53
+ // Import 规则
54
+ 'import/no-unresolved': 'error', // 检查导入路径是否存在
55
+ // 其他规则
56
+ 'no-constant-binary-expression': 'off', // 不强制使用常量二进制表达式
57
+ // React Refresh 相关 - 开发时不影响渲染的检测
58
+ 'react-refresh/only-export-components': 'off',
59
+ 'no-restricted-imports': [
60
+ 'error',
61
+ {
62
+ paths: [
63
+ {
64
+ name: 'next/link',
65
+ message: "Importing from 'next/link' is prohibited. Please use the `Link` component from 'react-router-dom' for navigation.",
66
+ },
67
+ ],
68
+ },
69
+ ],
70
+ 'no-restricted-syntax': [
71
+ 'error',
72
+ // 限制使用 fetch(推荐使用生成的 API Client)
73
+ {
74
+ message: "Please don't use fetch, use Generated API Client instead",
75
+ selector: "CallExpression[callee.name='fetch'][arguments.0.type='Literal'][arguments.0.value=/^\\u002F/]",
76
+ },
77
+ // 避免使用 console.log,推荐使用 logger 库
78
+ {
79
+ selector: "CallExpression[callee.object.name='console'][callee.property.name=/^(log|warn|info|debug|trace)$/]",
80
+ message: 'Avoid using console.log, console.warn, etc. Use `@lark-apaas/client-toolkit/logger` instead.',
81
+ },
82
+ // 禁用BOM方法alert和confirm,及不推荐使用同名方法
83
+ {
84
+ message: "Please don't use window.alert, use `Dialog` component instead for better user experience and consistency",
85
+ selector: "MemberExpression[object.name='window'][property.name='alert']",
86
+ },
87
+ {
88
+ message: "Please don't use window.confirm, use `Dialog` component instead for better user experience and consistency",
89
+ selector: "MemberExpression[object.name='window'][property.name='confirm']",
90
+ },
91
+ {
92
+ message: "Please don't use alert. It may conflict with window.alert BOM method, use `Dialog` component instead for better user experience and consistency",
93
+ selector: "CallExpression[callee.name='alert']",
94
+ },
95
+ {
96
+ message: "Please don't use confirm. It may conflict with window.confirm BOM method, use `Dialog` component instead for better user experience and consistency",
97
+ selector: "CallExpression[callee.name='confirm']",
98
+ },
99
+ // 禁用`window.location.href`赋值使用,可以读取
100
+ {
101
+ selector: 'AssignmentExpression[left.object.object.name="window"][left.object.property.name="location"][left.property.name="href"]',
102
+ message: "Please don't use `window.location.href` to navigate. Use `useNavigate` hook from 'react-router-dom' instead.",
103
+ },
104
+ // 禁止`location.href`赋值使用,可以读取
105
+ {
106
+ selector: 'AssignmentExpression[left.object.name="location"][left.property.name="href"]',
107
+ message: "Please don't use `location.href` to navigate. Use `useNavigate` hook from 'react-router-dom' instead.",
108
+ },
109
+ // SelectItem组件的value属性值不能为空字符串
110
+ {
111
+ message: 'The `value` attribute of the `SelectItem` component cannot be an empty string.',
112
+ selector: 'JSXOpeningElement[name.name="SelectItem"]:has(JSXAttribute[name.name="value"][value.value=""]), JSXOpeningElement[name.name="SelectItem"]:has(JSXAttribute[name.name="value"][value.expression.value=""])',
113
+ },
114
+ // 禁止a标签href使用相对路径
115
+ {
116
+ selector: "JSXOpeningElement[name.name='a']:has(JSXAttribute[name.name='href'][value.value=/^(?!https?:|\\u002F\\u002F|mailto:|tel:|#).+/])",
117
+ message: "Please don't use relative paths in <a> tags. Use NavLink from 'react-router-dom' instead.",
118
+ },
119
+ // 禁止 variant 为 outline|link|ghost 的 Button 使用 text-white
120
+ {
121
+ selector: 'JSXElement[openingElement.name.name="Button"]' +
122
+ ':has(JSXAttribute[name.name="variant"][value.value=/^(outline|link|ghost)$/])' +
123
+ ':has(JSXAttribute[name.name="className"][value.value=/text-white/])',
124
+ message: 'Button with variant="outline|link|ghost" should not use "text-white" className. This causes visibility issues. Consider using proper semantic color tokens from `client/src/tailwind-theme.css`',
125
+ },
126
+ // 禁止在 Button 上组合 text-primary-foreground 与 bg-background 并用的情况
127
+ {
128
+ selector: 'JSXElement[openingElement.name.name="Button"]' +
129
+ ':has(JSXAttribute[name.name="className"][value.value=/text-primary-foreground/])' +
130
+ ':has(JSXAttribute[name.name="className"][value.value=/bg-background/])',
131
+ message: 'Button should not use "text-primary-foreground" and "bg-background" className. This causes visibility issues. Consider using proper semantic color tokens from `client/src/tailwind-theme.css`',
132
+ },
133
+ // 禁止使用 text-accent
134
+ {
135
+ selector: 'JSXAttribute[name.name="className"][value.value=/(^|\\s)text-accent(\\s|$)/]',
136
+ message: 'Classname "text-accent" would cause visibility issues. Consider using proper semantic color tokens from `client/src/tailwind-theme.css`',
137
+ },
138
+ ],
139
+ },
140
+ };
@@ -0,0 +1,53 @@
1
+ declare const _default: {
2
+ name: string;
3
+ languageOptions: {
4
+ ecmaVersion: number;
5
+ sourceType: string;
6
+ parser: any;
7
+ globals: any;
8
+ };
9
+ plugins: {
10
+ import: any;
11
+ };
12
+ settings: {
13
+ 'import/resolver': {
14
+ node: {
15
+ extensions: string[];
16
+ };
17
+ };
18
+ 'import/parsers': {
19
+ '@typescript-eslint/parser': string[];
20
+ };
21
+ };
22
+ rules: {
23
+ '@typescript-eslint/no-unused-vars': string;
24
+ '@typescript-eslint/no-explicit-any': string;
25
+ '@typescript-eslint/no-empty-interface': string;
26
+ '@typescript-eslint/no-empty-object-type': string;
27
+ '@typescript-eslint/no-redeclare': string;
28
+ '@typescript-eslint/no-extraneous-class': string;
29
+ 'no-undef': string;
30
+ 'no-console': string;
31
+ 'prefer-const': string;
32
+ 'import/no-unresolved': string;
33
+ 'import/no-extraneous-dependencies': string;
34
+ 'no-restricted-imports': (string | {
35
+ patterns: {
36
+ group: string[];
37
+ message: string;
38
+ }[];
39
+ })[];
40
+ '@darraghor/nestjs-typed/injectable-should-be-provided': (string | {
41
+ src: string[];
42
+ })[];
43
+ '@darraghor/nestjs-typed/api-property-returning-array-should-set-array': string;
44
+ '@darraghor/nestjs-typed/api-property-matches-property-optionality': string;
45
+ '@darraghor/nestjs-typed/all-properties-have-explicit-defined': string;
46
+ '@darraghor/nestjs-typed/controllers-should-supply-api-tags': string;
47
+ '@darraghor/nestjs-typed/api-method-should-specify-api-response': string;
48
+ '@darraghor/nestjs-typed/api-method-should-specify-api-operation': string;
49
+ '@darraghor/nestjs-typed/api-enum-property-best-practices': string;
50
+ '@darraghor/nestjs-typed/all-properties-are-whitelisted': string;
51
+ };
52
+ };
53
+ export default _default;
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const globals = require('globals');
4
+ const tseslint = require('typescript-eslint');
5
+ const importPlugin = require('eslint-plugin-import');
6
+ exports.default = {
7
+ name: 'fullstack-presets/server-recommend',
8
+ languageOptions: {
9
+ ecmaVersion: 2022,
10
+ sourceType: 'module',
11
+ parser: tseslint.parser,
12
+ globals: {
13
+ ...globals.node,
14
+ NodeJS: true,
15
+ },
16
+ },
17
+ plugins: {
18
+ import: importPlugin,
19
+ },
20
+ settings: {
21
+ 'import/resolver': {
22
+ node: {
23
+ extensions: ['.js', '.jsx', '.ts', '.tsx'],
24
+ },
25
+ },
26
+ 'import/parsers': {
27
+ '@typescript-eslint/parser': ['.ts', '.tsx'],
28
+ },
29
+ },
30
+ rules: {
31
+ // TypeScript 规则
32
+ '@typescript-eslint/no-unused-vars': 'off',
33
+ '@typescript-eslint/no-explicit-any': 'off',
34
+ '@typescript-eslint/no-empty-interface': 'off',
35
+ '@typescript-eslint/no-empty-object-type': 'off',
36
+ '@typescript-eslint/no-redeclare': 'error',
37
+ '@typescript-eslint/no-extraneous-class': 'off',
38
+ // JavaScript 基础规则
39
+ 'no-undef': 'off',
40
+ 'no-console': 'error',
41
+ 'prefer-const': 'off',
42
+ // Import 规则
43
+ 'import/no-unresolved': 'error',
44
+ 'import/no-extraneous-dependencies': 'error',
45
+ // 禁止服务端导入客户端专用包
46
+ 'no-restricted-imports': [
47
+ 'error',
48
+ {
49
+ patterns: [
50
+ {
51
+ group: ['@lark-apaas/client-toolkit', '@lark-apaas/client-toolkit/*'],
52
+ message: 'This toolkit is for client-side use only and must not be imported or used in server-side code.',
53
+ },
54
+ ],
55
+ },
56
+ ],
57
+ '@darraghor/nestjs-typed/injectable-should-be-provided': [
58
+ 'error',
59
+ {
60
+ src: ['./server/**/*.ts'],
61
+ },
62
+ ],
63
+ '@darraghor/nestjs-typed/api-property-returning-array-should-set-array': 'off',
64
+ '@darraghor/nestjs-typed/api-property-matches-property-optionality': 'off',
65
+ '@darraghor/nestjs-typed/all-properties-have-explicit-defined': 'off',
66
+ // 关闭 Swagger 相关规则
67
+ '@darraghor/nestjs-typed/controllers-should-supply-api-tags': 'off',
68
+ '@darraghor/nestjs-typed/api-method-should-specify-api-response': 'off',
69
+ '@darraghor/nestjs-typed/api-method-should-specify-api-operation': 'off',
70
+ '@darraghor/nestjs-typed/api-enum-property-best-practices': 'off',
71
+ '@darraghor/nestjs-typed/all-properties-are-whitelisted': 'off',
72
+ },
73
+ };
@@ -0,0 +1,37 @@
1
+ export declare const eslintPresets: {
2
+ client: ({
3
+ readonly rules: Readonly<import("eslint").Linter.RulesRecord>;
4
+ } | import("typescript-eslint/dist/compatibility-types").CompatibleConfig | {
5
+ name: string;
6
+ languageOptions: {
7
+ ecmaVersion: number;
8
+ parser: any;
9
+ parserOptions: {
10
+ ecmaFeatures: {
11
+ jsx: boolean;
12
+ };
13
+ };
14
+ globals: any;
15
+ };
16
+ plugins: {
17
+ 'react-hooks': any;
18
+ import: any;
19
+ };
20
+ settings: {
21
+ 'import/resolver': {
22
+ node: {
23
+ extensions: string[];
24
+ };
25
+ };
26
+ 'import/parsers': {
27
+ '@typescript-eslint/parser': string[];
28
+ };
29
+ };
30
+ rules: any;
31
+ } | {
32
+ ignores: string[];
33
+ })[];
34
+ server: ({
35
+ readonly rules: Readonly<import("eslint").Linter.RulesRecord>;
36
+ } | import("typescript-eslint/dist/compatibility-types").CompatibleConfig)[];
37
+ };
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.eslintPresets = void 0;
7
+ const eslint_client_1 = __importDefault(require("./eslint-client"));
8
+ const eslint_server_1 = __importDefault(require("./eslint-server"));
9
+ const js_1 = __importDefault(require("@eslint/js"));
10
+ const typescript_eslint_1 = __importDefault(require("typescript-eslint"));
11
+ const eslint_plugin_nestjs_typed_1 = __importDefault(require("@darraghor/eslint-plugin-nestjs-typed"));
12
+ const globalIgnoreServerPatterns = ['server/database/.introspect/**']; // 全局 eslint server ignore
13
+ const globalIgnoreClientPatterns = ['dist', 'node_modules', 'client/src/api/gen']; // 全局 eslint client Ignore
14
+ // 只导出纯净的规则配置,不包含基础配置
15
+ // 用户需要在项目配置中自己添加基础配置(eslintJs, tseslint, nestjs 等)
16
+ exports.eslintPresets = {
17
+ client: [
18
+ { ignores: globalIgnoreClientPatterns },
19
+ js_1.default.configs.recommended,
20
+ ...typescript_eslint_1.default.configs.recommended,
21
+ eslint_client_1.default
22
+ ],
23
+ server: [
24
+ { ignores: globalIgnoreServerPatterns },
25
+ js_1.default.configs.recommended,
26
+ ...typescript_eslint_1.default.configs.recommended,
27
+ ...eslint_plugin_nestjs_typed_1.default.configs.flatRecommended,
28
+ eslint_server_1.default
29
+ ],
30
+ };
@@ -0,0 +1,5 @@
1
+ export declare const stylelintPresets: {
2
+ rules: {
3
+ 'declaration-block-no-duplicate-custom-properties': boolean;
4
+ };
5
+ };
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.stylelintPresets = void 0;
4
+ exports.stylelintPresets = {
5
+ rules: {
6
+ 'declaration-block-no-duplicate-custom-properties': true,
7
+ },
8
+ };
@@ -0,0 +1,8 @@
1
+ export declare function createTailwindPreset(options?: {
2
+ packageName?: string;
3
+ }): {
4
+ darkMode: string;
5
+ content: string[];
6
+ prefix: string;
7
+ plugins: any[];
8
+ };
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.createTailwindPreset = createTailwindPreset;
37
+ const path = __importStar(require("path"));
38
+ const defaultPackageName = '@lark-apaas/client-toolkit';
39
+ function createTailwindPreset(options = {}) {
40
+ // 默认补充扫描外网包依赖
41
+ const { packageName = defaultPackageName } = options;
42
+ const pkgPath = getToolKitPath(packageName);
43
+ return {
44
+ darkMode: 'class',
45
+ content: [pkgPath].filter(Boolean),
46
+ prefix: '',
47
+ plugins: [
48
+ require('tailwindcss-animate'),
49
+ ],
50
+ };
51
+ }
52
+ function getToolKitPath(packageName) {
53
+ let pkgPath = '';
54
+ if (packageName) {
55
+ try {
56
+ pkgPath = path.join(path.dirname(require.resolve(packageName)), '/**/*.js');
57
+ }
58
+ catch (e) {
59
+ console.warn(`Failed to resolve package ${packageName}, use default path`);
60
+ }
61
+ }
62
+ return pkgPath;
63
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "useDefineForClassFields": true,
5
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "skipLibCheck": true,
8
+
9
+ /* Bundler mode */
10
+ "moduleResolution": "bundler",
11
+ "allowImportingTsExtensions": true,
12
+ "isolatedModules": true,
13
+ "moduleDetection": "force",
14
+ "noEmit": true,
15
+ "jsx": "react-jsx",
16
+
17
+ /* Linting */
18
+ "strict": false,
19
+ "noUnusedLocals": false,
20
+ "noUnusedParameters": false,
21
+ "noImplicitAny": false,
22
+ "noFallthroughCasesInSwitch": false,
23
+
24
+ "sourceMap": true,
25
+ "allowJs": true,
26
+ "strictNullChecks": false,
27
+
28
+ "incremental": false,
29
+ },
30
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "commonjs",
5
+ "moduleResolution": "node",
6
+ "skipLibCheck": true,
7
+ "esModuleInterop": true,
8
+
9
+ /* Bundler mode */
10
+ "experimentalDecorators": true,
11
+ "emitDecoratorMetadata": true,
12
+ "importHelpers": true,
13
+ "incremental": true,
14
+ "noEmit": false,
15
+
16
+ /* Linting */
17
+ "strict": false,
18
+ "composite": true,
19
+ "declaration": true,
20
+ "removeComments": false,
21
+
22
+ "types": ["node"]
23
+ },
24
+ "ts-node": { "require": ["tsconfig-paths/register"] }
25
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * 监听 HMR 编译时间
3
+ * @param server
4
+ */
5
+ export declare function listenHmrTiming(server: any): void;
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.listenHmrTiming = listenHmrTiming;
37
+ /* eslint-disable @typescript-eslint/no-explicit-any */
38
+ const fs = __importStar(require("fs"));
39
+ /**
40
+ * 监听 HMR 编译时间
41
+ * @param server
42
+ */
43
+ function listenHmrTiming(server) {
44
+ const compiler = server.compiler;
45
+ const ws = server.webSocketServer;
46
+ let start = 0;
47
+ let changedFiles = new Set();
48
+ // 监听文件变更
49
+ compiler.hooks.watchRun.tap('HmrTiming', (comp) => {
50
+ const modifiedFiles = comp.modifiedFiles;
51
+ if (modifiedFiles && modifiedFiles.size > 0) {
52
+ changedFiles = new Set(modifiedFiles);
53
+ }
54
+ else {
55
+ changedFiles.clear();
56
+ }
57
+ start = Date.now();
58
+ });
59
+ // 编译完成
60
+ compiler.hooks.done.tap('HmrTiming', () => {
61
+ const duration = Date.now() - start;
62
+ // 过滤有效文件 - 只保留实际的项目文件
63
+ const validFiles = [...changedFiles]
64
+ .map(f => f.replace(process.cwd(), '').replace(/\\/g, '/'))
65
+ .filter(filePath => {
66
+ // 过滤无效文件
67
+ if (!filePath || filePath.length === 0)
68
+ return false;
69
+ // 过滤 node_modules 中的文件
70
+ if (filePath.includes('/node_modules/'))
71
+ return false;
72
+ // 只保留支持的文件类型
73
+ const validExtensions = ['.js', '.jsx', '.ts', '.tsx', '.svelte', '.css', '.json', '.html'];
74
+ const hasValidExtension = validExtensions.some(ext => filePath.toLowerCase().endsWith(ext));
75
+ if (!hasValidExtension)
76
+ return false;
77
+ return true;
78
+ });
79
+ // 获取文件统计信息
80
+ const fileStats = validFiles.map(filePath => {
81
+ const fullPath = process.cwd() + filePath;
82
+ try {
83
+ const stats = fs.statSync(fullPath);
84
+ return {
85
+ path: filePath,
86
+ size: stats.size,
87
+ };
88
+ }
89
+ catch (error) {
90
+ return {
91
+ path: filePath,
92
+ size: 0,
93
+ };
94
+ }
95
+ });
96
+ // 计算总文件大小(B)
97
+ const totalSize = fileStats.reduce((sum, file) => sum + file.size, 0);
98
+ const payload = {
99
+ duration,
100
+ fileCount: validFiles.length,
101
+ fileTotalSize: totalSize,
102
+ };
103
+ // 推送到浏览器端
104
+ for (const client of ws.clients) {
105
+ if (client.readyState === 1) {
106
+ client.send(JSON.stringify({
107
+ type: 'hmr-timing',
108
+ data: payload,
109
+ }));
110
+ }
111
+ }
112
+ });
113
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/fullstack-presets",
3
- "version": "1.0.14",
3
+ "version": "1.1.0",
4
4
  "files": [
5
5
  "lib"
6
6
  ],