From ac81dc4722f906dd0594d11ec5b0c3c5fb412e34 Mon Sep 17 00:00:00 2001 From: Roy Li Date: Thu, 20 Apr 2023 12:38:56 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20defineProvider=20=E5=92=8C=20defineSurg?= =?UTF-8?q?ioConfig?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.d.ts | 1 + internal.d.ts | 1 + package.json | 12 ++-------- src/constant/constant.ts | 26 +++++++++++---------- src/index.ts | 12 +++++----- src/internal.ts | 3 ++- src/provider/Provider.ts | 2 +- src/provider/index.ts | 29 ++++++++++++++++------- src/types.ts | 47 +++++++++++++++++++++++++++++++------- src/utils/configurables.ts | 9 ++++++++ src/validators/provider.ts | 4 ++++ 11 files changed, 100 insertions(+), 46 deletions(-) create mode 100644 index.d.ts create mode 100644 internal.d.ts create mode 100644 src/utils/configurables.ts diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 000000000..b8c634785 --- /dev/null +++ b/index.d.ts @@ -0,0 +1 @@ +export * from './build/index'; diff --git a/internal.d.ts b/internal.d.ts new file mode 100644 index 000000000..79ccc0a3d --- /dev/null +++ b/internal.d.ts @@ -0,0 +1 @@ +export * from './build/internal'; diff --git a/package.json b/package.json index 0ecfd749a..a0b6fce44 100644 --- a/package.json +++ b/package.json @@ -2,16 +2,8 @@ "name": "surgio", "description": "Generating rules for Surge, Clash, Quantumult like a PRO", "version": "2.25.0", - "exports": { - ".": { - "types": "./build/index.d.ts", - "require": "./build/index.js" - }, - "./internal": { - "types": "./build/internal.d.ts", - "require": "./build/internal.js" - } - }, + "main": "./build/index.js", + "types": "./build/index.d.ts", "bin": { "surgio": "bin/run" }, diff --git a/src/constant/constant.ts b/src/constant/constant.ts index ed8804f2a..7caf62da0 100644 --- a/src/constant/constant.ts +++ b/src/constant/constant.ts @@ -7,9 +7,11 @@ export const OBFS_UA = export const PROXY_TEST_URL = 'http://cp.cloudflare.com/generate_204'; +export const INTERNET_TEST_URL = 'http://connect.rom.miui.com/generate_204'; + export const PROXY_TEST_INTERVAL = 1200; // 1200s -export const CLASH_SUPPORTED_RULE: ReadonlyArray = [ +export const CLASH_SUPPORTED_RULE = [ 'DOMAIN-SUFFIX', 'DOMAIN-KEYWORD', 'DOMAIN', @@ -22,9 +24,9 @@ export const CLASH_SUPPORTED_RULE: ReadonlyArray = [ 'MATCH', 'FINAL', 'PROCESS-NAME', -]; +] as const; -export const QUANTUMULT_X_SUPPORTED_RULE: ReadonlyArray = [ +export const QUANTUMULT_X_SUPPORTED_RULE = [ 'USER-AGENT', 'HOST', 'HOST-KEYWORD', @@ -36,10 +38,10 @@ export const QUANTUMULT_X_SUPPORTED_RULE: ReadonlyArray = [ 'IP-CIDR6', 'GEOIP', 'FINAL', -]; +] as const; // @see https://www.notion.so/2-967c1a07462c43ab88906162bec475a4 -export const LOON_SUPPORTED_RULE: ReadonlyArray = [ +export const LOON_SUPPORTED_RULE = [ 'DOMAIN-SUFFIX', 'DOMAIN', 'DOMAIN-KEYWORD', @@ -48,9 +50,9 @@ export const LOON_SUPPORTED_RULE: ReadonlyArray = [ 'IP-CIDR', 'GEOIP', 'FINAL', -]; +] as const; -export const MELLOW_UNSUPPORTED_RULE: ReadonlyArray = [ +export const MELLOW_UNSUPPORTED_RULE = [ 'URL-REGEX', 'USER-AGENT', 'AND', @@ -60,10 +62,10 @@ export const MELLOW_UNSUPPORTED_RULE: ReadonlyArray = [ 'IN-PORT', 'SRC-IP', 'RULE-SET', -]; +] as const; // @see https://getsurfboard.com/docs/profile-format/rule/ -export const SURFBOARD_SUPPORTED_RULE: ReadonlyArray = [ +export const SURFBOARD_SUPPORTED_RULE = [ 'DOMAIN-SUFFIX', 'DOMAIN', 'DOMAIN-KEYWORD', @@ -74,7 +76,7 @@ export const SURFBOARD_SUPPORTED_RULE: ReadonlyArray = [ 'PROCESS-NAME', 'RULE-SET', 'DOMAIN-SET', -]; +] as const; export const CATEGORIES = { SNIPPET: 'Snippet', @@ -86,7 +88,7 @@ export const CATEGORIES = { CLASH: 'Clash', LOON: 'Loon', SURFBOARD: 'Surfboard', -}; +} as const; export const RELAY_SERVICE = 'https://surgio-cors.herokuapp.com/'; @@ -95,4 +97,4 @@ export const TMP_FOLDER_NAME = 'surgio-config'; export const CACHE_KEYS = { RemoteSnippets: 'remote-snippets', Provider: 'provider', -}; +} as const; diff --git a/src/index.ts b/src/index.ts index a012ec4e4..fcb29c230 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,3 @@ -import fs from 'fs-extra'; -import { join } from 'path'; import { PackageJson } from 'type-fest'; import { @@ -15,11 +13,13 @@ import { isVercel, } from './utils'; import * as filter from './utils/filter'; -import * as caches from './utils/cache'; import { CATEGORIES } from './constant'; -import redis from './redis'; -const pkg = fs.readJSONSync(join(__dirname, '../package.json')) as PackageJson; +export type { CommandConfigBeforeNormalize as SurgioConfig } from './types'; +export * as caches from './utils/cache'; +export * from './utils/configurables'; + +const pkg = require('../package.json') as PackageJson; export const utils = { ...filter, @@ -39,4 +39,4 @@ export const categories = { ...CATEGORIES, }; -export { pkg, caches, redis }; +export { pkg }; diff --git a/src/internal.ts b/src/internal.ts index 19795a526..cc78e7a21 100644 --- a/src/internal.ts +++ b/src/internal.ts @@ -1,7 +1,8 @@ import { loadConfig, setConfig, getConfig } from './utils/config'; import { loadRemoteSnippetList } from './utils/remote-snippet'; -export * as types from './types'; +export * as redis from './redis'; +export * from './types'; const utils = { loadRemoteSnippetList, diff --git a/src/provider/Provider.ts b/src/provider/Provider.ts index 99bb93fa3..73be9f6c9 100644 --- a/src/provider/Provider.ts +++ b/src/provider/Provider.ts @@ -39,7 +39,7 @@ export default abstract class Provider { } this.supportGetSubscriptionUserInfo = false; - this.config = result.data; + this.config = result.data as ProviderConfig; } static async requestCacheableResource( diff --git a/src/provider/index.ts b/src/provider/index.ts index a51c9bb90..f6a9a90c2 100644 --- a/src/provider/index.ts +++ b/src/provider/index.ts @@ -1,4 +1,5 @@ -import { SupportProviderEnum } from '../types'; +import { PossibleProviderConfigType, SupportProviderEnum } from '../types'; +import { defineProvider } from '../utils/configurables'; import BlackSSLProvider from './BlackSSLProvider'; import ClashProvider from './ClashProvider'; import CustomProvider from './CustomProvider'; @@ -7,16 +8,29 @@ import ShadowsocksrSubscribeProvider from './ShadowsocksrSubscribeProvider'; import ShadowsocksSubscribeProvider from './ShadowsocksSubscribeProvider'; import SsdProvider from './SsdProvider'; import TrojanProvider from './TrojanProvider'; -import { PossibleProviderType } from './types'; import V2rayNSubscribeProvider from './V2rayNSubscribeProvider'; +import { PossibleProviderType } from './types'; + +export { + BlackSSLProvider, + ClashProvider, + CustomProvider, + ShadowsocksJsonSubscribeProvider, + ShadowsocksrSubscribeProvider, + ShadowsocksSubscribeProvider, + SsdProvider, + TrojanProvider, + V2rayNSubscribeProvider, +}; + +export type { PossibleProviderType }; export async function getProvider( name: string, - config: any, + config: ReturnType | PossibleProviderConfigType, ): Promise { - // 函数形式,需要先获取到返回值 if (typeof config === 'function') { - config = await config(); + config = await config({}); } switch (config.type) { @@ -32,9 +46,8 @@ export async function getProvider( case SupportProviderEnum.ShadowsocksrSubscribe: return new ShadowsocksrSubscribeProvider(name, config); - case SupportProviderEnum.Custom: { + case SupportProviderEnum.Custom: return new CustomProvider(name, config); - } case SupportProviderEnum.V2rayNSubscribe: return new V2rayNSubscribeProvider(name, config); @@ -49,6 +62,6 @@ export async function getProvider( return new TrojanProvider(name, config); default: - throw new Error(`Unsupported provider type: ${config.type}`); + throw new Error(`Unsupported provider type: ${(config as any).type}`); } } diff --git a/src/types.ts b/src/types.ts index bd83f09b0..d44c79f3a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,4 +1,5 @@ import { z } from 'zod'; +import { PossibleProviderType } from './provider'; import Provider from './provider/Provider'; import { @@ -48,7 +49,10 @@ export type CommandConfigBeforeNormalize = z.infer< typeof SurgioConfigValidator >; -export type CommandConfig = CommandConfigBeforeNormalize & { +export type CommandConfig = Omit< + CommandConfigBeforeNormalize, + 'customFilters' +> & { publicUrl: string; output: string; urlBase: string; @@ -71,36 +75,44 @@ export type ArtifactConfig = z.infer & { readonly template: string | undefined; }; -export type ProviderConfig = z.infer & { - readonly nodeFilter?: NodeFilterType | SortedNodeNameFilterType; - readonly netflixFilter?: NodeNameFilterType | SortedNodeNameFilterType; - readonly youtubePremiumFilter?: NodeNameFilterType | SortedNodeNameFilterType; - readonly customFilters?: { - readonly [name: string]: NodeNameFilterType | SortedNodeNameFilterType; +export type ProviderConfig = Omit< + z.infer, + 'nodeFilter' | 'netflixFilter' | 'youtubePremiumFilter' | 'customFilters' +> & { + nodeFilter?: NodeFilterType | SortedNodeNameFilterType; + netflixFilter?: NodeNameFilterType | SortedNodeNameFilterType; + youtubePremiumFilter?: NodeNameFilterType | SortedNodeNameFilterType; + customFilters?: { + [name: string]: NodeNameFilterType | SortedNodeNameFilterType; }; }; export interface BlackSSLProviderConfig extends ProviderConfig { + readonly type: SupportProviderEnum.BlackSSL; readonly username: string; readonly password: string; } export interface ShadowsocksJsonSubscribeProviderConfig extends ProviderConfig { + readonly type: SupportProviderEnum.ShadowsocksJsonSubscribe; readonly url: string; readonly udpRelay?: boolean; } export interface ShadowsocksSubscribeProviderConfig extends ProviderConfig { + readonly type: SupportProviderEnum.ShadowsocksSubscribe; readonly url: string; readonly udpRelay?: boolean; } export interface ShadowsocksrSubscribeProviderConfig extends ProviderConfig { + readonly type: SupportProviderEnum.ShadowsocksrSubscribe; readonly url: string; readonly udpRelay?: boolean; } export interface V2rayNSubscribeProviderConfig extends ProviderConfig { + readonly type: SupportProviderEnum.V2rayNSubscribe; readonly url: string; readonly compatibleMode?: boolean; readonly skipCertVerify?: boolean; @@ -109,21 +121,25 @@ export interface V2rayNSubscribeProviderConfig extends ProviderConfig { } export interface ClashProviderConfig extends ProviderConfig { + readonly type: SupportProviderEnum.Clash; readonly url: string; readonly udpRelay?: boolean; readonly tls13?: boolean; } export interface SsdProviderConfig extends ProviderConfig { + readonly type: SupportProviderEnum.Ssd; readonly url: string; readonly udpRelay?: boolean; } export interface CustomProviderConfig extends ProviderConfig { - readonly nodeList: ReadonlyArray; + readonly type: SupportProviderEnum.Custom; + readonly nodeList: ReadonlyArray; } export interface TrojanProviderConfig extends ProviderConfig { + readonly type: SupportProviderEnum.Trojan; readonly url: string; readonly udpRelay?: boolean; readonly tls13?: boolean; @@ -208,3 +224,18 @@ export type PossibleNodeConfigType = | Socks5NodeConfig | TuicNodeConfig | WireguardNodeConfig; + +export type PossibleProviderConfigType = + | BlackSSLProviderConfig + | ClashProviderConfig + | CustomProviderConfig + | ShadowsocksJsonSubscribeProviderConfig + | ShadowsocksrSubscribeProviderConfig + | ShadowsocksSubscribeProviderConfig + | SsdProviderConfig + | TrojanProviderConfig + | V2rayNSubscribeProviderConfig; + +export type ProviderConfigFactory = ( + options: Record, +) => Promise | PossibleProviderConfigType; diff --git a/src/utils/configurables.ts b/src/utils/configurables.ts new file mode 100644 index 000000000..3be671069 --- /dev/null +++ b/src/utils/configurables.ts @@ -0,0 +1,9 @@ +import { CommandConfigBeforeNormalize, ProviderConfigFactory } from '../types'; +import { PossibleProviderConfigType } from '../types'; + +export const defineSurgioConfig = (config: CommandConfigBeforeNormalize) => + config; + +export const defineProvider = ( + config: PossibleProviderConfigType | ProviderConfigFactory, +) => config; diff --git a/src/validators/provider.ts b/src/validators/provider.ts index 42f737062..f5e4f16ec 100644 --- a/src/validators/provider.ts +++ b/src/validators/provider.ts @@ -12,4 +12,8 @@ export const ProviderValidator = z.object({ relayUrl: z.union([z.boolean(), z.string().url()]).optional(), requestUserAgent: z.ostring(), renameNode: z.function().args(z.string()).returns(z.string()).optional(), + customFilters: z.record(z.function()).optional(), + nodeFilter: z.function().optional(), + netflixFilter: z.function().optional(), + youtubePremiumFilter: z.function().optional(), });