ソースを参照

Refactor: refine writing strategy

SukkaW 1 年間 前
コミット
2035f5ea96

+ 9 - 6
Build/lib/rules/base.ts

@@ -8,7 +8,7 @@ import { fastStringArrayJoin } from 'foxts/fast-string-array-join';
 import { readFileByLine } from '../fetch-text-by-line';
 import { asyncWriteToStream } from 'foxts/async-write-to-stream';
 import type { BaseWriteStrategy } from '../writing-strategy/base';
-import { merge } from 'fast-cidr-tools';
+import { merge as mergeCidr } from 'fast-cidr-tools';
 import { createRetrieKeywordFilter as createKeywordFilter } from 'foxts/retrie';
 import path from 'node:path';
 import { SurgeMitmSgmodule } from '../writing-strategy/surge';
@@ -369,10 +369,10 @@ export class FileOutput {
     let ipcidr6NoResolve: string[] | null = null;
 
     if (this.ipcidr.size) {
-      ipcidr = merge(Array.from(this.ipcidr), true);
+      ipcidr = mergeCidr(Array.from(this.ipcidr), true);
     }
     if (this.ipcidrNoResolve.size) {
-      ipcidrNoResolve = merge(Array.from(this.ipcidrNoResolve), true);
+      ipcidrNoResolve = mergeCidr(Array.from(this.ipcidrNoResolve), true);
     }
     if (this.ipcidr6.size) {
       ipcidr6 = Array.from(this.ipcidr6);
@@ -433,9 +433,12 @@ export class FileOutput {
             this.title,
             this.description,
             this.date,
-            strategy.type
-              ? path.join(strategy.type, basename)
-              : basename
+            path.join(
+              strategy.outputDir,
+              strategy.type
+                ? path.join(strategy.type, basename)
+                : basename
+            )
           ));
         }
       }

+ 1 - 3
Build/lib/rules/domainset.ts

@@ -7,12 +7,10 @@ import { SurgeDomainSet } from '../writing-strategy/surge';
 import { FileOutput } from './base';
 
 export class DomainsetOutput extends FileOutput {
-  protected type = 'domainset' as const;
-
   strategies: Array<false | BaseWriteStrategy> = [
     new SurgeDomainSet(),
     new ClashDomainSet(),
-    new SingboxSource(this.type)
+    new SingboxSource('domainset')
   ];
 }
 

+ 3 - 4
Build/lib/rules/ip.ts

@@ -6,16 +6,15 @@ import { SurgeRuleSet } from '../writing-strategy/surge';
 import { FileOutput } from './base';
 
 export class IPListOutput extends FileOutput {
-  protected type = 'ip' as const;
   strategies: Array<false | BaseWriteStrategy>;
 
   constructor(span: Span, id: string, private readonly clashUseRule = true) {
     super(span, id);
 
     this.strategies = [
-      new SurgeRuleSet(this.type),
-      this.clashUseRule ? new ClashClassicRuleSet(this.type) : new ClashIPSet(),
-      new SingboxSource(this.type)
+      new SurgeRuleSet('ip'),
+      this.clashUseRule ? new ClashClassicRuleSet('ip') : new ClashIPSet(),
+      new SingboxSource('ip')
     ];
   }
 }

+ 8 - 8
Build/lib/rules/ruleset.ts

@@ -5,13 +5,13 @@ import { SurgeRuleSet } from '../writing-strategy/surge';
 import { FileOutput } from './base';
 
 export class RulesetOutput extends FileOutput {
-  constructor(span: Span, id: string, protected type: 'non_ip' | 'ip' | (string & {})) {
+  constructor(span: Span, id: string, type: 'non_ip' | 'ip') {
     super(span, id);
 
     this.strategies = [
-      new SurgeRuleSet(this.type),
-      new ClashClassicRuleSet(this.type),
-      new SingboxSource(this.type)
+      new SurgeRuleSet(type),
+      new ClashClassicRuleSet(type),
+      new SingboxSource(type)
     ];
   }
 }
@@ -20,13 +20,13 @@ export class SurgeOnlyRulesetOutput extends FileOutput {
   constructor(
     span: Span,
     id: string,
-    protected type: 'non_ip' | 'ip' | (string & {}),
+    type: 'non_ip' | 'ip' | (string & {}),
     overrideOutputDir?: string
   ) {
     super(span, id);
 
     this.strategies = [
-      new SurgeRuleSet(this.type, overrideOutputDir)
+      new SurgeRuleSet(type, overrideOutputDir)
     ];
   }
 }
@@ -35,12 +35,12 @@ export class ClashOnlyRulesetOutput extends FileOutput {
   constructor(
     span: Span,
     id: string,
-    protected type: 'non_ip' | 'ip' | (string & {})
+    type: 'non_ip' | 'ip'
   ) {
     super(span, id);
 
     this.strategies = [
-      new ClashClassicRuleSet(this.type)
+      new ClashClassicRuleSet(type)
     ];
   }
 }

+ 6 - 8
Build/lib/writing-strategy/base.ts

@@ -1,15 +1,13 @@
-import path from 'node:path';
 import type { Span } from '../../trace';
 import { compareAndWriteFile } from '../create-file';
 
 export abstract class BaseWriteStrategy {
-  // abstract readonly type: 'domainset' | 'non_ip' | 'ip' | (string & {});
   public overwriteFilename: string | null = null;
   public abstract readonly type: 'domainset' | 'non_ip' | 'ip' | (string & {});
 
   abstract readonly fileExtension: 'conf' | 'txt' | 'json' | (string & {});
 
-  constructor(protected outputDir: string) {}
+  constructor(public readonly outputDir: string) {}
 
   protected abstract result: string[] | null;
 
@@ -51,14 +49,14 @@ export abstract class BaseWriteStrategy {
     return result;
   };
 
-  abstract withPadding(title: string, description: string[] | readonly string[], date: Date, content: string[]): string[];
+  protected abstract withPadding(title: string, description: string[] | readonly string[], date: Date, content: string[]): string[];
 
-  output(
+  public output(
     span: Span,
     title: string,
     description: string[] | readonly string[],
     date: Date,
-    relativePath: string
+    filePath: string
   ): void | Promise<void> {
     if (!this.result) {
       return;
@@ -71,11 +69,11 @@ export abstract class BaseWriteStrategy {
         date,
         this.result
       ),
-      path.join(this.outputDir, relativePath)
+      filePath
     );
   };
 
-  get content() {
+  public get content() {
     return this.result;
   }
 }

+ 3 - 3
Build/lib/writing-strategy/clash.ts

@@ -12,7 +12,7 @@ export class ClashDomainSet extends BaseWriteStrategy {
 
   protected result: string[] = ['this_ruleset_is_made_by_sukkaw.ruleset.skk.moe'];
 
-  constructor(protected outputDir = OUTPUT_CLASH_DIR) {
+  constructor(public readonly outputDir = OUTPUT_CLASH_DIR) {
     super(outputDir);
   }
 
@@ -49,7 +49,7 @@ export class ClashIPSet extends BaseWriteStrategy {
 
   protected result: string[] = [];
 
-  constructor(protected outputDir = OUTPUT_CLASH_DIR) {
+  constructor(public readonly outputDir = OUTPUT_CLASH_DIR) {
     super(outputDir);
   }
 
@@ -84,7 +84,7 @@ export class ClashClassicRuleSet extends BaseWriteStrategy {
 
   protected result: string[] = ['DOMAIN,this_ruleset_is_made_by_sukkaw.ruleset.skk.moe'];
 
-  constructor(public readonly type: string, protected outputDir = OUTPUT_CLASH_DIR) {
+  constructor(public readonly type: 'ip' | 'non_ip' /* | (string & {}) */, public readonly outputDir = OUTPUT_CLASH_DIR) {
     super(outputDir);
   }
 

+ 5 - 1
Build/lib/writing-strategy/singbox.ts

@@ -42,7 +42,11 @@ export class SingboxSource extends BaseWriteStrategy {
     });
   }
 
-  constructor(public type: string, protected outputDir = OUTPUT_SINGBOX_DIR) {
+  constructor(
+    /** Since sing-box only have one format that does not reflect type, we need to specify it */
+    public type: 'domainset' | 'non_ip' | 'ip' /* | (string & {}) */,
+    public readonly outputDir = OUTPUT_SINGBOX_DIR
+  ) {
     super(outputDir);
   }
 

+ 6 - 2
Build/lib/writing-strategy/surge.ts

@@ -50,7 +50,11 @@ export class SurgeRuleSet extends BaseWriteStrategy {
 
   protected result: string[] = ['DOMAIN,this_ruleset_is_made_by_sukkaw.ruleset.skk.moe'];
 
-  constructor(public readonly type: string, outputDir = OUTPUT_SURGE_DIR) {
+  constructor(
+    /** Surge RULE-SET can be both ip or non_ip, so this needs to be specified */
+    public readonly type: 'ip' | 'non_ip' | (string & {}),
+    public readonly outputDir = OUTPUT_SURGE_DIR
+  ) {
     super(outputDir);
   }
 
@@ -130,7 +134,7 @@ export class SurgeRuleSet extends BaseWriteStrategy {
 export class SurgeMitmSgmodule extends BaseWriteStrategy {
   // readonly type = 'domainset';
   readonly fileExtension = 'sgmodule';
-  type = '';
+  readonly type = '';
 
   private rules = new Set<string>();