This commit is contained in:
2025-03-18 11:24:46 +08:00
commit a765dc8ba7
20 changed files with 1441 additions and 0 deletions

2
tojs/.npmrc Normal file
View File

@@ -0,0 +1,2 @@
//npm.xiongxiao.me/:_authToken=${ME_NPM_TOKEN}
//registry.npmjs.org/:_authToken=${NPM_TOKEN}

12
tojs/README.md Normal file
View File

@@ -0,0 +1,12 @@
# tojs
把一些ts和js文件转为import可以使用的js文件
浏览器请求的时候返回对应的cache。
## 使用
```ts
import { toJs } from '@kevisual/tojs';
```

36
tojs/package.json Normal file
View File

@@ -0,0 +1,36 @@
{
"name": "@kevisual/tojs",
"version": "0.0.5",
"description": "generate js from other js code",
"scripts": {
"build": "rollup -c",
"watch": "rollup -c -w"
},
"keywords": [],
"author": "abearxiong <xiongxiao@xiongxiao.me> (https://www.xiongxiao.me)",
"license": "MIT",
"packageManager": "pnpm@10.6.2",
"type": "module",
"publishConfig": {
"access": "public"
},
"devDependencies": {
"@rollup/plugin-node-resolve": "^16.0.1",
"@types/node": "^22.13.10",
"rollup": "^4.35.0",
"rollup-plugin-dts": "^6.1.1",
"rollup-plugin-esbuild": "^6.2.1",
"typescript": "^5.8.2"
},
"files": [
"dist"
],
"exports": {
".": "./dist/tojs.js"
},
"dependencies": {
"@cacheable/node-cache": "^1.5.3",
"@kevisual/use-config": "^1.0.9",
"cacheable": "^1.8.9"
}
}

32
tojs/rollup.config.js Normal file
View File

@@ -0,0 +1,32 @@
// rollup.config.js
import esbuild from 'rollup-plugin-esbuild';
import resolve from '@rollup/plugin-node-resolve';
import { dts } from 'rollup-plugin-dts';
/**
* @type {import('rollup').RollupOptions}
*/
export default [
{
input: 'src/index.ts', // TypeScript 入口文件
output: {
file: 'dist/tojs.js', // 输出文件
format: 'es', // 输出格式设置为 ES 模块
},
plugins: [
resolve(), // 使用 @rollup/plugin-node-resolve 解析 node_modules 中的模块
esbuild({
sourcemap: true,
minify: false,
}),
],
},
{
input: 'src/index.ts', // TypeScript 入口文件
output: {
file: 'dist/tojs.d.ts', // 输出文件
format: 'es', // 输出格式设置为 ES 模块
},
plugins: [dts()],
},
];

8
tojs/src/core.ts Normal file
View File

@@ -0,0 +1,8 @@
export class ToJs {
constructor(private readonly code: string) {}
public toJs() {
return this.code;
}
}

View File

@@ -0,0 +1,29 @@
import * as http from 'http';
import url from 'url';
export const parseBody = async (req: http.IncomingMessage) => {
return new Promise((resolve, reject) => {
const arr: any[] = [];
req.on('data', (chunk) => {
arr.push(chunk);
});
req.on('end', () => {
try {
if (arr.length === 0) {
resolve({});
return;
}
const body = Buffer.concat(arr).toString();
resolve(JSON.parse(body));
} catch (e) {
console.error('parse body error', e);
resolve({});
}
});
});
};
export const parseSearch = (req: http.IncomingMessage) => {
const parsedUrl = url.parse(req.url, true);
return parsedUrl.query;
};

66
tojs/src/http/res.ts Normal file
View File

@@ -0,0 +1,66 @@
import { IncomingMessage, ServerResponse } from 'http';
// import { parseBody, parseSearch } from './parse-body.ts';
// import { useContextKey } from '@kevisual/use-config/context';
import { CacheableMemory } from 'cacheable';
// const cache = useContextKey(
// 'cache',
// () =>
// new NodeCacheStore({
// ttl: 5 * 60, // 5 minutes
// }),
// );
const cache = new CacheableMemory({
ttl: 5 * 60, // 5 minutes
});
console.log('cache init');
type Context = {
req: IncomingMessage;
res: ServerResponse;
query?: any;
};
export const returnOriginalJs = async (
ctx: Context,
opts?: {
prefixUrl: string;
},
) => {
const { req, res, query } = ctx;
const prefixUrl = opts?.prefixUrl || '/';
const method = req.method;
const url = new URL(req.url, 'http://localhost');
const pathname = url.pathname;
const cacheKey = pathname.replace(prefixUrl, '');
console.log('keys', cache.keys);
if (method === 'GET') {
let cachedCode = await cache.get(cacheKey);
if (!cachedCode) {
let code = decodeURIComponent((query?.urlCode as string) || '');
if (code) {
await cache.set(cacheKey, code);
cachedCode = code;
}
}
if (cachedCode) {
res.setHeader('Cache-Control', 'public, max-age=43200'); // 12小时
res.setHeader('Content-Type', 'application/javascript');
res.end(cachedCode);
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('Resource not found');
}
return;
}
let code = decodeURIComponent((query?.urlCode as string) || '');
if (!code) {
code = query.code; // body code;
}
res.writeHead(200, { 'Content-Type': 'application/json' });
if (code) {
await cache.set(cacheKey, code);
res.end(JSON.stringify({ code: 200, message: 'success' }));
} else {
res.end(JSON.stringify({ code: 500, message: 'code is required' }));
}
};

4
tojs/src/index.ts Normal file
View File

@@ -0,0 +1,4 @@
import { returnOriginalJs } from './http/res.ts';
import { parseBody, parseSearch } from './http/parse-body.ts';
export { returnOriginalJs, parseBody, parseSearch };

36
tojs/tsconfig.json Normal file
View File

@@ -0,0 +1,36 @@
{
"compilerOptions": {
"module": "NodeNext",
"target": "esnext",
"noImplicitAny": false,
"outDir": "./dist",
"sourceMap": false,
"allowJs": true,
"newLine": "LF",
"baseUrl": "./",
"declaration": false,
"typeRoots": [
"node_modules/@types",
],
"noEmit": true,
"allowImportingTsExtensions": true,
"moduleResolution": "NodeNext",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"esModuleInterop": true,
"paths": {
"@/*": [
"src/*"
],
"*": [
"types/*"
]
}
},
"include": [
"src/**/*.ts"
],
"exclude": [
"node_modules",
]
}