mirror of
https://github.com/NapNeko/NapCatQQ.git
synced 2026-02-04 06:31:13 +00:00
Refactor type build: inline external types, simplify scripts
Removed custom build scripts for copying and inlining types, consolidating all post-build logic into a single enhanced post-build.mjs script. The new script processes .d.ts files, inlines external module types, updates imports, and copies necessary files to dist, eliminating the need for external-shims and simplifying the build process. Updated package.json scripts accordingly. Refactor type inlining: remove shims, auto-extract types Removed external-shims.d.ts and its references, replacing manual shims with an automated script that extracts type definitions from node_modules. Updated build scripts, dependencies, and test files to support the new inlining process. The inline-types.mjs script now scans for external imports, generates inline type files, and rewrites imports as import type, eliminating the need for hand-written shims. Add type inlining script and update build process Introduced a new script (inline-types.mjs) to inline external type dependencies into the dist directory, updated the build process to use this script, and removed the now-unnecessary external-shims.d.ts from the copy-dist script. Added a test file to verify inlined types, updated dependencies to include ts-morph, and adjusted package.json and pnpm-lock.yaml accordingly.
This commit is contained in:
parent
b958e9e803
commit
542036f46e
@ -1,4 +1,3 @@
|
||||
/// <reference path="./external-shims.d.ts" />
|
||||
// 聚合导出核心库的所有内容(包括枚举、类和类型)
|
||||
export * from '../napcat-core/index';
|
||||
|
||||
|
||||
@ -14,13 +14,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": "^22.10.7",
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/ws": "^8.5.12",
|
||||
"@types/cors": "^2.8.17",
|
||||
"@types/multer": "^1.4.12",
|
||||
"@types/winston": "^2.4.4",
|
||||
"@types/yaml": "^1.9.7",
|
||||
"@types/ip": "^1.1.3",
|
||||
"@sinclair/typebox": "^0.34.38"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "napcat-types",
|
||||
"version": "0.0.9",
|
||||
"version": "0.0.10",
|
||||
"private": false,
|
||||
"type": "module",
|
||||
"types": "./napcat-types/index.d.ts",
|
||||
@ -9,13 +9,6 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@types/node": "^22.10.7",
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/ws": "^8.5.12",
|
||||
"@types/cors": "^2.8.17",
|
||||
"@types/multer": "^1.4.12",
|
||||
"@types/winston": "^2.4.4",
|
||||
"@types/yaml": "^1.9.7",
|
||||
"@types/ip": "^1.1.3",
|
||||
"@sinclair/typebox": "^0.34.38"
|
||||
},
|
||||
"publishConfig": {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// 复制 cp README.md dist/ && cp package.public.json dist/package.json && cp external-shims.d.ts dist/
|
||||
// 复制 cp README.md dist/ && cp package.public.json dist/package.json
|
||||
import { copyFile } from 'node:fs/promises';
|
||||
import { join } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
@ -10,8 +10,4 @@ await copyFile(
|
||||
await copyFile(
|
||||
join(__dirname, 'README.md'),
|
||||
join(__dirname, 'dist', 'README.md')
|
||||
);
|
||||
await copyFile(
|
||||
join(__dirname, 'external-shims.d.ts'),
|
||||
join(__dirname, 'dist', 'external-shims.d.ts')
|
||||
);
|
||||
@ -5,6 +5,111 @@ import { fileURLToPath } from 'node:url';
|
||||
const __dirname = fileURLToPath(new URL('../', import.meta.url));
|
||||
const distDir = join(__dirname, 'dist');
|
||||
|
||||
// 允许保留的包(白名单)
|
||||
const ALLOWED_PACKAGES = [
|
||||
'@sinclair/typebox',
|
||||
'node:', // node: 前缀的内置模块
|
||||
];
|
||||
|
||||
// 外部包类型到 any 的映射
|
||||
const EXTERNAL_TYPE_REPLACEMENTS = {
|
||||
// winston
|
||||
'winston.Logger': 'any',
|
||||
'winston.transport': 'any',
|
||||
// express
|
||||
'express.Express': 'any',
|
||||
'express.Application': 'any',
|
||||
'express.Router': 'any',
|
||||
'Express': 'any',
|
||||
'Request': 'any',
|
||||
'Response': 'any',
|
||||
'NextFunction': 'any',
|
||||
// ws
|
||||
'WebSocket': 'any',
|
||||
'WebSocketServer': 'any',
|
||||
'RawData': 'any',
|
||||
// ajv
|
||||
'Ajv': 'any',
|
||||
'AnySchema': 'any',
|
||||
'ValidateFunction': 'any',
|
||||
'ValidateFunction<T>': 'any',
|
||||
// inversify
|
||||
'Container': 'any',
|
||||
// async-mutex
|
||||
'Mutex': 'any',
|
||||
'Semaphore': 'any',
|
||||
// napcat-protobuf
|
||||
'NapProtoDecodeStructType': 'any',
|
||||
'NapProtoEncodeStructType': 'any',
|
||||
'NapProtoDecodeStructType<T>': 'any',
|
||||
'NapProtoEncodeStructType<T>': 'any',
|
||||
};
|
||||
|
||||
function isAllowedImport (importPath) {
|
||||
return ALLOWED_PACKAGES.some(pkg => importPath.startsWith(pkg));
|
||||
}
|
||||
|
||||
function removeExternalImports (content) {
|
||||
const lines = content.split('\n');
|
||||
const resultLines = [];
|
||||
|
||||
for (const line of lines) {
|
||||
// 匹配 import 语句
|
||||
const importMatch = line.match(/^import\s+.*\s+from\s+['"]([^'"]+)['"]/);
|
||||
if (importMatch) {
|
||||
const importPath = importMatch[1];
|
||||
// 如果是相对路径或白名单包,保留
|
||||
if (importPath.startsWith('.') || importPath.startsWith('/') || isAllowedImport(importPath)) {
|
||||
resultLines.push(line);
|
||||
}
|
||||
// 否则移除该 import
|
||||
continue;
|
||||
}
|
||||
resultLines.push(line);
|
||||
}
|
||||
|
||||
return resultLines.join('\n');
|
||||
}
|
||||
|
||||
function replaceExternalTypes (content) {
|
||||
let result = content;
|
||||
|
||||
// 替换带泛型的类型(先处理复杂的)
|
||||
result = result.replace(/NapProtoDecodeStructType<[^>]+>/g, 'any');
|
||||
result = result.replace(/NapProtoEncodeStructType<[^>]+>/g, 'any');
|
||||
result = result.replace(/ValidateFunction<[^>]+>/g, 'any');
|
||||
|
||||
// 替换 winston.Logger 等带命名空间的类型
|
||||
result = result.replace(/winston\.Logger/g, 'any');
|
||||
result = result.replace(/winston\.transport/g, 'any');
|
||||
result = result.replace(/express\.Express/g, 'any');
|
||||
result = result.replace(/express\.Application/g, 'any');
|
||||
result = result.replace(/express\.Router/g, 'any');
|
||||
|
||||
// 替换独立的类型名(需要小心不要替换变量名)
|
||||
// 使用类型上下文的模式匹配
|
||||
const typeContextPatterns = [
|
||||
// : Type
|
||||
/:\s*(WebSocket|WebSocketServer|RawData|Ajv|AnySchema|ValidateFunction|Container|Mutex|Semaphore|NapProtoDecodeStructType|NapProtoEncodeStructType|Express|Request|Response|NextFunction)(?=\s*[;,)\]\}|&]|$)/g,
|
||||
// <Type>
|
||||
/<(WebSocket|WebSocketServer|RawData|Ajv|AnySchema|ValidateFunction|Container|Mutex|Semaphore|NapProtoDecodeStructType|NapProtoEncodeStructType|Express|Request|Response|NextFunction)>/g,
|
||||
// Type[]
|
||||
/(WebSocket|WebSocketServer|RawData|Ajv|AnySchema|ValidateFunction|Container|Mutex|Semaphore|NapProtoDecodeStructType|NapProtoEncodeStructType|Express|Request|Response|NextFunction)\[\]/g,
|
||||
// extends Type
|
||||
/extends\s+(WebSocket|WebSocketServer|RawData|Ajv|AnySchema|ValidateFunction|Container|Mutex|Semaphore|NapProtoDecodeStructType|NapProtoEncodeStructType|Express|Request|Response|NextFunction)(?=\s*[{,])/g,
|
||||
// implements Type
|
||||
/implements\s+(WebSocket|WebSocketServer|RawData|Ajv|AnySchema|ValidateFunction|Container|Mutex|Semaphore|NapProtoDecodeStructType|NapProtoEncodeStructType|Express|Request|Response|NextFunction)(?=\s*[{,])/g,
|
||||
];
|
||||
|
||||
for (const pattern of typeContextPatterns) {
|
||||
result = result.replace(pattern, (match, typeName) => {
|
||||
return match.replace(typeName, 'any');
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async function traverseDirectory (dir) {
|
||||
const entries = await readdir(dir, { withFileTypes: true });
|
||||
|
||||
@ -23,7 +128,13 @@ async function processFile (filePath) {
|
||||
// Read file content
|
||||
let content = await readFile(filePath, 'utf-8');
|
||||
|
||||
// Replace "export declare enum" with "export enum"
|
||||
// 1. 移除外部包的 import
|
||||
content = removeExternalImports(content);
|
||||
|
||||
// 2. 替换外部类型为 any
|
||||
content = replaceExternalTypes(content);
|
||||
|
||||
// 3. Replace "export declare enum" with "export enum"
|
||||
content = content.replace(/export declare enum/g, 'export enum');
|
||||
|
||||
// Write back the modified content
|
||||
@ -33,7 +144,7 @@ async function processFile (filePath) {
|
||||
const newPath = filePath.replace(/\.d\.ts$/, '.ts');
|
||||
await rename(filePath, newPath);
|
||||
|
||||
console.log(`Processed: ${basename(filePath)} -> ${basename(newPath)}`);
|
||||
//console.log(`Processed: ${basename(filePath)} -> ${basename(newPath)}`);
|
||||
}
|
||||
|
||||
console.log('Starting post-build processing...');
|
||||
|
||||
@ -39,9 +39,6 @@
|
||||
"../napcat-onebot/**/*.ts",
|
||||
"../napcat-common/**/*.ts"
|
||||
],
|
||||
"files": [
|
||||
"./external-shims.d.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist"
|
||||
|
||||
@ -308,30 +308,9 @@ importers:
|
||||
'@sinclair/typebox':
|
||||
specifier: ^0.34.38
|
||||
version: 0.34.41
|
||||
'@types/cors':
|
||||
specifier: ^2.8.17
|
||||
version: 2.8.19
|
||||
'@types/express':
|
||||
specifier: ^4.17.21
|
||||
version: 4.17.25
|
||||
'@types/ip':
|
||||
specifier: ^1.1.3
|
||||
version: 1.1.3
|
||||
'@types/multer':
|
||||
specifier: ^1.4.12
|
||||
version: 1.4.13
|
||||
'@types/node':
|
||||
specifier: ^22.10.7
|
||||
version: 22.19.1
|
||||
'@types/winston':
|
||||
specifier: ^2.4.4
|
||||
version: 2.4.4
|
||||
'@types/ws':
|
||||
specifier: ^8.5.12
|
||||
version: 8.18.1
|
||||
'@types/yaml':
|
||||
specifier: ^1.9.7
|
||||
version: 1.9.7
|
||||
devDependencies:
|
||||
napcat-core:
|
||||
specifier: workspace:*
|
||||
|
||||
Loading…
Reference in New Issue
Block a user