@adguard/filters-compiler 3.2.12 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/index.cjs +57 -27
- package/dist/index.js +57 -27
- package/dist/main/optimization.d.ts +6 -4
- package/dist/types/src/main/optimization.d.ts +6 -4
- package/dist/utils/trust-levels/exclusions-full.txt +1 -0
- package/dist/utils/trust-levels/exclusions-high.txt +2 -1
- package/dist/utils/trust-levels/exclusions-low.txt +2 -1
- package/package.json +7 -6
package/README.md
CHANGED
|
@@ -467,7 +467,8 @@ always fetched remotely, even when using the local cache.
|
|
|
467
467
|
1. Call `download(basePath, includedFilterIds, excludedFilterIds)` to save
|
|
468
468
|
`stats.json` for filters listed in the remote `percent.json`.
|
|
469
469
|
`includedFilterIds` limits processing to those IDs (default `[]` = all).
|
|
470
|
-
`excludedFilterIds` skips those IDs (default `[]` = none).
|
|
470
|
+
`excludedFilterIds` skips those IDs (default `[]` = none). When both are
|
|
471
|
+
given, a filter is processed only if it is included and not excluded.
|
|
471
472
|
2. Call `use(basePath)` before `compile()` to tell
|
|
472
473
|
`getOptimizationStatistics` to read stats from local files under
|
|
473
474
|
`basePath` instead of fetching from the remote server.
|
package/dist/index.cjs
CHANGED
|
@@ -17,7 +17,8 @@ var util = require('util');
|
|
|
17
17
|
var module$1 = require('module');
|
|
18
18
|
var jsdom = require('jsdom');
|
|
19
19
|
var crypto = require('crypto');
|
|
20
|
-
var
|
|
20
|
+
var dateFns = require('date-fns');
|
|
21
|
+
var utc = require('@date-fns/utc');
|
|
21
22
|
var fs$1 = require('fs/promises');
|
|
22
23
|
var tldts = require('tldts');
|
|
23
24
|
var Ajv = require('ajv');
|
|
@@ -1187,43 +1188,50 @@ function assertValidStats(filterId, stats) {
|
|
|
1187
1188
|
const localOptimizationStatistics = {
|
|
1188
1189
|
/**
|
|
1189
1190
|
* Downloads `stats.json` files for filters listed in the remote
|
|
1190
|
-
* `percent.json` and saves them to disk.
|
|
1191
|
-
*
|
|
1191
|
+
* `percent.json` and saves them to disk. Downloads into a staged
|
|
1192
|
+
* directory first and swaps it in only after all downloads succeed,
|
|
1193
|
+
* so a failed refresh leaves any previously cached stats intact.
|
|
1192
1194
|
*
|
|
1193
|
-
* `includedFilterIds` and `excludedFilterIds`
|
|
1195
|
+
* When both `includedFilterIds` and `excludedFilterIds` are non-empty,
|
|
1196
|
+
* a filter is processed only if it is in `includedFilterIds` and not in
|
|
1197
|
+
* `excludedFilterIds`.
|
|
1194
1198
|
*
|
|
1195
1199
|
* @param basePath - Directory to save `filters/<filterId>/stats.json` into.
|
|
1196
1200
|
* @param includedFilterIds - Filter IDs to process; empty (default) processes all.
|
|
1197
1201
|
* @param excludedFilterIds - Filter IDs to exclude; empty (default) excludes none.
|
|
1198
|
-
* @throws {Error} When both `includedFilterIds` and `excludedFilterIds` are non-empty.
|
|
1199
1202
|
*/
|
|
1200
1203
|
download: async (basePath, includedFilterIds = [], excludedFilterIds = []) => {
|
|
1201
|
-
if (includedFilterIds.length > 0 && excludedFilterIds.length > 0) {
|
|
1202
|
-
throw new Error('includedFilterIds and excludedFilterIds cannot both be non-empty');
|
|
1203
|
-
}
|
|
1204
1204
|
const percent = JSON.parse(await downloadOptimizationPercent());
|
|
1205
|
-
const configs = percent.config.filter(({ filterId }) =>
|
|
1206
|
-
|
|
1207
|
-
return includedFilterIds.includes(filterId);
|
|
1208
|
-
}
|
|
1209
|
-
if (excludedFilterIds.length > 0) {
|
|
1210
|
-
return !excludedFilterIds.includes(filterId);
|
|
1211
|
-
}
|
|
1212
|
-
return true;
|
|
1213
|
-
});
|
|
1205
|
+
const configs = percent.config.filter(({ filterId }) => (includedFilterIds.length === 0 || includedFilterIds.includes(filterId))
|
|
1206
|
+
&& (excludedFilterIds.length === 0 || !excludedFilterIds.includes(filterId)));
|
|
1214
1207
|
const FILTERS_PATH = path$1.join(basePath, FILTERS_DIR_NAME);
|
|
1208
|
+
const STAGED_PREFIX = `${process.pid}_${Date.now()}`;
|
|
1209
|
+
const STAGED_FILTERS_PATH = path$1.join(basePath, `${STAGED_PREFIX}_${FILTERS_DIR_NAME}`);
|
|
1215
1210
|
/**
|
|
1216
1211
|
* Bounds concurrency so a large `percent.json` cannot fan out into unbounded
|
|
1217
1212
|
* parallel requests if the underlying transport ever becomes truly async.
|
|
1218
1213
|
*/
|
|
1219
1214
|
const DOWNLOAD_CONCURRENCY = 8;
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1215
|
+
try {
|
|
1216
|
+
await fs$1.mkdir(STAGED_FILTERS_PATH, { recursive: true });
|
|
1217
|
+
await mapWithConcurrency(configs, DOWNLOAD_CONCURRENCY, async ({ filterId }) => {
|
|
1218
|
+
const dir = path$1.join(STAGED_FILTERS_PATH, String(filterId));
|
|
1219
|
+
const statsPath = path$1.join(dir, STATS_JSON);
|
|
1220
|
+
const content = await downloadOptimizationStats(filterId);
|
|
1221
|
+
await fs$1.mkdir(dir, { recursive: true });
|
|
1222
|
+
await fs$1.writeFile(statsPath, content, 'utf-8');
|
|
1223
|
+
});
|
|
1224
|
+
}
|
|
1225
|
+
catch (error) {
|
|
1226
|
+
// Downloads incomplete: staged dir is garbage, safe to discard.
|
|
1227
|
+
await fs$1.rm(STAGED_FILTERS_PATH, { recursive: true, force: true });
|
|
1228
|
+
throw error;
|
|
1229
|
+
}
|
|
1230
|
+
// Swap only after every fetch succeeded. From here on, staged dir is
|
|
1231
|
+
// a complete cache — never rm it on failure, that'd destroy the only
|
|
1232
|
+
// remaining valid copy once the old FILTERS_PATH is gone.
|
|
1233
|
+
await fs$1.rm(FILTERS_PATH, { recursive: true, force: true });
|
|
1234
|
+
await fs$1.rename(STAGED_FILTERS_PATH, FILTERS_PATH);
|
|
1227
1235
|
},
|
|
1228
1236
|
/**
|
|
1229
1237
|
* Configures `getOptimizationStatistics` to read stats from local files under
|
|
@@ -1697,7 +1705,7 @@ const makeHeader = function (metadataFile, revisionFile, platformsJsonExpires) {
|
|
|
1697
1705
|
`! Title: ${metadata.name}`,
|
|
1698
1706
|
`! Description: ${metadata.description}`,
|
|
1699
1707
|
`! Version: ${revision.version}`,
|
|
1700
|
-
`! TimeUpdated: ${
|
|
1708
|
+
`! TimeUpdated: ${dateFns.format(revision.timeUpdated, 'yyyy-MM-dd\'T\'HH:mm:ssxxx', { in: utc.utc })}`,
|
|
1701
1709
|
`! Expires: ${expires} (update frequency)`,
|
|
1702
1710
|
];
|
|
1703
1711
|
};
|
|
@@ -2417,8 +2425,8 @@ const loadFilterMetadata = function (filterDir, includedFilterIds, excludedFilte
|
|
|
2417
2425
|
|
|
2418
2426
|
const result = JSON.parse(metadataString);
|
|
2419
2427
|
result.version = revision.version;
|
|
2420
|
-
result.timeUpdated =
|
|
2421
|
-
result.timeAdded =
|
|
2428
|
+
result.timeUpdated = dateFns.format(revision.timeUpdated, 'yyyy-MM-dd\'T\'HH:mm:ssxx', { in: utc.utc });
|
|
2429
|
+
result.timeAdded = dateFns.format(result.timeAdded, 'yyyy-MM-dd\'T\'HH:mm:ssxx', { in: utc.utc });
|
|
2422
2430
|
delete result.disabled;
|
|
2423
2431
|
|
|
2424
2432
|
const { filterId } = result;
|
|
@@ -4391,6 +4399,25 @@ const REPLACE_MODIFIER_PATTERNS = [
|
|
|
4391
4399
|
'\\$(?!#|(path|domain)=.*]|.*removeparam=).*replace(,|=|$)',
|
|
4392
4400
|
];
|
|
4393
4401
|
|
|
4402
|
+
/**
|
|
4403
|
+
* Pattern to check if rule contains `$urltransform` modifier
|
|
4404
|
+
* and does not contain non-basic modifiers like `$domain` or `$path`.
|
|
4405
|
+
*
|
|
4406
|
+
* Pattern parts:
|
|
4407
|
+
* - `\\$` — modifiers divider
|
|
4408
|
+
* - `(?!#|(path|domain)=.*]|.*removeparam=).*` — negative lookahead to exclude CSS rules (#$#) and rules like
|
|
4409
|
+
* `[$path=...]##.textad,[urltransform="ads"]` and rules with `$removeparam` modifier like `$removeparam=urltransform`
|
|
4410
|
+
* - `.*urltransform` — urltransform modifier itself
|
|
4411
|
+
* - `(,|=|$)` — end of line or modifiers divider, as `$urltransform` can be followed by other modifiers (`,`),
|
|
4412
|
+
* it may have a value (`=`), or it may be the last modifier in the rule (`$`).
|
|
4413
|
+
*
|
|
4414
|
+
* @example
|
|
4415
|
+
* ```||example.com^$urltransform=/firstpath/secondpath/```
|
|
4416
|
+
*/
|
|
4417
|
+
const URLTRANSFORM_MODIFIER_PATTERNS = [
|
|
4418
|
+
'\\$(?!#|(path|domain)=.*]|.*removeparam=).*urltransform(,|=|$)',
|
|
4419
|
+
];
|
|
4420
|
+
|
|
4394
4421
|
/* eslint-disable max-len */
|
|
4395
4422
|
|
|
4396
4423
|
/**
|
|
@@ -4669,6 +4696,7 @@ const SAFARI_BASED_EXTENSION_PATTERNS = [
|
|
|
4669
4696
|
...REMOVEHEADER_MODIFIER_PATTERNS,
|
|
4670
4697
|
...MP4_MODIFIER_PATTERNS,
|
|
4671
4698
|
...REPLACE_MODIFIER_PATTERNS,
|
|
4699
|
+
...URLTRANSFORM_MODIFIER_PATTERNS,
|
|
4672
4700
|
...STEALTH_MODIFIER_PATTERNS,
|
|
4673
4701
|
...COOKIE_MODIFIER_PATTERNS,
|
|
4674
4702
|
...APP_MODIFIER_PATTERNS,
|
|
@@ -4932,6 +4960,7 @@ const platformsConfig = {
|
|
|
4932
4960
|
...CSS_RULES_PATTERNS,
|
|
4933
4961
|
...MP4_MODIFIER_PATTERNS,
|
|
4934
4962
|
...REPLACE_MODIFIER_PATTERNS,
|
|
4963
|
+
...URLTRANSFORM_MODIFIER_PATTERNS,
|
|
4935
4964
|
...STEALTH_MODIFIER_PATTERNS,
|
|
4936
4965
|
...COOKIE_MODIFIER_PATTERNS,
|
|
4937
4966
|
...EMPTY_MODIFIER_PATTERNS,
|
|
@@ -4965,6 +4994,7 @@ const platformsConfig = {
|
|
|
4965
4994
|
...HTML_FILTERING_MODIFIER_PATTERNS,
|
|
4966
4995
|
...MP4_MODIFIER_PATTERNS,
|
|
4967
4996
|
...REPLACE_MODIFIER_PATTERNS,
|
|
4997
|
+
...URLTRANSFORM_MODIFIER_PATTERNS,
|
|
4968
4998
|
...STEALTH_MODIFIER_PATTERNS,
|
|
4969
4999
|
...COOKIE_MODIFIER_PATTERNS,
|
|
4970
5000
|
...APP_MODIFIER_PATTERNS,
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,8 @@ import { TextEncoder, TextDecoder } from 'util';
|
|
|
15
15
|
import { createRequire } from 'module';
|
|
16
16
|
import { JSDOM } from 'jsdom';
|
|
17
17
|
import crypto from 'crypto';
|
|
18
|
-
import
|
|
18
|
+
import { format } from 'date-fns';
|
|
19
|
+
import { utc } from '@date-fns/utc';
|
|
19
20
|
import fs$1 from 'fs/promises';
|
|
20
21
|
import { parse as parse$1 } from 'tldts';
|
|
21
22
|
import Ajv from 'ajv';
|
|
@@ -1184,43 +1185,50 @@ function assertValidStats(filterId, stats) {
|
|
|
1184
1185
|
const localOptimizationStatistics = {
|
|
1185
1186
|
/**
|
|
1186
1187
|
* Downloads `stats.json` files for filters listed in the remote
|
|
1187
|
-
* `percent.json` and saves them to disk.
|
|
1188
|
-
*
|
|
1188
|
+
* `percent.json` and saves them to disk. Downloads into a staged
|
|
1189
|
+
* directory first and swaps it in only after all downloads succeed,
|
|
1190
|
+
* so a failed refresh leaves any previously cached stats intact.
|
|
1189
1191
|
*
|
|
1190
|
-
* `includedFilterIds` and `excludedFilterIds`
|
|
1192
|
+
* When both `includedFilterIds` and `excludedFilterIds` are non-empty,
|
|
1193
|
+
* a filter is processed only if it is in `includedFilterIds` and not in
|
|
1194
|
+
* `excludedFilterIds`.
|
|
1191
1195
|
*
|
|
1192
1196
|
* @param basePath - Directory to save `filters/<filterId>/stats.json` into.
|
|
1193
1197
|
* @param includedFilterIds - Filter IDs to process; empty (default) processes all.
|
|
1194
1198
|
* @param excludedFilterIds - Filter IDs to exclude; empty (default) excludes none.
|
|
1195
|
-
* @throws {Error} When both `includedFilterIds` and `excludedFilterIds` are non-empty.
|
|
1196
1199
|
*/
|
|
1197
1200
|
download: async (basePath, includedFilterIds = [], excludedFilterIds = []) => {
|
|
1198
|
-
if (includedFilterIds.length > 0 && excludedFilterIds.length > 0) {
|
|
1199
|
-
throw new Error('includedFilterIds and excludedFilterIds cannot both be non-empty');
|
|
1200
|
-
}
|
|
1201
1201
|
const percent = JSON.parse(await downloadOptimizationPercent());
|
|
1202
|
-
const configs = percent.config.filter(({ filterId }) =>
|
|
1203
|
-
|
|
1204
|
-
return includedFilterIds.includes(filterId);
|
|
1205
|
-
}
|
|
1206
|
-
if (excludedFilterIds.length > 0) {
|
|
1207
|
-
return !excludedFilterIds.includes(filterId);
|
|
1208
|
-
}
|
|
1209
|
-
return true;
|
|
1210
|
-
});
|
|
1202
|
+
const configs = percent.config.filter(({ filterId }) => (includedFilterIds.length === 0 || includedFilterIds.includes(filterId))
|
|
1203
|
+
&& (excludedFilterIds.length === 0 || !excludedFilterIds.includes(filterId)));
|
|
1211
1204
|
const FILTERS_PATH = path$1.join(basePath, FILTERS_DIR_NAME);
|
|
1205
|
+
const STAGED_PREFIX = `${process.pid}_${Date.now()}`;
|
|
1206
|
+
const STAGED_FILTERS_PATH = path$1.join(basePath, `${STAGED_PREFIX}_${FILTERS_DIR_NAME}`);
|
|
1212
1207
|
/**
|
|
1213
1208
|
* Bounds concurrency so a large `percent.json` cannot fan out into unbounded
|
|
1214
1209
|
* parallel requests if the underlying transport ever becomes truly async.
|
|
1215
1210
|
*/
|
|
1216
1211
|
const DOWNLOAD_CONCURRENCY = 8;
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1212
|
+
try {
|
|
1213
|
+
await fs$1.mkdir(STAGED_FILTERS_PATH, { recursive: true });
|
|
1214
|
+
await mapWithConcurrency(configs, DOWNLOAD_CONCURRENCY, async ({ filterId }) => {
|
|
1215
|
+
const dir = path$1.join(STAGED_FILTERS_PATH, String(filterId));
|
|
1216
|
+
const statsPath = path$1.join(dir, STATS_JSON);
|
|
1217
|
+
const content = await downloadOptimizationStats(filterId);
|
|
1218
|
+
await fs$1.mkdir(dir, { recursive: true });
|
|
1219
|
+
await fs$1.writeFile(statsPath, content, 'utf-8');
|
|
1220
|
+
});
|
|
1221
|
+
}
|
|
1222
|
+
catch (error) {
|
|
1223
|
+
// Downloads incomplete: staged dir is garbage, safe to discard.
|
|
1224
|
+
await fs$1.rm(STAGED_FILTERS_PATH, { recursive: true, force: true });
|
|
1225
|
+
throw error;
|
|
1226
|
+
}
|
|
1227
|
+
// Swap only after every fetch succeeded. From here on, staged dir is
|
|
1228
|
+
// a complete cache — never rm it on failure, that'd destroy the only
|
|
1229
|
+
// remaining valid copy once the old FILTERS_PATH is gone.
|
|
1230
|
+
await fs$1.rm(FILTERS_PATH, { recursive: true, force: true });
|
|
1231
|
+
await fs$1.rename(STAGED_FILTERS_PATH, FILTERS_PATH);
|
|
1224
1232
|
},
|
|
1225
1233
|
/**
|
|
1226
1234
|
* Configures `getOptimizationStatistics` to read stats from local files under
|
|
@@ -1694,7 +1702,7 @@ const makeHeader = function (metadataFile, revisionFile, platformsJsonExpires) {
|
|
|
1694
1702
|
`! Title: ${metadata.name}`,
|
|
1695
1703
|
`! Description: ${metadata.description}`,
|
|
1696
1704
|
`! Version: ${revision.version}`,
|
|
1697
|
-
`! TimeUpdated: ${
|
|
1705
|
+
`! TimeUpdated: ${format(revision.timeUpdated, 'yyyy-MM-dd\'T\'HH:mm:ssxxx', { in: utc })}`,
|
|
1698
1706
|
`! Expires: ${expires} (update frequency)`,
|
|
1699
1707
|
];
|
|
1700
1708
|
};
|
|
@@ -2414,8 +2422,8 @@ const loadFilterMetadata = function (filterDir, includedFilterIds, excludedFilte
|
|
|
2414
2422
|
|
|
2415
2423
|
const result = JSON.parse(metadataString);
|
|
2416
2424
|
result.version = revision.version;
|
|
2417
|
-
result.timeUpdated =
|
|
2418
|
-
result.timeAdded =
|
|
2425
|
+
result.timeUpdated = format(revision.timeUpdated, 'yyyy-MM-dd\'T\'HH:mm:ssxx', { in: utc });
|
|
2426
|
+
result.timeAdded = format(result.timeAdded, 'yyyy-MM-dd\'T\'HH:mm:ssxx', { in: utc });
|
|
2419
2427
|
delete result.disabled;
|
|
2420
2428
|
|
|
2421
2429
|
const { filterId } = result;
|
|
@@ -4388,6 +4396,25 @@ const REPLACE_MODIFIER_PATTERNS = [
|
|
|
4388
4396
|
'\\$(?!#|(path|domain)=.*]|.*removeparam=).*replace(,|=|$)',
|
|
4389
4397
|
];
|
|
4390
4398
|
|
|
4399
|
+
/**
|
|
4400
|
+
* Pattern to check if rule contains `$urltransform` modifier
|
|
4401
|
+
* and does not contain non-basic modifiers like `$domain` or `$path`.
|
|
4402
|
+
*
|
|
4403
|
+
* Pattern parts:
|
|
4404
|
+
* - `\\$` — modifiers divider
|
|
4405
|
+
* - `(?!#|(path|domain)=.*]|.*removeparam=).*` — negative lookahead to exclude CSS rules (#$#) and rules like
|
|
4406
|
+
* `[$path=...]##.textad,[urltransform="ads"]` and rules with `$removeparam` modifier like `$removeparam=urltransform`
|
|
4407
|
+
* - `.*urltransform` — urltransform modifier itself
|
|
4408
|
+
* - `(,|=|$)` — end of line or modifiers divider, as `$urltransform` can be followed by other modifiers (`,`),
|
|
4409
|
+
* it may have a value (`=`), or it may be the last modifier in the rule (`$`).
|
|
4410
|
+
*
|
|
4411
|
+
* @example
|
|
4412
|
+
* ```||example.com^$urltransform=/firstpath/secondpath/```
|
|
4413
|
+
*/
|
|
4414
|
+
const URLTRANSFORM_MODIFIER_PATTERNS = [
|
|
4415
|
+
'\\$(?!#|(path|domain)=.*]|.*removeparam=).*urltransform(,|=|$)',
|
|
4416
|
+
];
|
|
4417
|
+
|
|
4391
4418
|
/* eslint-disable max-len */
|
|
4392
4419
|
|
|
4393
4420
|
/**
|
|
@@ -4666,6 +4693,7 @@ const SAFARI_BASED_EXTENSION_PATTERNS = [
|
|
|
4666
4693
|
...REMOVEHEADER_MODIFIER_PATTERNS,
|
|
4667
4694
|
...MP4_MODIFIER_PATTERNS,
|
|
4668
4695
|
...REPLACE_MODIFIER_PATTERNS,
|
|
4696
|
+
...URLTRANSFORM_MODIFIER_PATTERNS,
|
|
4669
4697
|
...STEALTH_MODIFIER_PATTERNS,
|
|
4670
4698
|
...COOKIE_MODIFIER_PATTERNS,
|
|
4671
4699
|
...APP_MODIFIER_PATTERNS,
|
|
@@ -4929,6 +4957,7 @@ const platformsConfig = {
|
|
|
4929
4957
|
...CSS_RULES_PATTERNS,
|
|
4930
4958
|
...MP4_MODIFIER_PATTERNS,
|
|
4931
4959
|
...REPLACE_MODIFIER_PATTERNS,
|
|
4960
|
+
...URLTRANSFORM_MODIFIER_PATTERNS,
|
|
4932
4961
|
...STEALTH_MODIFIER_PATTERNS,
|
|
4933
4962
|
...COOKIE_MODIFIER_PATTERNS,
|
|
4934
4963
|
...EMPTY_MODIFIER_PATTERNS,
|
|
@@ -4962,6 +4991,7 @@ const platformsConfig = {
|
|
|
4962
4991
|
...HTML_FILTERING_MODIFIER_PATTERNS,
|
|
4963
4992
|
...MP4_MODIFIER_PATTERNS,
|
|
4964
4993
|
...REPLACE_MODIFIER_PATTERNS,
|
|
4994
|
+
...URLTRANSFORM_MODIFIER_PATTERNS,
|
|
4965
4995
|
...STEALTH_MODIFIER_PATTERNS,
|
|
4966
4996
|
...COOKIE_MODIFIER_PATTERNS,
|
|
4967
4997
|
...APP_MODIFIER_PATTERNS,
|
|
@@ -52,15 +52,17 @@ export declare function assertValidStats(filterId: number, stats: unknown): asse
|
|
|
52
52
|
export declare const localOptimizationStatistics: {
|
|
53
53
|
/**
|
|
54
54
|
* Downloads `stats.json` files for filters listed in the remote
|
|
55
|
-
* `percent.json` and saves them to disk.
|
|
56
|
-
*
|
|
55
|
+
* `percent.json` and saves them to disk. Downloads into a staged
|
|
56
|
+
* directory first and swaps it in only after all downloads succeed,
|
|
57
|
+
* so a failed refresh leaves any previously cached stats intact.
|
|
57
58
|
*
|
|
58
|
-
* `includedFilterIds` and `excludedFilterIds`
|
|
59
|
+
* When both `includedFilterIds` and `excludedFilterIds` are non-empty,
|
|
60
|
+
* a filter is processed only if it is in `includedFilterIds` and not in
|
|
61
|
+
* `excludedFilterIds`.
|
|
59
62
|
*
|
|
60
63
|
* @param basePath - Directory to save `filters/<filterId>/stats.json` into.
|
|
61
64
|
* @param includedFilterIds - Filter IDs to process; empty (default) processes all.
|
|
62
65
|
* @param excludedFilterIds - Filter IDs to exclude; empty (default) excludes none.
|
|
63
|
-
* @throws {Error} When both `includedFilterIds` and `excludedFilterIds` are non-empty.
|
|
64
66
|
*/
|
|
65
67
|
download: (basePath: string, includedFilterIds?: number[], excludedFilterIds?: number[]) => Promise<void>;
|
|
66
68
|
/**
|
|
@@ -52,15 +52,17 @@ export declare function assertValidStats(filterId: number, stats: unknown): asse
|
|
|
52
52
|
export declare const localOptimizationStatistics: {
|
|
53
53
|
/**
|
|
54
54
|
* Downloads `stats.json` files for filters listed in the remote
|
|
55
|
-
* `percent.json` and saves them to disk.
|
|
56
|
-
*
|
|
55
|
+
* `percent.json` and saves them to disk. Downloads into a staged
|
|
56
|
+
* directory first and swaps it in only after all downloads succeed,
|
|
57
|
+
* so a failed refresh leaves any previously cached stats intact.
|
|
57
58
|
*
|
|
58
|
-
* `includedFilterIds` and `excludedFilterIds`
|
|
59
|
+
* When both `includedFilterIds` and `excludedFilterIds` are non-empty,
|
|
60
|
+
* a filter is processed only if it is in `includedFilterIds` and not in
|
|
61
|
+
* `excludedFilterIds`.
|
|
59
62
|
*
|
|
60
63
|
* @param basePath - Directory to save `filters/<filterId>/stats.json` into.
|
|
61
64
|
* @param includedFilterIds - Filter IDs to process; empty (default) processes all.
|
|
62
65
|
* @param excludedFilterIds - Filter IDs to exclude; empty (default) excludes none.
|
|
63
|
-
* @throws {Error} When both `includedFilterIds` and `excludedFilterIds` are non-empty.
|
|
64
66
|
*/
|
|
65
67
|
download: (basePath: string, includedFilterIds?: number[], excludedFilterIds?: number[]) => Promise<void>;
|
|
66
68
|
/**
|
package/package.json
CHANGED
|
@@ -21,20 +21,21 @@
|
|
|
21
21
|
"pnpm": ">=10.33.4 <11"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@adguard/agtree": "4.1
|
|
24
|
+
"@adguard/agtree": "4.2.1",
|
|
25
25
|
"@adguard/css-tokenizer": "1.2.0",
|
|
26
26
|
"@adguard/ecss-tree": "2.0.1",
|
|
27
|
-
"@adguard/extended-css": "2.
|
|
27
|
+
"@adguard/extended-css": "2.2.0",
|
|
28
28
|
"@adguard/filters-downloader": "2.4.4",
|
|
29
29
|
"@adguard/logger": "2.0.0",
|
|
30
|
-
"@adguard/scriptlets": "2.
|
|
31
|
-
"@adguard/tsurlfilter": "
|
|
30
|
+
"@adguard/scriptlets": "2.5.1",
|
|
31
|
+
"@adguard/tsurlfilter": "6.0.3",
|
|
32
|
+
"@date-fns/utc": "2.1.1",
|
|
32
33
|
"@eslint/css-tree": "3.6.6",
|
|
33
34
|
"ajv": "8.17.1",
|
|
34
35
|
"child_process": "1.0.2",
|
|
36
|
+
"date-fns": "^4.4.0",
|
|
35
37
|
"jsdom": "21.1.2",
|
|
36
38
|
"md5": "2.3.0",
|
|
37
|
-
"moment": "2.30.1",
|
|
38
39
|
"tldts": "5.7.112",
|
|
39
40
|
"utf8": "3.0.0"
|
|
40
41
|
},
|
|
@@ -58,7 +59,7 @@
|
|
|
58
59
|
"typescript": "6.0.3",
|
|
59
60
|
"vitest": "3.0.5"
|
|
60
61
|
},
|
|
61
|
-
"version": "3.
|
|
62
|
+
"version": "3.3.0",
|
|
62
63
|
"scripts": {
|
|
63
64
|
"prebuild": "rimraf dist",
|
|
64
65
|
"build": "rollup --config rollup.config.js --silent",
|