1
+ import { type ByteRange } from '@adguard/tsurlfilter' ;
2
+ import {
3
+ METADATA_RULESET_ID ,
4
+ MetadataRuleSet ,
5
+ RuleSetByteRangeCategory ,
6
+ } from '@adguard/tsurlfilter/es/declarative-converter' ;
7
+ import { extractRuleSetId , getRuleSetId , getRuleSetPath } from '@adguard/tsurlfilter/es/declarative-converter-utils' ;
1
8
import fs from 'fs' ;
2
9
import path from 'path' ;
3
10
4
11
import { version } from '../package.json' ;
5
12
import { DEST_RULE_SETS_DIR } from './constants' ;
6
13
7
- // TODO: import METADATA_FILENAME from tsurlfilter/declarative-converter
8
- // and resolve transpile issue related to its import
9
- const METADATA_FILENAME = 'metadata.json' ;
10
-
11
14
/**
12
15
* File name where old validator data is stored.
13
16
*/
@@ -35,6 +38,42 @@ type RulesetIdsAndMetadataKeys = {
35
38
rulesetMetadataKeys : string [ ] ;
36
39
} ;
37
40
41
+ /**
42
+ * Retrieves metadata ruleset.
43
+ *
44
+ * @param destDir Directory with declarative rulesets.
45
+ *
46
+ * @returns Metadata ruleset.
47
+ *
48
+ * @throws Error if metadata ruleset is not found.
49
+ */
50
+ const getMetadataRuleset = ( destDir : string ) : MetadataRuleSet => {
51
+ const metadataRuleSetPath = getRuleSetPath ( METADATA_RULESET_ID , destDir ) ;
52
+
53
+ if ( ! fs . existsSync ( metadataRuleSetPath ) ) {
54
+ throw new Error ( `Metadata ruleset not found at ${ metadataRuleSetPath } ` ) ;
55
+ }
56
+
57
+ const metadataRulesetContent = fs . readFileSync ( metadataRuleSetPath , { encoding : 'utf-8' } ) ;
58
+
59
+ return MetadataRuleSet . deserialize ( metadataRulesetContent ) ;
60
+ } ;
61
+
62
+ /**
63
+ * Node.js specific function that reads the specified range of bytes from the file.
64
+ *
65
+ * @param filePath Path to the file.
66
+ * @param range Range of bytes to read.
67
+ *
68
+ * @returns Buffer with the read data.
69
+ */
70
+ const readFileRange = async ( filePath : string , range : ByteRange ) : Promise < Buffer > => {
71
+ const file = await fs . promises . open ( filePath , 'r' ) ;
72
+ const buffer = Buffer . alloc ( range . end - range . start + 1 ) ;
73
+ await file . read ( buffer , 0 , buffer . length , range . start ) ;
74
+ return buffer ;
75
+ } ;
76
+
38
77
/**
39
78
* Retrieves data needed for rulesets validation — rulesets ids and metadata keys.
40
79
*
@@ -44,24 +83,43 @@ type RulesetIdsAndMetadataKeys = {
44
83
*/
45
84
const getValidatorData = async ( destDir : string ) : Promise < RulesetIdsAndMetadataKeys > => {
46
85
const rulesetIds : number [ ] = [ ] ;
47
- const rulesetMetadataKeys = [ ] ;
86
+ const rulesetMetadataKeys : string [ ] = [ ] ;
87
+
88
+ const metadataRuleSet = getMetadataRuleset ( destDir ) ;
48
89
49
90
const destDirItems = await fs . promises . readdir ( destDir , { withFileTypes : true } ) ;
50
91
51
92
const destDirSubdirectories = destDirItems . filter ( ( item ) => item . isDirectory ( ) ) ;
52
93
53
94
destDirSubdirectories . forEach ( ( item ) => {
54
- // TODO: import and use const later instead of 'ruleset_' — RULESET_NAME_PREFIX
55
- // or use RuleSetsLoaderApi.getRuleSetId()
56
- const id = item . name . replace ( 'ruleset_' , '' ) ;
57
- rulesetIds . push ( Number ( id ) ) ;
95
+ const id = extractRuleSetId ( item . name ) ;
96
+
97
+ if ( id === null ) {
98
+ throw new Error ( `Cannot extract ruleset id from ${ item . name } ` ) ;
99
+ }
100
+
101
+ // Skip metadata ruleset, because its a special ruleset
102
+ if ( id === METADATA_RULESET_ID ) {
103
+ return ;
104
+ }
105
+
106
+ rulesetIds . push ( id ) ;
58
107
} ) ;
59
108
60
- const rulesetMetadata = path . join ( destDir , destDirSubdirectories [ 0 ] . name , METADATA_FILENAME ) ;
61
- const rulesetMetadataContent = await fs . promises . readFile ( rulesetMetadata , { encoding : 'utf-8' } ) ;
109
+ const metadataByteRange = metadataRuleSet . getByteRange (
110
+ getRuleSetId ( rulesetIds [ 0 ] ) ,
111
+ RuleSetByteRangeCategory . DeclarativeMetadata ,
112
+ ) ;
113
+
114
+ const metadataBuffer = await readFileRange (
115
+ getRuleSetPath ( rulesetIds [ 0 ] , destDir ) ,
116
+ metadataByteRange ,
117
+ ) ;
118
+
119
+ const rulesetMetadata = metadataBuffer . toString ( 'utf-8' ) ;
62
120
63
121
try {
64
- const parsedRulesetMetadata = JSON . parse ( rulesetMetadataContent ) ;
122
+ const parsedRulesetMetadata = JSON . parse ( rulesetMetadata ) ;
65
123
rulesetMetadataKeys . push ( ...Object . keys ( parsedRulesetMetadata ) ) ;
66
124
} catch ( e : unknown ) {
67
125
console . error ( `Error parsing metadata file ${ rulesetMetadata } due to ${ e } ` ) ;
0 commit comments