mirror of
https://github.com/lush2020/edgetunnel.git
synced 2026-03-22 01:22:21 +08:00
Vless (#67)
* init vless * change to cdn for uuid * add TODO * add support for ipv4 and 6 * add support for ipv4 and 6 * add error handle * add error handle * add error handle * add debug log * add debug log * add udp log * add udp log * update vless-js * add doc * add doc * add doc * remove log * remove log * remove log * remove log
This commit is contained in:
3
.vscode/extensions.json
vendored
3
.vscode/extensions.json
vendored
@@ -2,6 +2,7 @@
|
||||
"recommendations": [
|
||||
"nrwl.angular-console",
|
||||
"esbenp.prettier-vscode",
|
||||
"dbaeumer.vscode-eslint"
|
||||
"dbaeumer.vscode-eslint",
|
||||
"firsttris.vscode-jest-runner"
|
||||
]
|
||||
}
|
||||
|
||||
21
.vscode/launch.json
vendored
Normal file
21
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"request": "launch",
|
||||
"name": "Launch Program",
|
||||
"type": "pwa-node",
|
||||
"program": "C:\\github\\edgetunnel\\apps\\deno-vless\\src\\main.ts",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"runtimeExecutable": "C:\\Users\\zizifn\\scoop\\shims\\deno.EXE",
|
||||
"runtimeArgs": ["run", "--inspect", "--allow-all", "--unstable"],
|
||||
"attachSimplePort": 9229,
|
||||
"env": {
|
||||
"UUID": ""
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"deno.codeLens.implementations": true,
|
||||
"deno.codeLens.references": true,
|
||||
"deno.enablePaths": ["apps/deno-bypass"]
|
||||
"deno.enablePaths": ["apps/deno-bypass", "apps/deno-vless"]
|
||||
}
|
||||
|
||||
129
README.md
129
README.md
@@ -1,14 +1,14 @@
|
||||
# Edge Tunnel (正在开发)
|
||||
# Edge Tunnel (Beta)
|
||||
|
||||
一个无比简单安全,基于 edge 的 tunnel 。
|
||||
把 V2ray 部署到 Edge/Serverless Functions 平台上。
|
||||
|
||||
**v2ray-heroku 由于 heroku 取消免费,项目已经死了。
|
||||
**v2ray-heroku 由于 heroku 取消免费,项目已经死了。**
|
||||
|
||||
> 项目正在开发,基本可用,会有 bug。。
|
||||
> **请定期按照 github 的提示,只同步到自己的项目。只需要在乎下图红框的提示,其他提示不要点击**。
|
||||
> 
|
||||
|
||||
> 本项目纯属技术性验证,探索最新的 web standard。不给予任何保证。请大家酌情使用。如果有兴趣想一起进行技术探讨可以联系我。💕
|
||||
> 本项目纯属技术性验证,探索最新的 web standard。不给予任何保证。
|
||||
|
||||
## Edge Tunnel server --- Deno deploy
|
||||
|
||||
@@ -21,97 +21,78 @@ Edge tunnel 的服务使用了 [Deno deploy](https://deno.com/deploy).
|
||||
|
||||
> 这里十分感谢 Deno deploy 严肃对待 web standard, 支持 HTTP request & response streaming,让 edge tunnel 成为可能。
|
||||
|
||||
> 这里没有使用 deno websocket,其实技术上可以把 v2ray 移植过来。但是我暂时没有看明白 VLESS 协议内容.
|
||||
|
||||
## Edge Tunnel server --- Cloudflare Worker (敬请期待)
|
||||
|
||||
这个需要等 Cloudflare 发布下面的技术。
|
||||
https://blog.cloudflare.com/introducing-socket-workers/
|
||||
|
||||
### 如何部署服务
|
||||
|
||||
请查看下面教程。
|
||||
|
||||
[Deno deploy Install](./doc/edge-tunnel-deno.md)
|
||||
|
||||
## Edge Tunnel 客户端
|
||||
## Edge Tunnel server --- Cloudflare Worker (敬请期待)
|
||||
|
||||
> 由于看不懂 VLESS 协议内容, 所以无法使用常用的客户端软件.
|
||||
这个需要等 Cloudflare 发布下面的技术。
|
||||
https://blog.cloudflare.com/introducing-socket-workers/
|
||||
|
||||
### 安装
|
||||
## 客户端 v2rayN 配置
|
||||
|
||||
请转到本项目 [releases](https://github.com/zizifn/edgetunnel/releases),选择正确的平台,下载最新客户端.
|
||||
> ⚠️ 由于 edge 平台限制,无法转发 UDP 包。请在配置时候,把 DNS 的策略改成 "Asis", 否则会影响速度。
|
||||
|
||||
项目使用https://github.com/vercel/pkg, 所以支持下面平台.
|
||||
> [ DNS 科普文章](https://tachyondevel.medium.com/%E6%BC%AB%E8%B0%88%E5%90%84%E7%A7%8D%E9%BB%91%E7%A7%91%E6%8A%80%E5%BC%8F-dns-%E6%8A%80%E6%9C%AF%E5%9C%A8%E4%BB%A3%E7%90%86%E7%8E%AF%E5%A2%83%E4%B8%AD%E7%9A%84%E5%BA%94%E7%94%A8-62c50e58cbd0)
|
||||
|
||||
1. **platform** alpine, linux, linuxstatic, win, macos, (freebsd)
|
||||
2. **arch** x64, arm64, (armv6, armv7)
|
||||
## VLESS websocket 客户端配置
|
||||
|
||||
## 启动
|
||||
|
||||
解压并且修改安装文件的 `config.json` 文件.
|
||||
> ⚠️ 由于 edge 平台限制,无法转发 UDP 包。请在配置时候,把 DNS 的策略改成 "Asis", 否则会影响速度。
|
||||
|
||||
```json
|
||||
{
|
||||
"port": "1081", // 本地 HTTP 代理的端口
|
||||
"address": "https://****.deno.dev/", // deno deploy URL
|
||||
"uuid": "****" // 你 deno deploy 设置的用户
|
||||
}
|
||||
"outbounds": [
|
||||
{
|
||||
"protocol": "vless",
|
||||
"settings": {
|
||||
"vnext": [
|
||||
{
|
||||
"address": "***.herokuapp.com", // edge app URL 或者 cloudflare worker url/ip
|
||||
"port": 443,
|
||||
"users": [
|
||||
{
|
||||
"id": "", // 填写你的 UUID
|
||||
"encryption": "none"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"streamSettings": {
|
||||
"network": "ws",
|
||||
"security": "tls",
|
||||
"tlsSettings": {
|
||||
"serverName": "***.***.com" // edge app host 或者 cloudflare worker host
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
然后,在解压目录下,打开命令行, 输入下面命令.
|
||||
https://github.com/2dust/v2rayN
|
||||
别人的配置教程参考,https://v2raytech.com/v2rayn-config-tutorial/.
|
||||

|
||||
|
||||
> Edge Tunnel Client 会在本地启动一个 http 代理.
|
||||
## 建立 cloudflare worker (可选)
|
||||
|
||||
> 如果 window 系统提示,是否允许网络权限,请把所有允许。
|
||||
> 
|
||||
|
||||
```ps
|
||||
.\edgetunnel-win-x64.exe run --config .\config.json
|
||||
```js
|
||||
const targetHost = 'xxx.xxxx.dev'; //你的 edge function 的hostname
|
||||
addEventListener('fetch', (event) => {
|
||||
let url = new URL(event.request.url);
|
||||
url.hostname = targetHost;
|
||||
let request = new Request(url, event.request);
|
||||
event.respondWith(fetch(request));
|
||||
});
|
||||
```
|
||||
|
||||

|
||||
# FAQ
|
||||
|
||||
> 请不要关闭关闭命令行. 如果关闭,代理会自动退出.
|
||||
## 不支持 UDP
|
||||
|
||||
### 验证代理是否正常
|
||||
由于 edge 平台限制,无法转发 UDP 包。所以 DNS 策略请设置成 `Asis`.
|
||||
|
||||
再次开启一个新的命令行,测试 proxy 是否启动正常。。**注意自己 proxy 的端口**。
|
||||
## 不支持 VMESS
|
||||
|
||||
```bash
|
||||
curl -v https://www.google.com --proxy http://127.0.0.1:1081
|
||||
```
|
||||
|
||||
如果有返回结果,并且 edge tunnel 命令行有提示,说明一切成功。
|
||||
|
||||
```
|
||||
proxy to www.google.com:443 and remote return 200
|
||||
```
|
||||
|
||||
## 配置代理服务 (重要)
|
||||
|
||||
> 不像 v2rayN 可以在自动配置代理,本客户端目前需要手动配置代理才能工作。 下面三种方式可供参考。
|
||||
|
||||
### 浏览器 switchyomega 设置
|
||||
|
||||
具体安装和配置,请查看官网.
|
||||
https://proxy-switchyomega.com/proxy/
|
||||
|
||||
除了端口(port)和下图可能不一样。其他都应该是一样的。
|
||||
|
||||
> 端口是你在 config.json 自己配置的
|
||||
|
||||

|
||||
|
||||
### 系统全局 proxy 配置
|
||||
|
||||
你也可以配置 proxy 到系统级别。
|
||||
|
||||
### 其他软件 proxy 设置
|
||||
|
||||
> 电报客户端一直不停的发送 HTTP 请求,所以代理电报可能会快速消耗资源和免费额度。
|
||||
|
||||
> 下面以电报为例,其他软件也是一样的。具体方式请用搜索引擎。
|
||||
|
||||
路径, setting--> Advance-->Conntction type--> Use Custom proxy
|
||||

|
||||
VMESS 协议过于复杂,并且所有 edge 平台都支持 HTTPS, 所以无需 VMESS.
|
||||
|
||||
@@ -3,7 +3,7 @@ import { buildRawHttp500, isVaildateReq } from './helper.ts';
|
||||
const userID = Deno.env.get('UUID');
|
||||
|
||||
const handler = async (request: Request): Promise<Response> => {
|
||||
// console.log('--------start--------');
|
||||
console.log('--------start--------');
|
||||
try {
|
||||
const headers = request.headers;
|
||||
const serverAddress = headers.get('x-host') || '';
|
||||
@@ -80,4 +80,4 @@ ${userID ? 'has UUID env' : 'no UUID env'}
|
||||
}
|
||||
};
|
||||
|
||||
serve(handler, { port: 8080, hostname: '0.0.0.0' });
|
||||
serve(handler, { port: 8888, hostname: '[::]' });
|
||||
|
||||
18
apps/deno-vless/.eslintrc.json
Normal file
18
apps/deno-vless/.eslintrc.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": ["../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
16
apps/deno-vless/jest.config.ts
Normal file
16
apps/deno-vless/jest.config.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
/* eslint-disable */
|
||||
export default {
|
||||
displayName: 'deno-vless',
|
||||
preset: '../../jest.preset.js',
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
tsconfig: '<rootDir>/tsconfig.spec.json',
|
||||
},
|
||||
},
|
||||
testEnvironment: 'node',
|
||||
transform: {
|
||||
'^.+\\.[tj]s$': 'ts-jest',
|
||||
},
|
||||
moduleFileExtensions: ['ts', 'js', 'html'],
|
||||
coverageDirectory: '../../coverage/apps/deno-vless',
|
||||
};
|
||||
21
apps/deno-vless/project.json
Normal file
21
apps/deno-vless/project.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "deno-vless",
|
||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||
"sourceRoot": "apps/deno-vless/src",
|
||||
"projectType": "application",
|
||||
"targets": {
|
||||
"run": {
|
||||
"executor": "nx:run-commands",
|
||||
"options": {
|
||||
"command": "deno run --allow-net --allow-env --allow-write apps/deno-vless/src/main.ts "
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"executor": "nx:run-commands",
|
||||
"options": {
|
||||
"command": "deno run --allow-net --allow-write --allow-env --watch apps/deno-vless/src/main.ts "
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": []
|
||||
}
|
||||
0
apps/deno-vless/src/app/.gitkeep
Normal file
0
apps/deno-vless/src/app/.gitkeep
Normal file
0
apps/deno-vless/src/assets/.gitkeep
Normal file
0
apps/deno-vless/src/assets/.gitkeep
Normal file
3
apps/deno-vless/src/environments/environment.prod.ts
Normal file
3
apps/deno-vless/src/environments/environment.prod.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export const environment = {
|
||||
production: true,
|
||||
};
|
||||
3
apps/deno-vless/src/environments/environment.ts
Normal file
3
apps/deno-vless/src/environments/environment.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export const environment = {
|
||||
production: false,
|
||||
};
|
||||
194
apps/deno-vless/src/main.ts
Normal file
194
apps/deno-vless/src/main.ts
Normal file
@@ -0,0 +1,194 @@
|
||||
import { serve } from 'https://deno.land/std@0.167.0/http/server.ts';
|
||||
import { parse, stringify, validate } from 'https://jspm.dev/uuid';
|
||||
import { chunk, join } from 'https://jspm.dev/lodash-es';
|
||||
|
||||
const userID = Deno.env.get('UUID');
|
||||
|
||||
if (!validate(userID)) {
|
||||
console.log('not valid userID');
|
||||
}
|
||||
|
||||
const handler = async (req: Request): Promise<Response> => {
|
||||
const upgrade = req.headers.get('upgrade') || '';
|
||||
if (upgrade.toLowerCase() != 'websocket') {
|
||||
return new Response("request isn't trying to upgrade to websocket.");
|
||||
}
|
||||
const { socket, response } = Deno.upgradeWebSocket(req);
|
||||
let remoteConnection: Deno.TcpConn;
|
||||
let skipHeader = false;
|
||||
let address = '';
|
||||
let port = 0;
|
||||
socket.onopen = () => console.log('socket opened');
|
||||
socket.onmessage = async (e) => {
|
||||
try {
|
||||
if (!(e.data instanceof ArrayBuffer)) {
|
||||
return;
|
||||
}
|
||||
const vlessBuffer: ArrayBuffer = e.data;
|
||||
|
||||
if (remoteConnection) {
|
||||
const number = await remoteConnection.write(
|
||||
new Uint8Array(vlessBuffer)
|
||||
);
|
||||
} else {
|
||||
//https://github.com/v2ray/v2ray-core/issues/2636
|
||||
// 1 字节 16 字节 1 字节 M 字节 1 字节 2 字节 1 字节 S 字节 X 字节
|
||||
// 协议版本 等价 UUID 附加信息长度 M 附加信息 ProtoBuf 指令 端口 地址类型 地址 请求数据
|
||||
|
||||
// 1 字节 1 字节 N 字节 Y 字节
|
||||
// 协议版本,与请求的一致 附加信息长度 N 附加信息 ProtoBuf 响应数据
|
||||
if (vlessBuffer.byteLength < 24) {
|
||||
console.log('invalid data');
|
||||
return;
|
||||
}
|
||||
const version = new Uint8Array(vlessBuffer.slice(0, 1));
|
||||
let isValidUser = false;
|
||||
if (stringify(new Uint8Array(vlessBuffer.slice(1, 17))) === userID) {
|
||||
isValidUser = true;
|
||||
}
|
||||
if (!isValidUser) {
|
||||
console.log('in valid user');
|
||||
return;
|
||||
}
|
||||
|
||||
const optLength = new Uint8Array(vlessBuffer.slice(17, 18))[0];
|
||||
//skip opt for now
|
||||
|
||||
const command = new Uint8Array(
|
||||
vlessBuffer.slice(18 + optLength, 18 + optLength + 1)
|
||||
)[0];
|
||||
// 0x01 TCP
|
||||
// 0x02 UDP
|
||||
// 0x03 MUX
|
||||
if (command === 1) {
|
||||
} else {
|
||||
console.log(
|
||||
`command ${command} is not support, command 01-tcp,02-udp,03-mux`
|
||||
);
|
||||
socket.close();
|
||||
return;
|
||||
}
|
||||
const portIndex = 18 + optLength + 1;
|
||||
const portBuffer = vlessBuffer.slice(portIndex, portIndex + 2);
|
||||
// port is big-Endian in raw data etc 80 == 0x005d
|
||||
const portRemote = new DataView(portBuffer).getInt16(0);
|
||||
port = portRemote;
|
||||
let addressIndex = portIndex + 2;
|
||||
const addressBuffer = new Uint8Array(
|
||||
vlessBuffer.slice(addressIndex, addressIndex + 1)
|
||||
);
|
||||
|
||||
// 1--> ipv4 addressLength =4
|
||||
// 2--> domain name addressLength=addressBuffer[1]
|
||||
// 3--> ipv6 addressLength =16
|
||||
const addressType = addressBuffer[0];
|
||||
let addressLength = 0;
|
||||
let addressValueIndex = addressIndex + 1;
|
||||
let addressValue = '';
|
||||
switch (addressType) {
|
||||
case 1:
|
||||
addressLength = 4;
|
||||
addressValue = new Uint8Array(
|
||||
vlessBuffer.slice(
|
||||
addressValueIndex,
|
||||
addressValueIndex + addressLength
|
||||
)
|
||||
).join('.');
|
||||
break;
|
||||
case 2:
|
||||
addressLength = new Uint8Array(
|
||||
vlessBuffer.slice(addressValueIndex, addressValueIndex + 1)
|
||||
)[0];
|
||||
addressValueIndex += 1;
|
||||
addressValue = new TextDecoder().decode(
|
||||
vlessBuffer.slice(
|
||||
addressValueIndex,
|
||||
addressValueIndex + addressLength
|
||||
)
|
||||
);
|
||||
break;
|
||||
case 3:
|
||||
addressLength = 16;
|
||||
const addressChunkBy2: number[][] = chunk(
|
||||
new Uint8Array(
|
||||
vlessBuffer.slice(
|
||||
addressValueIndex,
|
||||
addressValueIndex + addressLength
|
||||
)
|
||||
),
|
||||
2,
|
||||
null
|
||||
);
|
||||
// 2001:0db8:85a3:0000:0000:8a2e:0370:7334
|
||||
addressValue = addressChunkBy2
|
||||
.map((items) =>
|
||||
items.map((item) => item.toString(16).padStart(2, '0')).join('')
|
||||
)
|
||||
.join('.');
|
||||
break;
|
||||
default:
|
||||
console.log(`[${address}:${port}] invild address`);
|
||||
}
|
||||
address = addressValue;
|
||||
if (!addressValue) {
|
||||
console.log(`[${address}:${port}] addressValue is empty`);
|
||||
socket.close();
|
||||
return;
|
||||
}
|
||||
// const addressType = requestAddr >> 4;
|
||||
// const addressLength = requestAddr & 0x0f;
|
||||
console.log(`[${address}:${port}] connecting`);
|
||||
remoteConnection = await Deno.connect({
|
||||
port: port,
|
||||
hostname: addressValue,
|
||||
});
|
||||
|
||||
const rawDataIndex = addressValueIndex + addressLength;
|
||||
const rawClientData = vlessBuffer.slice(rawDataIndex);
|
||||
await remoteConnection.write(new Uint8Array(rawClientData));
|
||||
|
||||
let chunkDatas = [new Uint8Array([version[0], 0])];
|
||||
remoteConnection.readable
|
||||
.pipeTo(
|
||||
new WritableStream({
|
||||
start() {
|
||||
socket.send(new Blob(chunkDatas));
|
||||
},
|
||||
write(chunk, controller) {
|
||||
socket.send(new Blob([chunk]));
|
||||
// if (!skipHeader) {
|
||||
// console.log(
|
||||
// `[${address}:${port}] first time write to client socket`
|
||||
// );
|
||||
// chunkDatas.push(chunk);
|
||||
// socket.send(new Blob(chunkDatas));
|
||||
// chunkDatas = [];
|
||||
// } else {
|
||||
// socket.send(new Blob([chunk]));
|
||||
// }
|
||||
},
|
||||
})
|
||||
)
|
||||
.catch((error) => {
|
||||
console.log(
|
||||
`[${address}:${port}] remoteConnection pipe to has error`,
|
||||
error
|
||||
);
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
// console.log(
|
||||
// [...new Uint8Array(vlessBuffer.slice(0, 32))].map((x) =>
|
||||
// x.toString(16).padStart(2, '0')
|
||||
// )
|
||||
// );
|
||||
console.log(`[${address}:${port}] request hadler has error`, error);
|
||||
}
|
||||
};
|
||||
socket.onerror = (e) =>
|
||||
console.log(`[${address}:${port}] socket errored:`, e);
|
||||
socket.onclose = () => console.log(`[${address}:${port}] socket closed`);
|
||||
return response;
|
||||
};
|
||||
|
||||
serve(handler, { port: 8080, hostname: '0.0.0.0' });
|
||||
10
apps/deno-vless/tsconfig.app.json
Normal file
10
apps/deno-vless/tsconfig.app.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"module": "commonjs",
|
||||
"types": ["node"]
|
||||
},
|
||||
"exclude": ["jest.config.ts", "**/*.spec.ts", "**/*.test.ts"],
|
||||
"include": ["**/*.ts"]
|
||||
}
|
||||
13
apps/deno-vless/tsconfig.json
Normal file
13
apps/deno-vless/tsconfig.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
9
apps/deno-vless/tsconfig.spec.json
Normal file
9
apps/deno-vless/tsconfig.spec.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"module": "commonjs",
|
||||
"types": ["jest", "node"]
|
||||
},
|
||||
"include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"]
|
||||
}
|
||||
BIN
doc/v2rayn.jpg
Normal file
BIN
doc/v2rayn.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 61 KiB |
18
libs/vless-js/.eslintrc.json
Normal file
18
libs/vless-js/.eslintrc.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": ["../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
11
libs/vless-js/README.md
Normal file
11
libs/vless-js/README.md
Normal file
@@ -0,0 +1,11 @@
|
||||
# vless-js
|
||||
|
||||
This library was generated with [Nx](https://nx.dev).
|
||||
|
||||
## Building
|
||||
|
||||
Run `nx build vless-js` to build the library.
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `nx test vless-js` to execute the unit tests via [Jest](https://jestjs.io).
|
||||
15
libs/vless-js/jest.config.ts
Normal file
15
libs/vless-js/jest.config.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
/* eslint-disable */
|
||||
export default {
|
||||
displayName: 'vless-js',
|
||||
preset: '../../jest.preset.js',
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
tsconfig: '<rootDir>/tsconfig.spec.json',
|
||||
},
|
||||
},
|
||||
transform: {
|
||||
'^.+\\.[tj]s$': 'ts-jest',
|
||||
},
|
||||
moduleFileExtensions: ['ts', 'js', 'html'],
|
||||
coverageDirectory: '../../coverage/libs/vless-js',
|
||||
};
|
||||
5
libs/vless-js/package.json
Normal file
5
libs/vless-js/package.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "vless-js",
|
||||
"version": "0.0.1",
|
||||
"type": "commonjs"
|
||||
}
|
||||
41
libs/vless-js/project.json
Normal file
41
libs/vless-js/project.json
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "vless-js",
|
||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||
"sourceRoot": "libs/vless-js/src",
|
||||
"projectType": "library",
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "@nrwl/js:tsc",
|
||||
"outputs": ["{options.outputPath}"],
|
||||
"options": {
|
||||
"outputPath": "dist/libs/vless-js",
|
||||
"main": "libs/vless-js/src/index.ts",
|
||||
"tsConfig": "libs/vless-js/tsconfig.lib.json",
|
||||
"assets": ["libs/vless-js/*.md"]
|
||||
}
|
||||
},
|
||||
"publish": {
|
||||
"executor": "nx:run-commands",
|
||||
"options": {
|
||||
"command": "node tools/scripts/publish.mjs vless-js {args.ver} {args.tag}"
|
||||
},
|
||||
"dependsOn": ["build"]
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nrwl/linter:eslint",
|
||||
"outputs": ["{options.outputFile}"],
|
||||
"options": {
|
||||
"lintFilePatterns": ["libs/vless-js/**/*.ts"]
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"executor": "@nrwl/jest:jest",
|
||||
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
|
||||
"options": {
|
||||
"jestConfig": "libs/vless-js/jest.config.ts",
|
||||
"passWithNoTests": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": []
|
||||
}
|
||||
1
libs/vless-js/src/index.ts
Normal file
1
libs/vless-js/src/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './lib/vless-js';
|
||||
7
libs/vless-js/src/lib/vless-js.spec.ts
Normal file
7
libs/vless-js/src/lib/vless-js.spec.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { vlessJs } from './vless-js';
|
||||
|
||||
describe('vlessJs', () => {
|
||||
it('should work', () => {
|
||||
expect(vlessJs()).toEqual('vless-js');
|
||||
});
|
||||
});
|
||||
3
libs/vless-js/src/lib/vless-js.ts
Normal file
3
libs/vless-js/src/lib/vless-js.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export function vlessJs(): string {
|
||||
return 'vless-js';
|
||||
}
|
||||
22
libs/vless-js/tsconfig.json
Normal file
22
libs/vless-js/tsconfig.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"noImplicitOverride": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
10
libs/vless-js/tsconfig.lib.json
Normal file
10
libs/vless-js/tsconfig.lib.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"declaration": true,
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": ["**/*.ts"],
|
||||
"exclude": ["jest.config.ts", "**/*.spec.ts", "**/*.test.ts"]
|
||||
}
|
||||
9
libs/vless-js/tsconfig.spec.json
Normal file
9
libs/vless-js/tsconfig.spec.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"module": "commonjs",
|
||||
"types": ["jest", "node"]
|
||||
},
|
||||
"include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"]
|
||||
}
|
||||
61
tools/scripts/publish.mjs
Normal file
61
tools/scripts/publish.mjs
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* This is a minimal script to publish your package to "npm".
|
||||
* This is meant to be used as-is or customize as you see fit.
|
||||
*
|
||||
* This script is executed on "dist/path/to/library" as "cwd" by default.
|
||||
*
|
||||
* You might need to authenticate with NPM before running this script.
|
||||
*/
|
||||
|
||||
import { readCachedProjectGraph } from '@nrwl/devkit';
|
||||
import { execSync } from 'child_process';
|
||||
import { readFileSync, writeFileSync } from 'fs';
|
||||
import chalk from 'chalk';
|
||||
|
||||
function invariant(condition, message) {
|
||||
if (!condition) {
|
||||
console.error(chalk.bold.red(message));
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Executing publish script: node path/to/publish.mjs {name} --version {version} --tag {tag}
|
||||
// Default "tag" to "next" so we won't publish the "latest" tag by accident.
|
||||
const [, , name, version, tag = 'next'] = process.argv;
|
||||
|
||||
// A simple SemVer validation to validate the version
|
||||
const validVersion = /^\d+\.\d+\.\d+(-\w+\.\d+)?/;
|
||||
invariant(
|
||||
version && validVersion.test(version),
|
||||
`No version provided or version did not match Semantic Versioning, expected: #.#.#-tag.# or #.#.#, got ${version}.`
|
||||
);
|
||||
|
||||
const graph = readCachedProjectGraph();
|
||||
const project = graph.nodes[name];
|
||||
|
||||
invariant(
|
||||
project,
|
||||
`Could not find project "${name}" in the workspace. Is the project.json configured correctly?`
|
||||
);
|
||||
|
||||
const outputPath = project.data?.targets?.build?.options?.outputPath;
|
||||
invariant(
|
||||
outputPath,
|
||||
`Could not find "build.options.outputPath" of project "${name}". Is project.json configured correctly?`
|
||||
);
|
||||
|
||||
process.chdir(outputPath);
|
||||
|
||||
// Updating the version in "package.json" before publishing
|
||||
try {
|
||||
const json = JSON.parse(readFileSync(`package.json`).toString());
|
||||
json.version = version;
|
||||
writeFileSync(`package.json`, JSON.stringify(json, null, 2));
|
||||
} catch (e) {
|
||||
console.error(
|
||||
chalk.bold.red(`Error reading package.json file from library build output.`)
|
||||
);
|
||||
}
|
||||
|
||||
// Execute "npm publish" to publish
|
||||
execSync(`npm publish --access public --tag ${tag}`);
|
||||
@@ -15,7 +15,8 @@
|
||||
"skipDefaultLibCheck": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@edge-bypass/test": ["libs/test/src/index.ts"]
|
||||
"@edge-bypass/test": ["libs/test/src/index.ts"],
|
||||
"vless-js": ["libs/vless-js/src/index.ts"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules", "tmp"]
|
||||
|
||||
Reference in New Issue
Block a user