@lark-apaas/fullstack-presets 0.1.0 → 1.0.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/lib/index.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { createTailwindPreset } from './recommend/tailwind/createTailwindPreset';
2
+ export { eslintPresets } from './recommend/eslint';
package/lib/index.js CHANGED
@@ -1,5 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createTailwindPresets = void 0;
3
+ exports.eslintPresets = exports.createTailwindPreset = void 0;
4
+ // Tailwind 配置
4
5
  var createTailwindPreset_1 = require("./recommend/tailwind/createTailwindPreset");
5
- Object.defineProperty(exports, "createTailwindPresets", { enumerable: true, get: function () { return createTailwindPreset_1.createTailwindPresets; } });
6
+ Object.defineProperty(exports, "createTailwindPreset", { enumerable: true, get: function () { return createTailwindPreset_1.createTailwindPreset; } });
7
+ // Eslint 配置
8
+ var eslint_1 = require("./recommend/eslint");
9
+ Object.defineProperty(exports, "eslintPresets", { enumerable: true, get: function () { return eslint_1.eslintPresets; } });
@@ -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,91 @@
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
+ 'import/named': 'error', // 检查命名导入是否存在
56
+ // 其他规则
57
+ 'no-constant-binary-expression': 'off', // 不强制使用常量二进制表达式
58
+ // React Refresh 相关 - 开发时不影响渲染的检测
59
+ 'react-refresh/only-export-components': 'off',
60
+ 'no-restricted-syntax': [
61
+ 'error',
62
+ // 限制使用 fetch(推荐使用生成的 API Client)
63
+ {
64
+ message: "Please don't use fetch, use Generated API Client instead",
65
+ selector: "CallExpression[callee.name='fetch'][arguments.0.type='Literal'][arguments.0.value=/^\\u002F/]",
66
+ },
67
+ // 避免使用 console.log,推荐使用 logger 库
68
+ {
69
+ selector: "CallExpression[callee.object.name='console'][callee.property.name=/^(log|warn|info|debug|trace)$/]",
70
+ message: 'Avoid using console.log, console.warn, etc. Use `@lark-apaas/client-toolkit/logger` instead.',
71
+ },
72
+ // 禁用BOM方法alert和confirm,及不推荐使用同名方法
73
+ {
74
+ message: "Please don't use window.alert, use `Dialog` component instead for better user experience and consistency",
75
+ selector: "MemberExpression[object.name='window'][property.name='alert']",
76
+ },
77
+ {
78
+ message: "Please don't use window.confirm, use `Dialog` component instead for better user experience and consistency",
79
+ selector: "MemberExpression[object.name='window'][property.name='confirm']",
80
+ },
81
+ {
82
+ message: "Please don't use alert. It may conflict with window.alert BOM method, use `Dialog` component instead for better user experience and consistency",
83
+ selector: "CallExpression[callee.name='alert']",
84
+ },
85
+ {
86
+ message: "Please don't use confirm. It may conflict with window.confirm BOM method, use `Dialog` component instead for better user experience and consistency",
87
+ selector: "CallExpression[callee.name='confirm']",
88
+ },
89
+ ],
90
+ },
91
+ };
@@ -0,0 +1,46 @@
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/named': string;
34
+ 'import/no-extraneous-dependencies': string;
35
+ 'no-restricted-imports': (string | {
36
+ patterns: {
37
+ group: string[];
38
+ message: string;
39
+ }[];
40
+ })[];
41
+ '@darraghor/nestjs-typed/injectable-should-be-provided': (string | {
42
+ src: string[];
43
+ })[];
44
+ };
45
+ };
46
+ export default _default;
@@ -0,0 +1,65 @@
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': 'error',
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/named': 'error',
45
+ 'import/no-extraneous-dependencies': 'error',
46
+ // 禁止服务端导入客户端专用包
47
+ 'no-restricted-imports': [
48
+ 'error',
49
+ {
50
+ patterns: [
51
+ {
52
+ group: ['@lark-apaas/client-toolkit', '@lark-apaas/client-toolkit/*'],
53
+ message: 'This toolkit is for client-side use only and must not be imported or used in server-side code.',
54
+ },
55
+ ],
56
+ },
57
+ ],
58
+ '@darraghor/nestjs-typed/injectable-should-be-provided': [
59
+ 'error',
60
+ {
61
+ src: ['./server/**/*.ts'],
62
+ },
63
+ ],
64
+ },
65
+ };
@@ -0,0 +1,35 @@
1
+ export declare const eslintPresets: {
2
+ client: ({
3
+ readonly rules: Readonly<import("eslint").Linter.RulesRecord>;
4
+ } | {
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
+ } | import("typescript-eslint/dist/compatibility-types").CompatibleConfig)[];
32
+ server: ({
33
+ readonly rules: Readonly<import("eslint").Linter.RulesRecord>;
34
+ } | import("typescript-eslint/dist/compatibility-types").CompatibleConfig)[];
35
+ };
@@ -0,0 +1,26 @@
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
+ // 只导出纯净的规则配置,不包含基础配置
13
+ // 用户需要在项目配置中自己添加基础配置(eslintJs, tseslint, nestjs 等)
14
+ exports.eslintPresets = {
15
+ client: [
16
+ js_1.default.configs.recommended,
17
+ ...typescript_eslint_1.default.configs.recommended,
18
+ eslint_client_1.default
19
+ ],
20
+ server: [
21
+ js_1.default.configs.recommended,
22
+ ...typescript_eslint_1.default.configs.recommended,
23
+ ...eslint_plugin_nestjs_typed_1.default.configs.flatRecommended,
24
+ eslint_server_1.default
25
+ ],
26
+ };
@@ -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,8 @@
1
+ export declare function createTailwindPreset(options?: {
2
+ packageName?: string;
3
+ }): {
4
+ darkMode: string;
5
+ content: string[];
6
+ prefix: string;
7
+ plugins: any[];
8
+ };
@@ -33,10 +33,10 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.createTailwindPresets = createTailwindPresets;
36
+ exports.createTailwindPreset = createTailwindPreset;
37
37
  const path = __importStar(require("path"));
38
38
  const defaultPackageName = '@lark-apaas/client-toolkit';
39
- function createTailwindPresets(options = {}) {
39
+ function createTailwindPreset(options = {}) {
40
40
  // 默认补充扫描外网包依赖
41
41
  const { packageName = defaultPackageName } = options;
42
42
  const pkgPath = getToolKitPath(packageName);
@@ -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,9 +1,16 @@
1
1
  {
2
2
  "name": "@lark-apaas/fullstack-presets",
3
- "version": "0.1.0",
3
+ "version": "1.0.0",
4
4
  "files": [
5
5
  "lib"
6
6
  ],
7
+ "main": "./lib/index.js",
8
+ "types": "./lib/index.d.ts",
9
+ "license": "MIT",
10
+ "keywords": [
11
+ "fullstack",
12
+ "presets"
13
+ ],
7
14
  "publishConfig": {
8
15
  "access": "public"
9
16
  },
@@ -14,9 +21,23 @@
14
21
  "prepublishOnly": "npm run build"
15
22
  },
16
23
  "dependencies": {
24
+ "@darraghor/eslint-plugin-nestjs-typed": "^6.9.1",
25
+ "@eslint/js": "^9.35.0",
26
+ "eslint-import-resolver-alias": "^1.1.2",
27
+ "eslint-plugin-import": "^2.32.0",
28
+ "eslint-plugin-react": "^7.37.5",
29
+ "eslint-plugin-react-hooks": "^5.2.0",
30
+ "globals": "^16.4.0",
17
31
  "tailwindcss-animate": "^1.0.7"
18
32
  },
19
33
  "devDependencies": {
20
- "typescript": "^5.9.2"
34
+ "@types/eslint": "^9.6.0",
35
+ "eslint": "^9.35.0",
36
+ "typescript": "^5.9.2",
37
+ "typescript-eslint": "^8.44.0"
38
+ },
39
+ "peerDependencies": {
40
+ "eslint": "^9.0.0",
41
+ "typescript-eslint": "^8.44.0"
21
42
  }
22
43
  }