@ezmar/yandex-metric-parser-lib 0.1.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/LICENSE +21 -0
- package/README.md +213 -0
- package/dist/index.cjs +2790 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +999 -0
- package/dist/index.d.ts +999 -0
- package/dist/index.js +2707 -0
- package/dist/index.js.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/contract/registry.generated.ts","../src/contract/registry.ts","../src/client/errors.ts","../src/client/rateLimit.ts","../src/client/warnings.ts","../src/client/http.ts","../src/management/api.ts","../src/reports/dates.ts","../src/reports/validate.ts","../src/reports/data.ts","../src/keywords/shared.ts","../src/keywords/directCost.ts","../src/keywords/directVisits.ts","../src/keywords/organic.ts","../src/keywords/landing.ts","../src/keywords/timeline.ts","../src/keywords/quality.ts","../src/keywords/merge.ts","../src/metrika.ts","../src/contract/used.ts"],"sourcesContent":["// СГЕНЕРИРОВАНО скриптом scripts/parse-contract.ts — не редактировать вручную.\n// Источник: docs/full-docs.txt (llms-full.txt API Яндекс Метрики).\n\n/** Версия контракта: первые 12 символов sha256 документации, по которой собран реестр. */\nexport const contractVersion = \"5695d8903f6d\";\n\n/** Полный sha256 документации-источника. */\nexport const contractSourceSha256 = \"5695d8903f6d252cdd95f058ed3b5984815fe96a215bbd6c23db3e349d4eb784\";\n\n/** Когда снапшот был разобран. */\nexport const contractParsedAt = \"2026-09-05T13:29:26.759Z\";\n\n/** Все известные группировки (684). */\nexport const DIMENSION_IDS: ReadonlySet<string> = new Set([\n \"ym:ad:<attribution>Currency\",\n \"ym:ad:<attribution>DirectBanner\",\n \"ym:ad:<attribution>DirectBannerGroup\",\n \"ym:ad:<attribution>DirectConditionType\",\n \"ym:ad:<attribution>DirectOrder\",\n \"ym:ad:<attribution>DirectPhraseOrCond\",\n \"ym:ad:<attribution>DirectPlatform\",\n \"ym:ad:<attribution>DirectPlatformType\",\n \"ym:ad:<attribution>DirectSearchPhrase\",\n \"ym:ad:<attribution>DisplayCampaign\",\n \"ym:ad:ageInterval\",\n \"ym:ad:gender\",\n \"ym:ad:regionArea\",\n \"ym:ad:regionCity\",\n \"ym:ad:regionCitySize\",\n \"ym:ad:regionContinent\",\n \"ym:ad:regionCountry\",\n \"ym:ad:regionDistrict\",\n \"ym:dl:ageInterval\",\n \"ym:dl:browser\",\n \"ym:dl:browserAndVersion\",\n \"ym:dl:browserAndVersionMajor\",\n \"ym:dl:browserCountry\",\n \"ym:dl:browserDate\",\n \"ym:dl:browserDatePeriod<group>\",\n \"ym:dl:browserDateTime\",\n \"ym:dl:browserDayOfMonth\",\n \"ym:dl:browserDayOfWeek\",\n \"ym:dl:browserDekaminute\",\n \"ym:dl:browserEngine\",\n \"ym:dl:browserEngineVersion1\",\n \"ym:dl:browserEngineVersion2\",\n \"ym:dl:browserEngineVersion3\",\n \"ym:dl:browserEngineVersion4\",\n \"ym:dl:browserHour\",\n \"ym:dl:browserHourMinute\",\n \"ym:dl:browserLanguage\",\n \"ym:dl:browserMinute\",\n \"ym:dl:browserMonth\",\n \"ym:dl:browserStartOfDekaminute\",\n \"ym:dl:browserStartOfHour\",\n \"ym:dl:browserStartOfMinute\",\n \"ym:dl:browserStartOfMonth\",\n \"ym:dl:browserStartOfQuarter\",\n \"ym:dl:browserStartOfWeek\",\n \"ym:dl:browserStartOfYear\",\n \"ym:dl:browserYear\",\n \"ym:dl:clientTimeZone\",\n \"ym:dl:cookieEnabled\",\n \"ym:dl:date\",\n \"ym:dl:datePeriod<group>\",\n \"ym:dl:dateTime\",\n \"ym:dl:dayOfMonth\",\n \"ym:dl:dayOfWeek\",\n \"ym:dl:dekaminute\",\n \"ym:dl:deviceCategory\",\n \"ym:dl:downloadURL\",\n \"ym:dl:from\",\n \"ym:dl:gender\",\n \"ym:dl:hasAdBlocker\",\n \"ym:dl:hasGCLID\",\n \"ym:dl:hasSBCLID\",\n \"ym:dl:hour\",\n \"ym:dl:hourMinute\",\n \"ym:dl:ipAddress\",\n \"ym:dl:javascriptEnabled\",\n \"ym:dl:minute\",\n \"ym:dl:mobilePhone\",\n \"ym:dl:mobilePhoneModel\",\n \"ym:dl:month\",\n \"ym:dl:openstatAd\",\n \"ym:dl:openstatCampaign\",\n \"ym:dl:openstatService\",\n \"ym:dl:openstatSource\",\n \"ym:dl:operatingSystem\",\n \"ym:dl:operatingSystemRoot\",\n \"ym:dl:pageURL\",\n \"ym:dl:physicalScreenHeight\",\n \"ym:dl:physicalScreenResolution\",\n \"ym:dl:physicalScreenWidth\",\n \"ym:dl:regionArea\",\n \"ym:dl:regionCity\",\n \"ym:dl:regionCitySize\",\n \"ym:dl:regionContinent\",\n \"ym:dl:regionCountry\",\n \"ym:dl:regionDistrict\",\n \"ym:dl:SBCLID\",\n \"ym:dl:screenColors\",\n \"ym:dl:screenFormat\",\n \"ym:dl:screenHeight\",\n \"ym:dl:screenOrientation\",\n \"ym:dl:screenResolution\",\n \"ym:dl:screenWidth\",\n \"ym:dl:startOfDekaminute\",\n \"ym:dl:startOfHour\",\n \"ym:dl:startOfMinute\",\n \"ym:dl:startOfMonth\",\n \"ym:dl:startOfQuarter\",\n \"ym:dl:startOfWeek\",\n \"ym:dl:startOfYear\",\n \"ym:dl:thirdPartyCookieEnabled\",\n \"ym:dl:title\",\n \"ym:dl:URL\",\n \"ym:dl:URLDomain\",\n \"ym:dl:URLParamName\",\n \"ym:dl:URLParamNameAndValue\",\n \"ym:dl:URLParamValue\",\n \"ym:dl:URLPath\",\n \"ym:dl:URLPathFull\",\n \"ym:dl:URLPathLevel1\",\n \"ym:dl:URLPathLevel2\",\n \"ym:dl:URLPathLevel3\",\n \"ym:dl:URLPathLevel4\",\n \"ym:dl:URLPathLevel5\",\n \"ym:dl:URLProto\",\n \"ym:dl:UTMCampaign\",\n \"ym:dl:UTMContent\",\n \"ym:dl:UTMMedium\",\n \"ym:dl:UTMSource\",\n \"ym:dl:UTMTerm\",\n \"ym:dl:windowClientArea\",\n \"ym:dl:windowClientHeight\",\n \"ym:dl:windowClientWidth\",\n \"ym:dl:year\",\n \"ym:ep:actionGoal\",\n \"ym:ep:ageInterval\",\n \"ym:ep:browser\",\n \"ym:ep:browserAndVersion\",\n \"ym:ep:browserAndVersionMajor\",\n \"ym:ep:browserDate\",\n \"ym:ep:browserDatePeriod<group>\",\n \"ym:ep:browserDateTime\",\n \"ym:ep:browserDayOfMonth\",\n \"ym:ep:browserDayOfWeek\",\n \"ym:ep:browserDekaminute\",\n \"ym:ep:browserEngine\",\n \"ym:ep:browserEngineVersion1\",\n \"ym:ep:browserEngineVersion2\",\n \"ym:ep:browserEngineVersion3\",\n \"ym:ep:browserEngineVersion4\",\n \"ym:ep:browserHour\",\n \"ym:ep:browserHourMinute\",\n \"ym:ep:browserMinute\",\n \"ym:ep:browserMonth\",\n \"ym:ep:browserStartOfDekaminute\",\n \"ym:ep:browserStartOfHour\",\n \"ym:ep:browserStartOfMinute\",\n \"ym:ep:browserStartOfMonth\",\n \"ym:ep:browserStartOfQuarter\",\n \"ym:ep:browserStartOfWeek\",\n \"ym:ep:browserStartOfYear\",\n \"ym:ep:browserYear\",\n \"ym:ep:cookieEnabled\",\n \"ym:ep:date\",\n \"ym:ep:datePeriod<group>\",\n \"ym:ep:dateTime\",\n \"ym:ep:dayOfMonth\",\n \"ym:ep:dayOfWeek\",\n \"ym:ep:dekaminute\",\n \"ym:ep:deviceCategory\",\n \"ym:ep:eventParamsLevel1\",\n \"ym:ep:eventParamsLevel10\",\n \"ym:ep:eventParamsLevel2\",\n \"ym:ep:eventParamsLevel3\",\n \"ym:ep:eventParamsLevel4\",\n \"ym:ep:eventParamsLevel5\",\n \"ym:ep:eventParamsLevel6\",\n \"ym:ep:eventParamsLevel7\",\n \"ym:ep:eventParamsLevel8\",\n \"ym:ep:eventParamsLevel9\",\n \"ym:ep:eventURL\",\n \"ym:ep:eventURLDomain\",\n \"ym:ep:eventURLParamName\",\n \"ym:ep:eventURLParamNameAndValue\",\n \"ym:ep:eventURLParamValue\",\n \"ym:ep:eventURLPath\",\n \"ym:ep:eventURLPathFull\",\n \"ym:ep:eventURLPathLevel1\",\n \"ym:ep:eventURLPathLevel2\",\n \"ym:ep:eventURLPathLevel3\",\n \"ym:ep:eventURLPathLevel4\",\n \"ym:ep:eventURLPathLevel5\",\n \"ym:ep:eventURLProto\",\n \"ym:ep:gender\",\n \"ym:ep:hasAdBlocker\",\n \"ym:ep:hour\",\n \"ym:ep:hourMinute\",\n \"ym:ep:ipAddress\",\n \"ym:ep:javascriptEnabled\",\n \"ym:ep:minute\",\n \"ym:ep:mobilePhone\",\n \"ym:ep:mobilePhoneModel\",\n \"ym:ep:month\",\n \"ym:ep:operatingSystem\",\n \"ym:ep:operatingSystemRoot\",\n \"ym:ep:physicalScreenHeight\",\n \"ym:ep:physicalScreenResolution\",\n \"ym:ep:physicalScreenWidth\",\n \"ym:ep:regionArea\",\n \"ym:ep:regionCity\",\n \"ym:ep:regionCitySize\",\n \"ym:ep:regionContinent\",\n \"ym:ep:regionCountry\",\n \"ym:ep:regionDistrict\",\n \"ym:ep:screenColors\",\n \"ym:ep:screenFormat\",\n \"ym:ep:screenHeight\",\n \"ym:ep:screenOrientation\",\n \"ym:ep:screenResolution\",\n \"ym:ep:screenWidth\",\n \"ym:ep:startOfDekaminute\",\n \"ym:ep:startOfHour\",\n \"ym:ep:startOfMinute\",\n \"ym:ep:startOfMonth\",\n \"ym:ep:startOfQuarter\",\n \"ym:ep:startOfWeek\",\n \"ym:ep:startOfYear\",\n \"ym:ep:thirdPartyCookieEnabled\",\n \"ym:ep:windowClientArea\",\n \"ym:ep:windowClientHeight\",\n \"ym:ep:windowClientWidth\",\n \"ym:ep:year\",\n \"ym:ev:<attribution>ExpenseCampaign\",\n \"ym:ev:<attribution>ExpenseContent\",\n \"ym:ev:<attribution>ExpenseMedium\",\n \"ym:ev:<attribution>ExpenseSource\",\n \"ym:ev:<attribution>ExpenseTerm\",\n \"ym:ev:<attribution>SourceEngine\",\n \"ym:ev:<attribution>TrafficSource\",\n \"ym:pv:ageInterval\",\n \"ym:pv:browser\",\n \"ym:pv:browserAndVersion\",\n \"ym:pv:browserAndVersionMajor\",\n \"ym:pv:browserCountry\",\n \"ym:pv:browserDate\",\n \"ym:pv:browserDatePeriod<group>\",\n \"ym:pv:browserDateTime\",\n \"ym:pv:browserDayOfMonth\",\n \"ym:pv:browserDayOfWeek\",\n \"ym:pv:browserDekaminute\",\n \"ym:pv:browserEngine\",\n \"ym:pv:browserEngineVersion1\",\n \"ym:pv:browserEngineVersion2\",\n \"ym:pv:browserEngineVersion3\",\n \"ym:pv:browserEngineVersion4\",\n \"ym:pv:browserHour\",\n \"ym:pv:browserHourMinute\",\n \"ym:pv:browserLanguage\",\n \"ym:pv:browserMinute\",\n \"ym:pv:browserMonth\",\n \"ym:pv:browserStartOfDekaminute\",\n \"ym:pv:browserStartOfHour\",\n \"ym:pv:browserStartOfMinute\",\n \"ym:pv:browserStartOfMonth\",\n \"ym:pv:browserStartOfQuarter\",\n \"ym:pv:browserStartOfWeek\",\n \"ym:pv:browserStartOfYear\",\n \"ym:pv:browserYear\",\n \"ym:pv:clientTimeZone\",\n \"ym:pv:cookieEnabled\",\n \"ym:pv:counterID\",\n \"ym:pv:date\",\n \"ym:pv:datePeriod<group>\",\n \"ym:pv:dateTime\",\n \"ym:pv:dayOfMonth\",\n \"ym:pv:dayOfWeek\",\n \"ym:pv:dekaminute\",\n \"ym:pv:deviceCategory\",\n \"ym:pv:from\",\n \"ym:pv:gender\",\n \"ym:pv:hasAdBlocker\",\n \"ym:pv:hasGCLID\",\n \"ym:pv:hasSBCLID\",\n \"ym:pv:hour\",\n \"ym:pv:hourMinute\",\n \"ym:pv:ipAddress\",\n \"ym:pv:isTurboPage\",\n \"ym:pv:javascriptEnabled\",\n \"ym:pv:minute\",\n \"ym:pv:mobilePhone\",\n \"ym:pv:mobilePhoneModel\",\n \"ym:pv:month\",\n \"ym:pv:openstatAd\",\n \"ym:pv:openstatCampaign\",\n \"ym:pv:openstatService\",\n \"ym:pv:openstatSource\",\n \"ym:pv:operatingSystem\",\n \"ym:pv:operatingSystemRoot\",\n \"ym:pv:physicalScreenHeight\",\n \"ym:pv:physicalScreenResolution\",\n \"ym:pv:physicalScreenWidth\",\n \"ym:pv:referer\",\n \"ym:pv:refererDomain\",\n \"ym:pv:refererPath\",\n \"ym:pv:refererPathFull\",\n \"ym:pv:refererPathLevel1\",\n \"ym:pv:refererPathLevel2\",\n \"ym:pv:refererPathLevel3\",\n \"ym:pv:refererPathLevel4\",\n \"ym:pv:refererPathLevel5\",\n \"ym:pv:refererProto\",\n \"ym:pv:regionArea\",\n \"ym:pv:regionCity\",\n \"ym:pv:regionCitySize\",\n \"ym:pv:regionContinent\",\n \"ym:pv:regionCountry\",\n \"ym:pv:regionDistrict\",\n \"ym:pv:SBCLID\",\n \"ym:pv:screenColors\",\n \"ym:pv:screenFormat\",\n \"ym:pv:screenHeight\",\n \"ym:pv:screenOrientation\",\n \"ym:pv:screenResolution\",\n \"ym:pv:screenWidth\",\n \"ym:pv:startOfDekaminute\",\n \"ym:pv:startOfHour\",\n \"ym:pv:startOfMinute\",\n \"ym:pv:startOfMonth\",\n \"ym:pv:startOfQuarter\",\n \"ym:pv:startOfWeek\",\n \"ym:pv:startOfYear\",\n \"ym:pv:thirdPartyCookieEnabled\",\n \"ym:pv:title\",\n \"ym:pv:URL\",\n \"ym:pv:URLDomain\",\n \"ym:pv:URLParamName\",\n \"ym:pv:URLParamNameAndValue\",\n \"ym:pv:URLParamValue\",\n \"ym:pv:URLPath\",\n \"ym:pv:URLPathFull\",\n \"ym:pv:URLPathLevel1\",\n \"ym:pv:URLPathLevel2\",\n \"ym:pv:URLPathLevel3\",\n \"ym:pv:URLPathLevel4\",\n \"ym:pv:URLPathLevel5\",\n \"ym:pv:URLProto\",\n \"ym:pv:UTMCampaign\",\n \"ym:pv:UTMContent\",\n \"ym:pv:UTMMedium\",\n \"ym:pv:UTMSource\",\n \"ym:pv:UTMTerm\",\n \"ym:pv:windowClientArea\",\n \"ym:pv:windowClientHeight\",\n \"ym:pv:windowClientWidth\",\n \"ym:pv:year\",\n \"ym:s:<attribution>AdvEngine\",\n \"ym:s:<attribution>Currency\",\n \"ym:s:<attribution>DirectBannerGroup\",\n \"ym:s:<attribution>DirectClickBanner\",\n \"ym:s:<attribution>DirectClickOrder\",\n \"ym:s:<attribution>DirectConditionType\",\n \"ym:s:<attribution>DirectID\",\n \"ym:s:<attribution>DirectPhraseOrCond\",\n \"ym:s:<attribution>DirectPlatform\",\n \"ym:s:<attribution>DirectPlatformType\",\n \"ym:s:<attribution>DirectSearchPhrase\",\n \"ym:s:<attribution>DisplayCampaign\",\n \"ym:s:<attribution>From\",\n \"ym:s:<attribution>HasGCLID\",\n \"ym:s:<attribution>HasSBCLID\",\n \"ym:s:<attribution>Messenger\",\n \"ym:s:<attribution>OpenstatAd\",\n \"ym:s:<attribution>OpenstatCampaign\",\n \"ym:s:<attribution>OpenstatService\",\n \"ym:s:<attribution>OpenstatSource\",\n \"ym:s:<attribution>QRCodeProvider\",\n \"ym:s:<attribution>RecommendationSystem\",\n \"ym:s:<attribution>ReferalSource\",\n \"ym:s:<attribution>SBCLID\",\n \"ym:s:<attribution>SearchEngineRoot\",\n \"ym:s:<attribution>SearchPhrase\",\n \"ym:s:<attribution>SocialNetwork\",\n \"ym:s:<attribution>SocialNetworkProfile\",\n \"ym:s:<attribution>SourceEngine\",\n \"ym:s:<attribution>TrafficSource\",\n \"ym:s:<attribution>UTMCampaign\",\n \"ym:s:<attribution>UTMContent\",\n \"ym:s:<attribution>UTMMedium\",\n \"ym:s:<attribution>UTMSource\",\n \"ym:s:<attribution>UTMTerm\",\n \"ym:s:<attribution>YandexRythmDetailed\",\n \"ym:s:adfoxBanner\",\n \"ym:s:adfoxBannerType\",\n \"ym:s:adfoxCampaign\",\n \"ym:s:adfoxHeaderBidding\",\n \"ym:s:adfoxLevel1\",\n \"ym:s:adfoxLevel1Chained\",\n \"ym:s:adfoxLevel2\",\n \"ym:s:adfoxLevel2Chained\",\n \"ym:s:adfoxLevel3Chained\",\n \"ym:s:adfoxLevel4Chained\",\n \"ym:s:adfoxOwner\",\n \"ym:s:adfoxPlace\",\n \"ym:s:adfoxPuidKey\",\n \"ym:s:adfoxPuidValue\",\n \"ym:s:adfoxSection\",\n \"ym:s:adfoxSite\",\n \"ym:s:adfoxUrlPathLevel1\",\n \"ym:s:adfoxUrlPathLevel2\",\n \"ym:s:adfoxUrlPathLevel3\",\n \"ym:s:adfoxUrlPathLevel4\",\n \"ym:s:adfoxYanImp\",\n \"ym:s:adfoxYanPage\",\n \"ym:s:ageInterval\",\n \"ym:s:bounce\",\n \"ym:s:browser\",\n \"ym:s:browserAndVersion\",\n \"ym:s:browserAndVersionMajor\",\n \"ym:s:browserCountry\",\n \"ym:s:browserDate\",\n \"ym:s:browserDatePeriod<group>\",\n \"ym:s:browserDateTime\",\n \"ym:s:browserDayOfMonth\",\n \"ym:s:browserDayOfWeek\",\n \"ym:s:browserDekaminute\",\n \"ym:s:browserEngine\",\n \"ym:s:browserEngineVersion1\",\n \"ym:s:browserEngineVersion2\",\n \"ym:s:browserEngineVersion3\",\n \"ym:s:browserEngineVersion4\",\n \"ym:s:browserHour\",\n \"ym:s:browserHourMinute\",\n \"ym:s:browserLanguage\",\n \"ym:s:browserMinute\",\n \"ym:s:browserMonth\",\n \"ym:s:browserStartOfDekaminute\",\n \"ym:s:browserStartOfHour\",\n \"ym:s:browserStartOfMinute\",\n \"ym:s:browserStartOfMonth\",\n \"ym:s:browserStartOfQuarter\",\n \"ym:s:browserStartOfWeek\",\n \"ym:s:browserStartOfYear\",\n \"ym:s:browserYear\",\n \"ym:s:clientID\",\n \"ym:s:clientTimeZone\",\n \"ym:s:cookieEnabled\",\n \"ym:s:counterID\",\n \"ym:s:date\",\n \"ym:s:datePeriod<group>\",\n \"ym:s:dateTime\",\n \"ym:s:dayOfMonth\",\n \"ym:s:dayOfWeek\",\n \"ym:s:daysSinceFirstVisit\",\n \"ym:s:daysSinceFirstVisitInterval\",\n \"ym:s:daysSincePreviousVisit\",\n \"ym:s:daysSincePreviousVisitInterval\",\n \"ym:s:dekaminute\",\n \"ym:s:deviceCategory\",\n \"ym:s:endURL\",\n \"ym:s:endURLDomain\",\n \"ym:s:endURLPath\",\n \"ym:s:endURLPathFull\",\n \"ym:s:endURLPathLevel1\",\n \"ym:s:endURLPathLevel2\",\n \"ym:s:endURLPathLevel3\",\n \"ym:s:endURLPathLevel4\",\n \"ym:s:endURLPathLevel5\",\n \"ym:s:endURLProto\",\n \"ym:s:EPromotionCreative\",\n \"ym:s:EPromotionCreativeSlot\",\n \"ym:s:EPromotionEventURL\",\n \"ym:s:EPromotionID\",\n \"ym:s:EPromotionName\",\n \"ym:s:EPromotionPosition\",\n \"ym:s:experimentAB<experiment_ab>\",\n \"ym:s:externalReferer\",\n \"ym:s:externalRefererDomain\",\n \"ym:s:externalRefererPath\",\n \"ym:s:externalRefererPathFull\",\n \"ym:s:externalRefererPathLevel1\",\n \"ym:s:externalRefererPathLevel2\",\n \"ym:s:externalRefererPathLevel3\",\n \"ym:s:externalRefererPathLevel4\",\n \"ym:s:externalRefererPathLevel5\",\n \"ym:s:externalRefererProto\",\n \"ym:s:firstVisitDate\",\n \"ym:s:firstVisitDatePeriod<group>\",\n \"ym:s:firstVisitDateTime\",\n \"ym:s:firstVisitDayOfMonth\",\n \"ym:s:firstVisitDayOfWeek\",\n \"ym:s:firstVisitDekaminute\",\n \"ym:s:firstVisitHour\",\n \"ym:s:firstVisitHourMinute\",\n \"ym:s:firstVisitMinute\",\n \"ym:s:firstVisitMonth\",\n \"ym:s:firstVisitStartOfDekaminute\",\n \"ym:s:firstVisitStartOfHour\",\n \"ym:s:firstVisitStartOfMinute\",\n \"ym:s:firstVisitStartOfMonth\",\n \"ym:s:firstVisitStartOfQuarter\",\n \"ym:s:firstVisitStartOfWeek\",\n \"ym:s:firstVisitStartOfYear\",\n \"ym:s:firstVisitYear\",\n \"ym:s:gender\",\n \"ym:s:goal\",\n \"ym:s:hasAdBlocker\",\n \"ym:s:hour\",\n \"ym:s:hourMinute\",\n \"ym:s:interest\",\n \"ym:s:interest2d1\",\n \"ym:s:interest2d2\",\n \"ym:s:interest2d3\",\n \"ym:s:ipAddress\",\n \"ym:s:isNewUser\",\n \"ym:s:isRobot\",\n \"ym:s:isRobotPro\",\n \"ym:s:isTurboPage\",\n \"ym:s:javascriptEnabled\",\n \"ym:s:marketSearchPhrase\",\n \"ym:s:minute\",\n \"ym:s:mobilePhone\",\n \"ym:s:mobilePhoneModel\",\n \"ym:s:month\",\n \"ym:s:offlineCallFirstTimeCaller\",\n \"ym:s:offlineCallHoldDuration\",\n \"ym:s:offlineCallMissed\",\n \"ym:s:offlineCallTag\",\n \"ym:s:offlineCallTalkDuration\",\n \"ym:s:offlineChatAnswered\",\n \"ym:s:offlineChatPlatform\",\n \"ym:s:offlineChatTag\",\n \"ym:s:operatingSystem\",\n \"ym:s:operatingSystemRoot\",\n \"ym:s:originalBounce\",\n \"ym:s:originalPageViews\",\n \"ym:s:originalVisitDuration\",\n \"ym:s:originalVisitDurationInterval\",\n \"ym:s:pageViews\",\n \"ym:s:pageViewsInterval\",\n \"ym:s:paramsLevel1\",\n \"ym:s:paramsLevel10\",\n \"ym:s:paramsLevel2\",\n \"ym:s:paramsLevel3\",\n \"ym:s:paramsLevel4\",\n \"ym:s:paramsLevel5\",\n \"ym:s:paramsLevel6\",\n \"ym:s:paramsLevel7\",\n \"ym:s:paramsLevel8\",\n \"ym:s:paramsLevel9\",\n \"ym:s:physicalScreenHeight\",\n \"ym:s:physicalScreenResolution\",\n \"ym:s:physicalScreenWidth\",\n \"ym:s:PProductBrand\",\n \"ym:s:PProductID\",\n \"ym:s:PProductName\",\n \"ym:s:previousVisitDate\",\n \"ym:s:previousVisitDatePeriod<group>\",\n \"ym:s:previousVisitDayOfMonth\",\n \"ym:s:previousVisitDayOfWeek\",\n \"ym:s:previousVisitMonth\",\n \"ym:s:previousVisitStartOfMonth\",\n \"ym:s:previousVisitStartOfQuarter\",\n \"ym:s:previousVisitStartOfWeek\",\n \"ym:s:previousVisitStartOfYear\",\n \"ym:s:previousVisitYear\",\n \"ym:s:productBrand\",\n \"ym:s:productBrandCart\",\n \"ym:s:productCategoryLevel1\",\n \"ym:s:productCategoryLevel2\",\n \"ym:s:productCategoryLevel3\",\n \"ym:s:productCategoryLevel4\",\n \"ym:s:productCategoryLevel5\",\n \"ym:s:productCoupon\",\n \"ym:s:productCurrency\",\n \"ym:s:productDiscount\",\n \"ym:s:productEventType\",\n \"ym:s:productEventURL\",\n \"ym:s:productID\",\n \"ym:s:productIDCart\",\n \"ym:s:productList\",\n \"ym:s:productName\",\n \"ym:s:productNameCart\",\n \"ym:s:productPosition\",\n \"ym:s:productPrice\",\n \"ym:s:productSum\",\n \"ym:s:productVariant\",\n \"ym:s:publisherArticleAuthor\",\n \"ym:s:publisherArticleFromTitle\",\n \"ym:s:publisherArticleHasFullRead\",\n \"ym:s:publisherArticleHasFullScroll\",\n \"ym:s:publisherArticleHasRecircled\",\n \"ym:s:publisherArticlePublishedDate\",\n \"ym:s:publisherArticleReadPart\",\n \"ym:s:publisherArticleRubric\",\n \"ym:s:publisherArticleRubric2\",\n \"ym:s:publisherArticleScrollDown\",\n \"ym:s:publisherArticleTitle\",\n \"ym:s:publisherArticleTopic\",\n \"ym:s:publisherArticleURL\",\n \"ym:s:publisherLongArticle\",\n \"ym:s:publisherPageFormat\",\n \"ym:s:publisherTrafficSource\",\n \"ym:s:publisherTrafficSource2\",\n \"ym:s:purchaseCoupon\",\n \"ym:s:purchaseExistsVisit\",\n \"ym:s:purchaseID\",\n \"ym:s:purchaseRevenue\",\n \"ym:s:purchaseRevenueVisit\",\n \"ym:s:referer\",\n \"ym:s:refererDomain\",\n \"ym:s:refererPath\",\n \"ym:s:refererPathFull\",\n \"ym:s:refererPathLevel1\",\n \"ym:s:refererPathLevel2\",\n \"ym:s:refererPathLevel3\",\n \"ym:s:refererPathLevel4\",\n \"ym:s:refererPathLevel5\",\n \"ym:s:refererProto\",\n \"ym:s:regionArea\",\n \"ym:s:regionCity\",\n \"ym:s:regionCitySize\",\n \"ym:s:regionContinent\",\n \"ym:s:regionCountry\",\n \"ym:s:regionDistrict\",\n \"ym:s:RWArticleURLHash\",\n \"ym:s:RWArticleURLPathLevel1Hash\",\n \"ym:s:RWArticleURLPathLevel2Hash\",\n \"ym:s:RWArticleURLPathLevel3Hash\",\n \"ym:s:RWArticleURLPathLevel4Hash\",\n \"ym:s:RWArticleURLPathLevel5Hash\",\n \"ym:s:RWConversion\",\n \"ym:s:RWURLHash\",\n \"ym:s:RWURLPathLevel1Hash\",\n \"ym:s:RWURLPathLevel2Hash\",\n \"ym:s:RWURLPathLevel3Hash\",\n \"ym:s:RWURLPathLevel4Hash\",\n \"ym:s:RWURLPathLevel5Hash\",\n \"ym:s:screenColors\",\n \"ym:s:screenFormat\",\n \"ym:s:screenHeight\",\n \"ym:s:screenOrientation\",\n \"ym:s:screenResolution\",\n \"ym:s:screenWidth\",\n \"ym:s:startOfDekaminute\",\n \"ym:s:startOfHour\",\n \"ym:s:startOfMinute\",\n \"ym:s:startOfMonth\",\n \"ym:s:startOfQuarter\",\n \"ym:s:startOfWeek\",\n \"ym:s:startOfYear\",\n \"ym:s:startURL\",\n \"ym:s:startURLDomain\",\n \"ym:s:startURLPath\",\n \"ym:s:startURLPathFull\",\n \"ym:s:startURLPathLevel1\",\n \"ym:s:startURLPathLevel2\",\n \"ym:s:startURLPathLevel3\",\n \"ym:s:startURLPathLevel4\",\n \"ym:s:startURLPathLevel5\",\n \"ym:s:startURLProto\",\n \"ym:s:thirdPartyCookieEnabled\",\n \"ym:s:topLevelDomain\",\n \"ym:s:userClientUserId\",\n \"ym:s:userParamsLevel1\",\n \"ym:s:userParamsLevel2\",\n \"ym:s:userParamsLevel3\",\n \"ym:s:userParamsLevel4\",\n \"ym:s:userParamsLevel5\",\n \"ym:s:userVisits\",\n \"ym:s:userVisitsInterval\",\n \"ym:s:userVisitsPeriod\",\n \"ym:s:userVisitsPeriodInterval\",\n \"ym:s:vacuumEvent\",\n \"ym:s:vacuumOrganization\",\n \"ym:s:vacuumSurface\",\n \"ym:s:visitDuration\",\n \"ym:s:visitDurationInterval\",\n \"ym:s:windowClientArea\",\n \"ym:s:windowClientHeight\",\n \"ym:s:windowClientWidth\",\n \"ym:s:yanBlockID\",\n \"ym:s:yanBlockSize\",\n \"ym:s:yanPageID\",\n \"ym:s:yanUrl\",\n \"ym:s:yanUrlPathLevel1\",\n \"ym:s:yanUrlPathLevel2\",\n \"ym:s:yanUrlPathLevel3\",\n \"ym:s:yanUrlPathLevel4\",\n \"ym:s:year\",\n \"ym:up:paramsLevel1\",\n \"ym:up:paramsLevel2\",\n \"ym:up:paramsLevel3\",\n \"ym:up:paramsLevel4\",\n \"ym:up:paramsLevel5\",\n]);\n\n/** Все известные метрики (538). */\nexport const METRIC_IDS: ReadonlySet<string> = new Set([\n \"ym:ad:<currency>ConvertedAdCost\",\n \"ym:ad:<currency>ConvertedAdCostPerVisit\",\n \"ym:ad:affinityIndexInterests\",\n \"ym:ad:affinityIndexInterests2\",\n \"ym:ad:anyGoalConversionRate\",\n \"ym:ad:anyGoalConverted<currency>Revenue\",\n \"ym:ad:anyGoalReaches\",\n \"ym:ad:anyGoalReachesPerUser\",\n \"ym:ad:anyGoalUserConversionRate\",\n \"ym:ad:anyGoalUsers\",\n \"ym:ad:anyGoalVisits\",\n \"ym:ad:avgDaysBetweenVisits\",\n \"ym:ad:avgDaysSinceFirstVisit\",\n \"ym:ad:avgParams\",\n \"ym:ad:avgVisitDurationSeconds\",\n \"ym:ad:blockedPercentage\",\n \"ym:ad:bounceRate\",\n \"ym:ad:clicks\",\n \"ym:ad:cookieEnabledPercentage\",\n \"ym:ad:ecommerce<currency>ConvertedRevenue\",\n \"ym:ad:ecommerce<currency>ConvertedRevenuePerPurchase\",\n \"ym:ad:ecommerce<currency>ConvertedRevenuePerVisit\",\n \"ym:ad:ecommerceCartPercents\",\n \"ym:ad:ecommerceCartVisits\",\n \"ym:ad:ecommerceDetailsPercents\",\n \"ym:ad:ecommerceDetailsVisits\",\n \"ym:ad:ecommercePurchasePercents\",\n \"ym:ad:ecommercePurchases\",\n \"ym:ad:ecommercePurchaseVisits\",\n \"ym:ad:ePromotionClicks\",\n \"ym:ad:ePromotionClicksUniq\",\n \"ym:ad:ePromotionClicksUserPercentage\",\n \"ym:ad:ePromotionImpressions\",\n \"ym:ad:ePromotionImpressionsUniq\",\n \"ym:ad:ePromotionImpressionsUserPercentage\",\n \"ym:ad:favoriteGoalsConversionRate\",\n \"ym:ad:favoriteGoalsConverted<currency>Revenue\",\n \"ym:ad:favoriteGoalsConverted<currency>RevenuePerVisit\",\n \"ym:ad:favoriteGoalsReaches\",\n \"ym:ad:favoriteGoalsReachesPerUser\",\n \"ym:ad:favoriteGoalsUserConversionRate\",\n \"ym:ad:favoriteGoalsUsers\",\n \"ym:ad:favoriteGoalsVisits\",\n \"ym:ad:GCLIDPercentage\",\n \"ym:ad:goal<goal_id>conversionRate\",\n \"ym:ad:goal<goal_id>converted<currency>AdCostPerVisit\",\n \"ym:ad:goal<goal_id>converted<currency>CPA\",\n \"ym:ad:goal<goal_id>converted<currency>Revenue\",\n \"ym:ad:goal<goal_id>reaches\",\n \"ym:ad:goal<goal_id>reachesPerUser\",\n \"ym:ad:goal<goal_id>userConversionRate\",\n \"ym:ad:goal<goal_id>users\",\n \"ym:ad:goal<goal_id>visits\",\n \"ym:ad:jsEnabledPercentage\",\n \"ym:ad:manPercentage\",\n \"ym:ad:mobilePercentage\",\n \"ym:ad:newUsers\",\n \"ym:ad:newUserVisitsPercentage\",\n \"ym:ad:oneDayBetweenVisitsPercentage\",\n \"ym:ad:oneVisitPerUserPercentage\",\n \"ym:ad:over32VisitsPerUserPercentage\",\n \"ym:ad:over54AgePercentage\",\n \"ym:ad:overMonthBetweenVisitsPercentage\",\n \"ym:ad:overYearSinceFirstVisitPercentage\",\n \"ym:ad:overYearUserRecencyPercentage\",\n \"ym:ad:pageDepth\",\n \"ym:ad:pageviews\",\n \"ym:ad:paramsNumber\",\n \"ym:ad:percentNewVisitors\",\n \"ym:ad:productBaskets<currency>ConvertedPrice\",\n \"ym:ad:productBasketsPrice\",\n \"ym:ad:productBasketsQuantity\",\n \"ym:ad:productBasketsRemoveUniq\",\n \"ym:ad:productBasketsRemoveUserPercentage\",\n \"ym:ad:productBasketsUniq\",\n \"ym:ad:productBasketsUserPercentage\",\n \"ym:ad:productClicks\",\n \"ym:ad:productClicksUniq\",\n \"ym:ad:productClicksUserPercentage\",\n \"ym:ad:productImpressions\",\n \"ym:ad:productImpressionsUniq\",\n \"ym:ad:productImpressionsUserPercentage\",\n \"ym:ad:productInListImpressions\",\n \"ym:ad:productInListImpressionsUniq\",\n \"ym:ad:productInListImpressionsUserPercentage\",\n \"ym:ad:productPurchased<currency>ConvertedPrice\",\n \"ym:ad:productPurchasedPrice\",\n \"ym:ad:productPurchasedQuantity\",\n \"ym:ad:productPurchasedUniq\",\n \"ym:ad:robotPercentage\",\n \"ym:ad:robotVisits\",\n \"ym:ad:sumParams\",\n \"ym:ad:thirdPartyCookieEnabledPercentage\",\n \"ym:ad:under18AgePercentage\",\n \"ym:ad:upTo24AgePercentage\",\n \"ym:ad:upTo31VisitsPerUserPercentage\",\n \"ym:ad:upTo34AgePercentage\",\n \"ym:ad:upTo3VisitsPerUserPercentage\",\n \"ym:ad:upTo44AgePercentage\",\n \"ym:ad:upTo54AgePercentage\",\n \"ym:ad:upTo7VisitsPerUserPercentage\",\n \"ym:ad:upToDaySinceFirstVisitPercentage\",\n \"ym:ad:upToDayUserRecencyPercentage\",\n \"ym:ad:upToMonthBetweenVisitsPercentage\",\n \"ym:ad:upToMonthSinceFirstVisitPercentage\",\n \"ym:ad:upToMonthUserRecencyPercentage\",\n \"ym:ad:upToQuarterSinceFirstVisitPercentage\",\n \"ym:ad:upToQuarterUserRecencyPercentage\",\n \"ym:ad:upToWeekBetweenVisitsPercentage\",\n \"ym:ad:upToWeekSinceFirstVisitPercentage\",\n \"ym:ad:upToWeekUserRecencyPercentage\",\n \"ym:ad:upToYearSinceFirstVisitPercentage\",\n \"ym:ad:upToYearUserRecencyPercentage\",\n \"ym:ad:userRecencyDays\",\n \"ym:ad:users\",\n \"ym:ad:usersPurchasePercentage\",\n \"ym:ad:visits\",\n \"ym:ad:visitsPerDay\",\n \"ym:ad:visitsPerHour\",\n \"ym:ad:visitsPerMinute\",\n \"ym:ad:womanPercentage\",\n \"ym:dl:blockedPercentage\",\n \"ym:dl:cookieEnabledPercentage\",\n \"ym:dl:downloads\",\n \"ym:dl:jsEnabledPercentage\",\n \"ym:dl:mobilePercentage\",\n \"ym:dl:pageviewsPerDay\",\n \"ym:dl:pageviewsPerHour\",\n \"ym:dl:pageviewsPerMinute\",\n \"ym:dl:thirdPartyCookieEnabledPercentage\",\n \"ym:dl:users\",\n \"ym:ep:avgEventParams\",\n \"ym:ep:eventPageViews\",\n \"ym:ep:eventParamsNumber\",\n \"ym:ep:eventsNumber\",\n \"ym:ep:sumEventParams\",\n \"ym:ev:affinityIndexInterests\",\n \"ym:ev:affinityIndexInterests2\",\n \"ym:ev:anyGoalConversionRate\",\n \"ym:ev:anyGoalConverted<currency>Revenue\",\n \"ym:ev:anyGoalReaches\",\n \"ym:ev:anyGoalReachesPerUser\",\n \"ym:ev:anyGoalUserConversionRate\",\n \"ym:ev:anyGoalUsers\",\n \"ym:ev:anyGoalVisits\",\n \"ym:ev:avgDaysBetweenVisits\",\n \"ym:ev:avgDaysSinceFirstVisit\",\n \"ym:ev:avgOriginalVisitDurationSeconds\",\n \"ym:ev:avgParams\",\n \"ym:ev:avgVisitDurationSeconds\",\n \"ym:ev:blockedPercentage\",\n \"ym:ev:bounceRate\",\n \"ym:ev:cdpOrders<currency>AverageCheque\",\n \"ym:ev:cdpOrders<currency>Profit\",\n \"ym:ev:cdpOrders<currency>Revenue\",\n \"ym:ev:cdpOrdersAllOrders\",\n \"ym:ev:cdpOrdersCancelled\",\n \"ym:ev:cdpOrdersConversionIntoOrder\",\n \"ym:ev:cdpOrdersConversionIntoPayment\",\n \"ym:ev:cdpOrdersInProgress\",\n \"ym:ev:cdpOrdersOther\",\n \"ym:ev:cdpOrdersPayed\",\n \"ym:ev:cdpOrdersSpam\",\n \"ym:ev:cookieEnabledPercentage\",\n \"ym:ev:ecommerce<currency>ConvertedRevenue\",\n \"ym:ev:ecommerce<currency>ConvertedRevenuePerPurchase\",\n \"ym:ev:ecommerce<currency>ConvertedRevenuePerVisit\",\n \"ym:ev:ecommerceCartPercents\",\n \"ym:ev:ecommerceCartVisits\",\n \"ym:ev:ecommerceDetailsPercents\",\n \"ym:ev:ecommerceDetailsVisits\",\n \"ym:ev:ecommercePurchasePercents\",\n \"ym:ev:ecommercePurchases\",\n \"ym:ev:ecommercePurchaseVisits\",\n \"ym:ev:ePromotionClicks\",\n \"ym:ev:ePromotionClicksUniq\",\n \"ym:ev:ePromotionClicksUserPercentage\",\n \"ym:ev:ePromotionImpressions\",\n \"ym:ev:ePromotionImpressionsUniq\",\n \"ym:ev:ePromotionImpressionsUserPercentage\",\n \"ym:ev:expense<currency>CPC\",\n \"ym:ev:expense<currency>EcommerceCPA\",\n \"ym:ev:expense<currency>EcommerceCRR\",\n \"ym:ev:expense<currency>EcommerceROI\",\n \"ym:ev:expense<currency>FavoriteGoalsCPA\",\n \"ym:ev:expense<currency>FavoriteGoalsCRR\",\n \"ym:ev:expense<currency>FavoriteGoalsROI\",\n \"ym:ev:expense<currency>FavoriteGoalsUserCPA\",\n \"ym:ev:expense<currency>FavoriteGoalsVisitCPA\",\n \"ym:ev:expenseClicks\",\n \"ym:ev:expenses<currency>\",\n \"ym:ev:favoriteGoalsConversionRate\",\n \"ym:ev:favoriteGoalsConverted<currency>Revenue\",\n \"ym:ev:favoriteGoalsConverted<currency>RevenuePerVisit\",\n \"ym:ev:favoriteGoalsReaches\",\n \"ym:ev:favoriteGoalsReachesPerUser\",\n \"ym:ev:favoriteGoalsUserConversionRate\",\n \"ym:ev:favoriteGoalsUsers\",\n \"ym:ev:favoriteGoalsVisits\",\n \"ym:ev:GCLIDPercentage\",\n \"ym:ev:goal<goal_id>conversionRate\",\n \"ym:ev:goal<goal_id>converted<currency>Revenue\",\n \"ym:ev:goal<goal_id>expense<currency>CRR\",\n \"ym:ev:goal<goal_id>expense<currency>ReachCPA\",\n \"ym:ev:goal<goal_id>expense<currency>ROI\",\n \"ym:ev:goal<goal_id>expense<currency>UserCPA\",\n \"ym:ev:goal<goal_id>expense<currency>VisitCPA\",\n \"ym:ev:goal<goal_id>reaches\",\n \"ym:ev:goal<goal_id>reachesPerUser\",\n \"ym:ev:goal<goal_id>userConversionRate\",\n \"ym:ev:goal<goal_id>users\",\n \"ym:ev:goal<goal_id>visits\",\n \"ym:ev:jsEnabledPercentage\",\n \"ym:ev:manPercentage\",\n \"ym:ev:mobilePercentage\",\n \"ym:ev:newUsers\",\n \"ym:ev:newUserVisitsPercentage\",\n \"ym:ev:oneDayBetweenVisitsPercentage\",\n \"ym:ev:oneVisitPerUserPercentage\",\n \"ym:ev:originalBounceRate\",\n \"ym:ev:originalPageDepth\",\n \"ym:ev:originalPageviews\",\n \"ym:ev:over32VisitsPerUserPercentage\",\n \"ym:ev:over54AgePercentage\",\n \"ym:ev:overMonthBetweenVisitsPercentage\",\n \"ym:ev:overYearSinceFirstVisitPercentage\",\n \"ym:ev:overYearUserRecencyPercentage\",\n \"ym:ev:pageDepth\",\n \"ym:ev:pageviews\",\n \"ym:ev:paramsNumber\",\n \"ym:ev:percentNewVisitors\",\n \"ym:ev:productBaskets<currency>ConvertedPrice\",\n \"ym:ev:productBasketsPrice\",\n \"ym:ev:productBasketsQuantity\",\n \"ym:ev:productBasketsRemoveUniq\",\n \"ym:ev:productBasketsRemoveUserPercentage\",\n \"ym:ev:productBasketsUniq\",\n \"ym:ev:productBasketsUserPercentage\",\n \"ym:ev:productClicks\",\n \"ym:ev:productClicksUniq\",\n \"ym:ev:productClicksUserPercentage\",\n \"ym:ev:productImpressions\",\n \"ym:ev:productImpressionsUniq\",\n \"ym:ev:productImpressionsUserPercentage\",\n \"ym:ev:productInListImpressions\",\n \"ym:ev:productInListImpressionsUniq\",\n \"ym:ev:productInListImpressionsUserPercentage\",\n \"ym:ev:productPurchased<currency>ConvertedPrice\",\n \"ym:ev:productPurchasedPrice\",\n \"ym:ev:productPurchasedQuantity\",\n \"ym:ev:productPurchasedUniq\",\n \"ym:ev:robotPercentage\",\n \"ym:ev:robotVisits\",\n \"ym:ev:sumParams\",\n \"ym:ev:thirdPartyCookieEnabledPercentage\",\n \"ym:ev:under18AgePercentage\",\n \"ym:ev:upTo24AgePercentage\",\n \"ym:ev:upTo31VisitsPerUserPercentage\",\n \"ym:ev:upTo34AgePercentage\",\n \"ym:ev:upTo3VisitsPerUserPercentage\",\n \"ym:ev:upTo44AgePercentage\",\n \"ym:ev:upTo54AgePercentage\",\n \"ym:ev:upTo7VisitsPerUserPercentage\",\n \"ym:ev:upToDaySinceFirstVisitPercentage\",\n \"ym:ev:upToDayUserRecencyPercentage\",\n \"ym:ev:upToMonthBetweenVisitsPercentage\",\n \"ym:ev:upToMonthSinceFirstVisitPercentage\",\n \"ym:ev:upToMonthUserRecencyPercentage\",\n \"ym:ev:upToQuarterSinceFirstVisitPercentage\",\n \"ym:ev:upToQuarterUserRecencyPercentage\",\n \"ym:ev:upToWeekBetweenVisitsPercentage\",\n \"ym:ev:upToWeekSinceFirstVisitPercentage\",\n \"ym:ev:upToWeekUserRecencyPercentage\",\n \"ym:ev:upToYearSinceFirstVisitPercentage\",\n \"ym:ev:upToYearUserRecencyPercentage\",\n \"ym:ev:userRecencyDays\",\n \"ym:ev:users\",\n \"ym:ev:usersPurchasePercentage\",\n \"ym:ev:visits\",\n \"ym:ev:visitsPerDay\",\n \"ym:ev:visitsPerHour\",\n \"ym:ev:visitsPerMinute\",\n \"ym:ev:womanPercentage\",\n \"ym:pv:blockedPercentage\",\n \"ym:pv:cookieEnabledPercentage\",\n \"ym:pv:jsEnabledPercentage\",\n \"ym:pv:mobilePercentage\",\n \"ym:pv:pageviews\",\n \"ym:pv:pageviewsPerDay\",\n \"ym:pv:pageviewsPerHour\",\n \"ym:pv:pageviewsPerMinute\",\n \"ym:pv:thirdPartyCookieEnabledPercentage\",\n \"ym:pv:users\",\n \"ym:s:adfoxARPU\",\n \"ym:s:adfoxClicks\",\n \"ym:s:adfoxCountEvent1\",\n \"ym:s:adfoxCountEvent10\",\n \"ym:s:adfoxCountEvent11\",\n \"ym:s:adfoxCountEvent12\",\n \"ym:s:adfoxCountEvent13\",\n \"ym:s:adfoxCountEvent14\",\n \"ym:s:adfoxCountEvent15\",\n \"ym:s:adfoxCountEvent16\",\n \"ym:s:adfoxCountEvent17\",\n \"ym:s:adfoxCountEvent18\",\n \"ym:s:adfoxCountEvent19\",\n \"ym:s:adfoxCountEvent2\",\n \"ym:s:adfoxCountEvent20\",\n \"ym:s:adfoxCountEvent21\",\n \"ym:s:adfoxCountEvent22\",\n \"ym:s:adfoxCountEvent23\",\n \"ym:s:adfoxCountEvent24\",\n \"ym:s:adfoxCountEvent25\",\n \"ym:s:adfoxCountEvent26\",\n \"ym:s:adfoxCountEvent27\",\n \"ym:s:adfoxCountEvent28\",\n \"ym:s:adfoxCountEvent29\",\n \"ym:s:adfoxCountEvent3\",\n \"ym:s:adfoxCountEvent30\",\n \"ym:s:adfoxCountEvent4\",\n \"ym:s:adfoxCountEvent5\",\n \"ym:s:adfoxCountEvent6\",\n \"ym:s:adfoxCountEvent7\",\n \"ym:s:adfoxCountEvent8\",\n \"ym:s:adfoxCountEvent9\",\n \"ym:s:adfoxCPMV\",\n \"ym:s:adfoxECPM\",\n \"ym:s:adfoxPrice\",\n \"ym:s:adfoxPriceGoogle\",\n \"ym:s:adfoxPriceHeaderBidding\",\n \"ym:s:adfoxPricePerHit\",\n \"ym:s:adfoxPricePerUser\",\n \"ym:s:adfoxPricePerVisit\",\n \"ym:s:adfoxPriceStrict\",\n \"ym:s:adfoxPriceYan\",\n \"ym:s:adfoxRenders\",\n \"ym:s:adfoxRendersDefault\",\n \"ym:s:adfoxRendersDefaultShare\",\n \"ym:s:adfoxRendersPerHit\",\n \"ym:s:adfoxRendersPerUser\",\n \"ym:s:adfoxRendersPerVisit\",\n \"ym:s:adfoxRequests\",\n \"ym:s:adfoxRPM\",\n \"ym:s:adfoxShows\",\n \"ym:s:adfoxVisibility\",\n \"ym:s:affinityIndexInterests\",\n \"ym:s:affinityIndexInterests2\",\n \"ym:s:anyGoalConversionRate\",\n \"ym:s:anyGoalConverted<currency>Revenue\",\n \"ym:s:anyGoalReaches\",\n \"ym:s:anyGoalReachesPerUser\",\n \"ym:s:anyGoalUserConversionRate\",\n \"ym:s:anyGoalUsers\",\n \"ym:s:anyGoalVisits\",\n \"ym:s:avgDaysBetweenVisits\",\n \"ym:s:avgDaysSinceFirstVisit\",\n \"ym:s:avgOriginalVisitDurationSeconds\",\n \"ym:s:avgParams\",\n \"ym:s:avgPublisherArticleInvolvedTimeSeconds\",\n \"ym:s:avgUserParams\",\n \"ym:s:avgVisitDurationSeconds\",\n \"ym:s:blockedPercentage\",\n \"ym:s:bounceRate\",\n \"ym:s:cdpOrders<currency>AverageCheque\",\n \"ym:s:cdpOrders<currency>Profit\",\n \"ym:s:cdpOrders<currency>Revenue\",\n \"ym:s:cdpOrdersAllOrders\",\n \"ym:s:cdpOrdersCancelled\",\n \"ym:s:cdpOrdersConversionIntoOrder\",\n \"ym:s:cdpOrdersConversionIntoPayment\",\n \"ym:s:cdpOrdersInProgress\",\n \"ym:s:cdpOrdersOther\",\n \"ym:s:cdpOrdersPayed\",\n \"ym:s:cdpOrdersSpam\",\n \"ym:s:cookieEnabledPercentage\",\n \"ym:s:crossDeviceUsers\",\n \"ym:s:ecommerce<currency>ConvertedRevenue\",\n \"ym:s:ecommerce<currency>ConvertedRevenuePerPurchase\",\n \"ym:s:ecommerce<currency>ConvertedRevenuePerVisit\",\n \"ym:s:ecommerceCartPercents\",\n \"ym:s:ecommerceCartVisits\",\n \"ym:s:ecommerceDetailsPercents\",\n \"ym:s:ecommerceDetailsVisits\",\n \"ym:s:ecommercePurchasePercents\",\n \"ym:s:ecommercePurchases\",\n \"ym:s:ecommercePurchaseVisits\",\n \"ym:s:ePromotionClicks\",\n \"ym:s:ePromotionClicksUniq\",\n \"ym:s:ePromotionClicksUserPercentage\",\n \"ym:s:ePromotionImpressions\",\n \"ym:s:ePromotionImpressionsUniq\",\n \"ym:s:ePromotionImpressionsUserPercentage\",\n \"ym:s:favoriteGoalsConversionRate\",\n \"ym:s:favoriteGoalsConverted<currency>Revenue\",\n \"ym:s:favoriteGoalsConverted<currency>RevenuePerVisit\",\n \"ym:s:favoriteGoalsReaches\",\n \"ym:s:favoriteGoalsReachesPerUser\",\n \"ym:s:favoriteGoalsUserConversionRate\",\n \"ym:s:favoriteGoalsUsers\",\n \"ym:s:favoriteGoalsVisits\",\n \"ym:s:GCLIDPercentage\",\n \"ym:s:goal<goal_id>conversionRate\",\n \"ym:s:goal<goal_id>converted<currency>Revenue\",\n \"ym:s:goal<goal_id>reaches\",\n \"ym:s:goal<goal_id>reachesPerUser\",\n \"ym:s:goal<goal_id>userConversionRate\",\n \"ym:s:goal<goal_id>users\",\n \"ym:s:goal<goal_id>visits\",\n \"ym:s:jsEnabledPercentage\",\n \"ym:s:manPercentage\",\n \"ym:s:mobilePercentage\",\n \"ym:s:newUsers\",\n \"ym:s:newUserVisitsPercentage\",\n \"ym:s:offlineCall<currency>ConvertedRevenue\",\n \"ym:s:offlineCall<currency>ConvertedRevenueAvg\",\n \"ym:s:offlineCallDurationAvg\",\n \"ym:s:offlineCallHoldDurationTillAnswerAvg\",\n \"ym:s:offlineCallHoldDurationTillMissAvg\",\n \"ym:s:offlineCalls\",\n \"ym:s:offlineCallsFirstTimeCaller\",\n \"ym:s:offlineCallsFirstTimeCallerPercentage\",\n \"ym:s:offlineCallsMissed\",\n \"ym:s:offlineCallsMissedPercentage\",\n \"ym:s:offlineCallsUniq\",\n \"ym:s:offlineCallTalkDurationAvg\",\n \"ym:s:offlineChats\",\n \"ym:s:offlineChatsMissed\",\n \"ym:s:offlineChatsMissedPercentage\",\n \"ym:s:oneDayBetweenVisitsPercentage\",\n \"ym:s:oneVisitPerUserPercentage\",\n \"ym:s:originalBounceRate\",\n \"ym:s:originalPageDepth\",\n \"ym:s:originalPageviews\",\n \"ym:s:over32VisitsPerUserPercentage\",\n \"ym:s:over54AgePercentage\",\n \"ym:s:overMonthBetweenVisitsPercentage\",\n \"ym:s:overYearSinceFirstVisitPercentage\",\n \"ym:s:overYearUserRecencyPercentage\",\n \"ym:s:pageDepth\",\n \"ym:s:pageviews\",\n \"ym:s:paramsNumber\",\n \"ym:s:percentNewVisitors\",\n \"ym:s:productBaskets<currency>ConvertedPrice\",\n \"ym:s:productBasketsPrice\",\n \"ym:s:productBasketsQuantity\",\n \"ym:s:productBasketsRemoveUniq\",\n \"ym:s:productBasketsRemoveUserPercentage\",\n \"ym:s:productBasketsUniq\",\n \"ym:s:productBasketsUserPercentage\",\n \"ym:s:productClicks\",\n \"ym:s:productClicksUniq\",\n \"ym:s:productClicksUserPercentage\",\n \"ym:s:productImpressions\",\n \"ym:s:productImpressionsUniq\",\n \"ym:s:productImpressionsUserPercentage\",\n \"ym:s:productInListImpressions\",\n \"ym:s:productInListImpressionsUniq\",\n \"ym:s:productInListImpressionsUserPercentage\",\n \"ym:s:productPurchased<currency>ConvertedPrice\",\n \"ym:s:productPurchasedPrice\",\n \"ym:s:productPurchasedQuantity\",\n \"ym:s:productPurchasedUniq\",\n \"ym:s:publisherArticleFullReadShare\",\n \"ym:s:publisherArticleRecirculation\",\n \"ym:s:publisherArticleUsersRecircled\",\n \"ym:s:publisherArticleViewsFullScrollShare\",\n \"ym:s:publisherMobileOrTabletViews\",\n \"ym:s:publisherMobileOrTabletViewsShare\",\n \"ym:s:publisherusers\",\n \"ym:s:publisherviews\",\n \"ym:s:publisherViewsFullRead\",\n \"ym:s:publisherViewsFullScroll\",\n \"ym:s:publisherviewsPerDay\",\n \"ym:s:publisherviewsPerHour\",\n \"ym:s:publisherviewsPerMinute\",\n \"ym:s:robotPercentage\",\n \"ym:s:robotProPercentage\",\n \"ym:s:robotVisits\",\n \"ym:s:rwArticleClicks\",\n \"ym:s:rwArticleCTR\",\n \"ym:s:rwArticleShows\",\n \"ym:s:rwArticleVisibility\",\n \"ym:s:rwClicksSum\",\n \"ym:s:rwCTR\",\n \"ym:s:rwShows\",\n \"ym:s:rwVisibility\",\n \"ym:s:sumParams\",\n \"ym:s:sumPublisherArticleInvolvedTimeSeconds\",\n \"ym:s:sumUserParams\",\n \"ym:s:thirdPartyCookieEnabledPercentage\",\n \"ym:s:under18AgePercentage\",\n \"ym:s:upTo24AgePercentage\",\n \"ym:s:upTo31VisitsPerUserPercentage\",\n \"ym:s:upTo34AgePercentage\",\n \"ym:s:upTo3VisitsPerUserPercentage\",\n \"ym:s:upTo44AgePercentage\",\n \"ym:s:upTo54AgePercentage\",\n \"ym:s:upTo7VisitsPerUserPercentage\",\n \"ym:s:upToDaySinceFirstVisitPercentage\",\n \"ym:s:upToDayUserRecencyPercentage\",\n \"ym:s:upToMonthBetweenVisitsPercentage\",\n \"ym:s:upToMonthSinceFirstVisitPercentage\",\n \"ym:s:upToMonthUserRecencyPercentage\",\n \"ym:s:upToQuarterSinceFirstVisitPercentage\",\n \"ym:s:upToQuarterUserRecencyPercentage\",\n \"ym:s:upToWeekBetweenVisitsPercentage\",\n \"ym:s:upToWeekSinceFirstVisitPercentage\",\n \"ym:s:upToWeekUserRecencyPercentage\",\n \"ym:s:upToYearSinceFirstVisitPercentage\",\n \"ym:s:upToYearUserRecencyPercentage\",\n \"ym:s:userParamsNumber\",\n \"ym:s:userRecencyDays\",\n \"ym:s:users\",\n \"ym:s:usersPurchasePercentage\",\n \"ym:s:vacuumevents\",\n \"ym:s:vacuumeventsPerUser\",\n \"ym:s:vacuumusers\",\n \"ym:s:visits\",\n \"ym:s:visitsPerDay\",\n \"ym:s:visitsPerHour\",\n \"ym:s:visitsPerMinute\",\n \"ym:s:womanPercentage\",\n \"ym:s:yanARPU\",\n \"ym:s:yanCPMV\",\n \"ym:s:yanECPM\",\n \"ym:s:yanPartnerPrice\",\n \"ym:s:yanRenders\",\n \"ym:s:yanRendersPerHit\",\n \"ym:s:yanRendersPerUser\",\n \"ym:s:yanRendersPerVisit\",\n \"ym:s:yanRequests\",\n \"ym:s:yanRevenuePerHit\",\n \"ym:s:yanRevenuePerVisit\",\n \"ym:s:yanRPM\",\n \"ym:s:yanShows\",\n \"ym:s:yanVisibility\",\n \"ym:up:params\",\n \"ym:up:users\",\n]);\n\n/** Все известные шаблоны отчётов (93). */\nexport const PRESET_IDS: ReadonlySet<string> = new Set([\n \"adfox_defaults\",\n \"adfox_geo\",\n \"adfox_header_bidding\",\n \"adfox_invent\",\n \"adfox_puids\",\n \"adfox_shows\",\n \"adfox_sources\",\n \"adfox_urls\",\n \"adv_engine\",\n \"age\",\n \"age_gender\",\n \"basket\",\n \"basket_products\",\n \"content_entrance\",\n \"content_exit\",\n \"content_user_params\",\n \"content_visit_params\",\n \"conversion\",\n \"coupon\",\n \"deepness_depth\",\n \"deepness_time\",\n \"downloads\",\n \"ecom_funnel\",\n \"event_params\",\n \"expenses\",\n \"experiment_ab\",\n \"gender\",\n \"geo_country\",\n \"goal_params\",\n \"hidden_metrics_goal\",\n \"hourly\",\n \"interests\",\n \"interests2\",\n \"loyalty_newness\",\n \"loyalty_period\",\n \"loyalty_recency\",\n \"loyalty_visits\",\n \"offline_calls_quality\",\n \"offline_calls_sources\",\n \"orders_sources\",\n \"popular\",\n \"product_list\",\n \"promo_campaigns\",\n \"publishers_authors\",\n \"publishers_rubrics\",\n \"publishers_sources\",\n \"publishers_thematics\",\n \"purchase\",\n \"recommendation_widget_articles\",\n \"recommendation_widget_conversion\",\n \"recommendation_widget_page\",\n \"resolution_map\",\n \"search_engines\",\n \"sources_direct_clicks\",\n \"sources_direct_platforms\",\n \"sources_direct_platforms_types\",\n \"sources_direct_summary\",\n \"sources_expenses_and_roi\",\n \"sources_messenger\",\n \"sources_recommend\",\n \"sources_search_phrases\",\n \"sources_sites\",\n \"sources_social\",\n \"sources_summary\",\n \"tags_from\",\n \"tags_gclid\",\n \"tags_openstat\",\n \"tags_u_t_m\",\n \"tech_browsers\",\n \"tech_cookies\",\n \"tech_devices\",\n \"tech_display\",\n \"tech_display_groups\",\n \"tech_java_script\",\n \"tech_platforms\",\n \"tech_third_party_cookies\",\n \"titles\",\n \"top_brands\",\n \"top_products\",\n \"traffic\",\n \"turbo_app\",\n \"turbo_pages\",\n \"url_params\",\n \"vacuum\",\n \"visits_by_client_user_id\",\n \"visits_by_user_param\",\n \"yan\",\n \"yan_adb\",\n \"yan_browsers\",\n \"yan_device\",\n \"yan_geo\",\n \"yan_sources\",\n \"yandex_rythm\",\n]);\n","/**\n * Реестр известных группировок, метрик и шаблонов — извлечён из документации Метрики.\n *\n * Используется для валидации запросов до отправки: неизвестное имя ловится локально,\n * а не превращается в `400 invalid_parameter` после расхода квоты.\n */\nimport {\n DIMENSION_IDS,\n METRIC_IDS,\n PRESET_IDS,\n contractParsedAt,\n contractSourceSha256,\n contractVersion,\n} from './registry.generated.ts';\n\nexport { DIMENSION_IDS, METRIC_IDS, PRESET_IDS, contractParsedAt, contractSourceSha256, contractVersion };\n\n/** Пространства имён API отчётов: визиты, просмотры, реклама, расходы, события, загрузки, параметры. */\nexport type Namespace = 's' | 'pv' | 'ad' | 'ev' | 'ep' | 'dl' | 'up';\n\nconst NAMESPACE_RE = /^ym:([a-z]{1,3}):/;\n\n/** Возвращает пространство имён идентификатора: `ym:s:visits` → `s`. */\nexport function namespaceOf(id: string): string | undefined {\n return NAMESPACE_RE.exec(id)?.[1];\n}\n\n/**\n * Приводит конкретный идентификатор к форме из документации, заменяя подставленные\n * значения параметров обратно на плейсхолдеры: `ym:s:lastSearchPhrase` → `ym:s:<attribution>SearchPhrase`.\n */\nconst ATTRIBUTIONS = [\n 'cross_device_first',\n 'cross_device_last_significant',\n 'last_significant',\n 'last_yandex_direct_click',\n 'automatic',\n 'first',\n 'last',\n] as const;\n\n/** Модели атрибуции, поддерживаемые API отчётов. */\nexport type Attribution = (typeof ATTRIBUTIONS)[number];\n\n/**\n * Модели, которые с 25 июня 2026 года схлопываются в ближайшие аналоги.\n * Библиотека их принимает, но предупреждает.\n */\nexport const DEPRECATED_ATTRIBUTIONS: Readonly<Record<string, Attribution>> = {\n first: 'cross_device_first',\n last_significant: 'cross_device_last_significant',\n last_yandex_direct_click: 'automatic',\n};\n\n/** Валюты, доступные в параметре `<currency>`. */\nexport type Currency = 'RUB' | 'USD' | 'EUR' | 'YND';\n\n/** Известна ли группировка (идентификатор в форме документации, с плейсхолдерами). */\nexport function hasDimension(id: string): boolean {\n return DIMENSION_IDS.has(id);\n}\n\n/** Известна ли метрика (идентификатор в форме документации, с плейсхолдерами). */\nexport function hasMetric(id: string): boolean {\n return METRIC_IDS.has(id);\n}\n\n/** Известен ли шаблон отчёта. */\nexport function hasPreset(id: string): boolean {\n return PRESET_IDS.has(id);\n}\n","/**\n * Ошибки API Метрики.\n *\n * Тело ошибки: `{ errors: [{ error_type, message, location }], code, message }`.\n * Типы ошибок описаны в разделе «Описание ошибок в API».\n */\n\n/** Один элемент массива `errors` в ответе API. */\nexport interface ApiErrorDetail {\n error_type: string;\n message?: string;\n location?: string;\n}\n\n/** Тело ошибочного ответа API Метрики. */\nexport interface ApiErrorBody {\n errors?: ApiErrorDetail[];\n code?: number;\n message?: string;\n}\n\n/** Базовая ошибка API Метрики. */\nexport class MetrikaError extends Error {\n readonly status: number;\n readonly errorType: string;\n readonly details: ApiErrorDetail[];\n readonly requestUrl: string;\n\n constructor(message: string, options: {\n status: number;\n errorType: string;\n details: ApiErrorDetail[];\n requestUrl: string;\n }) {\n super(message);\n this.name = new.target.name;\n this.status = options.status;\n this.errorType = options.errorType;\n this.details = options.details;\n this.requestUrl = options.requestUrl;\n }\n}\n\n/** 429: превышена одна из квот. Запрос имеет смысл повторить позже. */\nexport class QuotaError extends MetrikaError {\n /** Через сколько миллисекунд разумно повторить попытку. */\n readonly retryAfterMs: number;\n\n constructor(\n message: string,\n options: ConstructorParameters<typeof MetrikaError>[1] & { retryAfterMs: number },\n ) {\n super(message, options);\n this.retryAfterMs = options.retryAfterMs;\n }\n}\n\n/** 401/403: нет токена, токен недействителен или нет доступа к счётчику. */\nexport class AuthError extends MetrikaError {}\n\n/** 400: неверный параметр запроса — обычно исчезнувшая или опечатанная группировка. */\nexport class InvalidRequestError extends MetrikaError {}\n\n/** 404: объект не найден. */\nexport class NotFoundError extends MetrikaError {}\n\n/** 5xx и 504: временная проблема на стороне сервиса. */\nexport class ServerError extends MetrikaError {}\n\n/** Ошибка валидации запроса на стороне библиотеки — до обращения к API. */\nexport class RequestValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'RequestValidationError';\n }\n}\n\nconst AUTH_TYPES = new Set(['invalid_token', 'unauthorized', 'access_denied', 'counter_in_connect']);\nconst SERVER_TYPES = new Set(['backend_error', 'timeout']);\n\n/**\n * Ошибки квот, для которых повтор через несколько секунд бессмыслен: суточные лимиты\n * сбрасываются в 00:00 GMT, пятиминутные — через 5 минут.\n */\nconst QUOTA_RETRY_MS: Readonly<Record<string, number>> = {\n quota_requests_by_ip: 1_000,\n quota_parallel_requests: 1_000,\n quota_requests_by_uid: 5 * 60_000,\n quota_requests_by_counter_id: 5 * 60_000,\n quota_delegate_requests: 60 * 60_000,\n quota_grants_requests: 60 * 60_000,\n};\n\n/** Строит типизированную ошибку по HTTP-статусу и телу ответа. */\nexport function toMetrikaError(\n status: number,\n body: ApiErrorBody | undefined,\n requestUrl: string,\n): MetrikaError {\n const details = body?.errors ?? [];\n const errorType = details[0]?.error_type ?? `http_${status}`;\n const message =\n details[0]?.message ?? body?.message ?? `Запрос к API Метрики завершился со статусом ${status}`;\n const options = { status, errorType, details, requestUrl };\n const full = `${message} (${errorType}, HTTP ${status})`;\n\n if (status === 429 || errorType.startsWith('quota_')) {\n return new QuotaError(full, {\n ...options,\n retryAfterMs: QUOTA_RETRY_MS[errorType] ?? 60_000,\n });\n }\n if (status === 401 || status === 403 || AUTH_TYPES.has(errorType)) {\n return new AuthError(full, options);\n }\n if (status === 404 || errorType === 'not_found') return new NotFoundError(full, options);\n if (status >= 500 || SERVER_TYPES.has(errorType)) return new ServerError(full, options);\n return new InvalidRequestError(full, options);\n}\n\n/** Стоит ли повторять запрос после этой ошибки. */\nexport function isRetryable(error: unknown): boolean {\n return error instanceof QuotaError || error instanceof ServerError;\n}\n","/**\n * Локальный лимитер под квоты Яндекс Метрики.\n *\n * Квоты из раздела «Квотирование»:\n * - 30 запросов в секунду с одного IP;\n * - 3 параллельных запроса на пользователя;\n * - 5000 запросов в сутки на пользователя (сброс в 00:00 GMT);\n * - 200 запросов за 5 минут к `/stat/v1/data`.\n *\n * Дешевле подождать локально, чем словить 429 и потерять запрос.\n */\n\n/** Группа методов: отчёты считаются отдельной пятиминутной квотой. */\nexport type QuotaScope = 'report' | 'management';\n\nexport interface RateLimitOptions {\n /** Одновременных запросов. По умолчанию 3 — квота на пользователя. */\n maxConcurrent?: number;\n /** Запросов в секунду. По умолчанию 30 — квота на IP. */\n perSecond?: number;\n /** Запросов к `/stat/v1/data` за 5 минут. По умолчанию 200. */\n reportsPer5Min?: number;\n /** Запросов в сутки. По умолчанию 5000, сброс в 00:00 GMT. */\n perDay?: number;\n /** Подменяемый источник времени и сна — для тестов. */\n now?: () => number;\n sleep?: (ms: number) => Promise<void>;\n}\n\nconst SECOND = 1_000;\nconst FIVE_MINUTES = 5 * 60 * 1_000;\n\nconst defaultSleep = (ms: number): Promise<void> =>\n new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n\n/** Номер суток по Гринвичу — квота сбрасывается в 00:00 GMT, а не скользящим окном. */\nfunction gmtDay(timestamp: number): number {\n return Math.floor(timestamp / 86_400_000);\n}\n\n/** Убирает из окна отметки старше `windowMs`. */\nfunction prune(timestamps: number[], now: number, windowMs: number): void {\n const cutoff = now - windowMs;\n let drop = 0;\n while (drop < timestamps.length && timestamps[drop]! <= cutoff) drop += 1;\n if (drop > 0) timestamps.splice(0, drop);\n}\n\nexport class RateLimiter {\n private readonly maxConcurrent: number;\n private readonly perSecond: number;\n private readonly reportsPer5Min: number;\n private readonly perDay: number;\n private readonly now: () => number;\n private readonly sleep: (ms: number) => Promise<void>;\n\n private inFlight = 0;\n private readonly secondWindow: number[] = [];\n private readonly reportWindow: number[] = [];\n private dayKey = -1;\n private dayCount = 0;\n /** Очередь ожидающих: разбуженные проверяют условия заново. */\n private readonly waiters: (() => void)[] = [];\n\n constructor(options: RateLimitOptions = {}) {\n this.maxConcurrent = options.maxConcurrent ?? 3;\n this.perSecond = options.perSecond ?? 30;\n this.reportsPer5Min = options.reportsPer5Min ?? 200;\n this.perDay = options.perDay ?? 5000;\n this.now = options.now ?? Date.now;\n this.sleep = options.sleep ?? defaultSleep;\n }\n\n /** Выполняет `fn`, не нарушая квот. Возвращает результат `fn`. */\n async schedule<T>(scope: QuotaScope, fn: () => Promise<T>): Promise<T> {\n await this.acquire(scope);\n try {\n return await fn();\n } finally {\n this.release();\n }\n }\n\n /** Сколько запросов уже израсходовано в текущих окнах — для диагностики. */\n usage(): { inFlight: number; lastSecond: number; reportsLast5Min: number; today: number } {\n const now = this.now();\n prune(this.secondWindow, now, SECOND);\n prune(this.reportWindow, now, FIVE_MINUTES);\n this.rollDay(now);\n return {\n inFlight: this.inFlight,\n lastSecond: this.secondWindow.length,\n reportsLast5Min: this.reportWindow.length,\n today: this.dayCount,\n };\n }\n\n private rollDay(now: number): void {\n const key = gmtDay(now);\n if (key !== this.dayKey) {\n this.dayKey = key;\n this.dayCount = 0;\n }\n }\n\n private async acquire(scope: QuotaScope): Promise<void> {\n for (;;) {\n const now = this.now();\n prune(this.secondWindow, now, SECOND);\n prune(this.reportWindow, now, FIVE_MINUTES);\n this.rollDay(now);\n\n const wait = this.waitMs(scope, now);\n if (wait === 0) {\n this.inFlight += 1;\n this.secondWindow.push(now);\n this.dayCount += 1;\n if (scope === 'report') this.reportWindow.push(now);\n return;\n }\n\n if (this.inFlight > 0 && wait === Number.POSITIVE_INFINITY) {\n // Упёрлись только в параллелизм — ждём освобождения слота, а не таймера.\n await new Promise<void>((resolve) => this.waiters.push(resolve));\n continue;\n }\n await this.sleep(Math.min(wait, FIVE_MINUTES));\n }\n }\n\n /** 0 — можно выполнять; Infinity — ждать освобождения слота параллелизма. */\n private waitMs(scope: QuotaScope, now: number): number {\n if (this.dayCount >= this.perDay) {\n const nextDayStart = (gmtDay(now) + 1) * 86_400_000;\n return nextDayStart - now;\n }\n if (this.secondWindow.length >= this.perSecond) {\n return this.secondWindow[0]! + SECOND - now;\n }\n if (scope === 'report' && this.reportWindow.length >= this.reportsPer5Min) {\n return this.reportWindow[0]! + FIVE_MINUTES - now;\n }\n if (this.inFlight >= this.maxConcurrent) return Number.POSITIVE_INFINITY;\n return 0;\n }\n\n private release(): void {\n this.inFlight -= 1;\n this.waiters.shift()?.();\n }\n}\n","/**\n * Предупреждения, которые библиотека выдаёт вместо тихого проглатывания проблемы.\n *\n * Ни одно из них не является ошибкой запроса: данные пришли, но их нужно читать с оговоркой.\n */\n\nexport type WarningCode =\n /** Ответ построен по неполной выборке — редкие фразы могли не попасть в отчёт. */\n | 'sampling'\n /** Часть строк скрыта порогом приватности: фразы не отдаются при выборке < 10 посетителей. */\n | 'sensitive_data_hidden'\n /** Данные за хвост периода ещё дозаполняются. */\n | 'data_lag'\n /** Запрошена модель атрибуции, которая с 25.06.2026 схлопывается в аналог. */\n | 'deprecated_attribution'\n /** API вернул группировку или метрику, которой нет в снапшоте контракта. */\n | 'unknown_field'\n /** Достигнут предел выдачи — часть строк осталась за пределами выгрузки. */\n | 'truncated'\n /** Нет доступа к кампаниям Директа: клики и расходы недоступны. */\n | 'direct_access_missing';\n\nexport interface Warning {\n code: WarningCode;\n message: string;\n details?: Record<string, unknown>;\n}\n\nexport type WarningHandler = (warning: Warning) => void;\n\n/** Печатает предупреждение в `console.warn` — поведение по умолчанию. */\nexport const consoleWarningHandler: WarningHandler = (warning) => {\n console.warn(`[yandex-metric-parser-lib] ${warning.code}: ${warning.message}`);\n};\n","/**\n * HTTP-слой: OAuth-авторизация, лимитер квот, ретраи, разбор ошибок API Метрики.\n */\nimport { contractVersion } from '../contract/registry.ts';\nimport { isRetryable, toMetrikaError, type ApiErrorBody, type MetrikaError } from './errors.ts';\nimport { RateLimiter, type QuotaScope, type RateLimitOptions } from './rateLimit.ts';\nimport { consoleWarningHandler, type WarningHandler } from './warnings.ts';\n\n/** Базовый адрес API Метрики. */\nexport const DEFAULT_BASE_URL = 'https://api-metrika.yandex.net';\n\n/** Значение параметра запроса: массивы сериализуются через запятую, как требует API. */\nexport type QueryValue = string | number | boolean | readonly (string | number)[] | undefined;\n\nexport interface MetrikaClientOptions {\n /** OAuth-токен Яндекса. Передаётся в заголовке `Authorization: OAuth <token>`. */\n token: string;\n /** Базовый URL. Переопределяется в тестах. */\n baseUrl?: string;\n /** Настройки лимитера или готовый лимитер (чтобы делить квоту между клиентами). */\n rateLimit?: RateLimitOptions | RateLimiter;\n /** Подменяемый `fetch` — для тестов и прокси. */\n fetch?: typeof globalThis.fetch;\n /** Сколько раз повторять запрос при 429 и 5xx. По умолчанию 3. */\n maxRetries?: number;\n /** Верхняя граница паузы перед повтором. По умолчанию 30 секунд. */\n maxRetryDelayMs?: number;\n /** Таймаут одного запроса. По умолчанию 60 секунд. */\n timeoutMs?: number;\n /** Язык расшифровок и значений фильтров. По умолчанию `ru`. */\n lang?: 'ru' | 'en';\n /** Куда отдавать предупреждения. По умолчанию `console.warn`. */\n onWarning?: WarningHandler;\n}\n\nexport interface RequestOptions {\n /** Путь без базового URL, например `/stat/v1/data`. */\n path: string;\n query?: Record<string, QueryValue>;\n /** Группа квот: у отчётов отдельный пятиминутный лимит. */\n scope: QuotaScope;\n signal?: AbortSignal;\n}\n\nconst sleep = (ms: number): Promise<void> =>\n new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n\n/**\n * Объединяет сигналы отмены: результат срабатывает от любого из них.\n *\n * Ручная реализация вместо `AbortSignal.any` — источники расходятся в том,\n * с какой версии Node он доступен, а пакет заявляет поддержку Node 18.\n * `release` снимает слушатели, чтобы долгоживущий внешний сигнал не накапливал их\n * по одному на каждый запрос.\n */\nexport function combineSignals(signals: AbortSignal[]): {\n signal: AbortSignal;\n release: () => void;\n} {\n const controller = new AbortController();\n const detach: (() => void)[] = [];\n\n for (const source of signals) {\n if (source.aborted) {\n controller.abort(source.reason);\n break;\n }\n const onAbort = (): void => controller.abort(source.reason);\n source.addEventListener('abort', onAbort, { once: true });\n detach.push(() => source.removeEventListener('abort', onAbort));\n }\n\n return {\n signal: controller.signal,\n release: () => {\n for (const off of detach) off();\n },\n };\n}\n\n/** Сериализует значение параметра: массив → строка через запятую. */\nfunction serialize(value: Exclude<QueryValue, undefined>): string {\n return Array.isArray(value) ? value.join(',') : String(value);\n}\n\nexport function buildUrl(\n baseUrl: string,\n path: string,\n query: Record<string, QueryValue> = {},\n): string {\n const url = new URL(path, baseUrl);\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined) continue;\n url.searchParams.set(key, serialize(value));\n }\n return url.toString();\n}\n\n/** Низкоуровневый клиент API Метрики. */\nexport class MetrikaHttpClient {\n readonly lang: 'ru' | 'en';\n readonly warn: WarningHandler;\n readonly limiter: RateLimiter;\n\n private readonly token: string;\n private readonly baseUrl: string;\n private readonly fetchImpl: typeof globalThis.fetch;\n private readonly maxRetries: number;\n private readonly maxRetryDelayMs: number;\n private readonly timeoutMs: number;\n\n constructor(options: MetrikaClientOptions) {\n if (!options.token) throw new Error('Не передан OAuth-токен Яндекс Метрики');\n this.token = options.token;\n this.baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;\n this.fetchImpl = options.fetch ?? globalThis.fetch.bind(globalThis);\n this.maxRetries = options.maxRetries ?? 3;\n this.maxRetryDelayMs = options.maxRetryDelayMs ?? 30_000;\n this.timeoutMs = options.timeoutMs ?? 60_000;\n this.lang = options.lang ?? 'ru';\n this.warn = options.onWarning ?? consoleWarningHandler;\n this.limiter =\n options.rateLimit instanceof RateLimiter\n ? options.rateLimit\n : new RateLimiter(options.rateLimit);\n }\n\n /** Выполняет GET-запрос и разбирает JSON-ответ. */\n async get<T>(options: RequestOptions): Promise<T> {\n const url = buildUrl(this.baseUrl, options.path, options.query);\n let lastError: unknown;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt += 1) {\n try {\n return await this.limiter.schedule(options.scope, () => this.send<T>(url, options.signal));\n } catch (error) {\n lastError = error;\n if (!isRetryable(error) || attempt === this.maxRetries) throw error;\n const delay = this.retryDelay(error, attempt);\n if (delay === undefined) throw error;\n await sleep(delay);\n }\n }\n throw lastError;\n }\n\n /**\n * Пауза перед повтором. `undefined` — ждать пришлось бы дольше `maxRetryDelayMs`,\n * повтор бессмыслен и ошибку надо отдать вызывающему коду.\n */\n private retryDelay(error: unknown, attempt: number): number | undefined {\n const required = (error as { retryAfterMs?: number }).retryAfterMs;\n const backoff = Math.min(1_000 * 2 ** attempt, this.maxRetryDelayMs);\n const delay = required ?? backoff;\n return delay > this.maxRetryDelayMs ? undefined : delay;\n }\n\n private async send<T>(url: string, signal?: AbortSignal): Promise<T> {\n const timeout = AbortSignal.timeout(this.timeoutMs);\n const combined = combineSignals(signal ? [signal, timeout] : [timeout]);\n\n let response: Response;\n try {\n response = await this.fetchImpl(url, {\n method: 'GET',\n headers: {\n Authorization: `OAuth ${this.token}`,\n Accept: 'application/json',\n 'User-Agent': `yandex-metric-parser-lib (contract ${contractVersion})`,\n },\n signal: combined.signal,\n });\n } finally {\n combined.release();\n }\n\n const text = await response.text();\n const body: unknown = text ? safeJson(text) : undefined;\n\n if (!response.ok) {\n throw toMetrikaError(response.status, body as ApiErrorBody | undefined, url);\n }\n return body as T;\n }\n}\n\nfunction safeJson(text: string): unknown {\n try {\n return JSON.parse(text);\n } catch {\n return { message: text.slice(0, 500) };\n }\n}\n\nexport type { MetrikaError };\n","/**\n * API управления: счётчики и клиенты Яндекс Директа.\n *\n * Отсюда берутся две вещи, без которых не построить отчёт по ключевым словам:\n * идентификатор счётчика (по адресу сайта) и логины клиентов Директа\n * для параметра `direct_client_logins`.\n */\nimport type { MetrikaHttpClient } from '../client/http.ts';\n\n/** Клиент Яндекс Директа, доступный счётчику. */\nexport interface DirectClient {\n id: number;\n name?: string;\n /** Логин главного представителя — то, что передаётся в `direct_client_logins`. */\n chief_login: string;\n}\n\n/** Счётчик Метрики в плоском виде: адрес сайта поднят из вложенного `site2`. */\nexport interface CounterBrief {\n id: number;\n name: string;\n /** Адрес сайта. В ответе API лежит в `site2.site`. */\n site: string;\n /** Дополнительные адреса (зеркала). */\n mirrors: string[];\n status?: string;\n /** Уровень доступа: `own`, `view`, `edit`. */\n permission?: string;\n ownerLogin?: string;\n}\n\n/** Уровень доступа к счётчику. */\nexport type CounterPermission = 'own' | 'view' | 'edit';\n\nexport interface GetCountersOptions {\n /**\n * Фильтр по подстроке: идентификатор, название, адрес сайта или зеркало.\n * Идентификатор указывается целиком.\n */\n searchString?: string;\n /** Ограничить уровнем доступа. */\n permission?: CounterPermission[];\n /** Счётчиков за запрос. Максимум 10 000, по умолчанию 1000. */\n perPage?: number;\n /** Номер первого счётчика в выдаче, начиная с 1. */\n offset?: number;\n signal?: AbortSignal;\n}\n\ninterface RawCounter {\n id: number;\n name?: string;\n status?: string;\n permission?: string;\n owner_login?: string;\n site2?: { site?: string } | null;\n mirrors2?: ({ site?: string } | string | null)[] | null;\n}\n\ninterface CountersResponse {\n rows?: number;\n counters?: RawCounter[];\n}\n\ninterface ClientsResponse {\n clients?: DirectClient[];\n}\n\n/** Счётчик по адресу сайта не найден или найден не один. */\nexport class CounterLookupError extends Error {\n readonly candidates: CounterBrief[];\n\n constructor(message: string, candidates: CounterBrief[]) {\n super(message);\n this.name = 'CounterLookupError';\n this.candidates = candidates;\n }\n}\n\nexport class ManagementApi {\n constructor(private readonly http: MetrikaHttpClient) {}\n\n /** Счётчики, доступные владельцу токена. */\n async getCounters(options: GetCountersOptions = {}): Promise<CounterBrief[]> {\n const response = await this.http.get<CountersResponse>({\n path: '/management/v1/counters',\n query: {\n search_string: options.searchString,\n permission: options.permission?.length ? options.permission : undefined,\n per_page: options.perPage,\n offset: options.offset,\n // Адрес сайта и зеркала приходят и без field, но просим явно.\n field: 'mirrors',\n },\n scope: 'management',\n signal: options.signal,\n });\n return (response.counters ?? []).map(toCounterBrief);\n }\n\n /**\n * Находит единственный счётчик по адресу сайта.\n * Бросает `CounterLookupError` со списком кандидатов, если совпадений нет или их несколько:\n * запускать выгрузку по наугад выбранному счётчику хуже, чем остановиться.\n */\n async findCounterBySite(site: string, signal?: AbortSignal): Promise<CounterBrief> {\n const needle = normalizeHost(site);\n const counters = await this.getCounters({\n searchString: needle,\n ...(signal ? { signal } : {}),\n });\n\n // search_string ищет по подстроке: engraf.ru совпадёт и с engraf.ru.example.com.\n const exact = counters.filter(\n (counter) =>\n normalizeHost(counter.site) === needle ||\n counter.mirrors.some((mirror) => normalizeHost(mirror) === needle),\n );\n const matches = exact.length > 0 ? exact : counters;\n\n if (matches.length === 1) return matches[0]!;\n\n if (matches.length === 0) {\n throw new CounterLookupError(\n `Счётчик для сайта \"${site}\" не найден. Проверьте, что у аккаунта, ` +\n 'на который выдан токен, есть доступ к этому счётчику.',\n [],\n );\n }\n throw new CounterLookupError(\n `Сайту \"${site}\" соответствует несколько счётчиков: ` +\n `${matches.map((counter) => `${counter.id} (${counter.site})`).join(', ')}. ` +\n 'Укажите идентификатор явно.',\n matches,\n );\n }\n\n /** Клиенты Директа, доступные указанным счётчикам. */\n async getDirectClients(\n counterIds: number | number[],\n signal?: AbortSignal,\n ): Promise<DirectClient[]> {\n const counters = Array.isArray(counterIds) ? counterIds : [counterIds];\n const response = await this.http.get<ClientsResponse>({\n path: '/management/v1/clients',\n query: { counters },\n scope: 'management',\n signal,\n });\n return response.clients ?? [];\n }\n\n /** Логины для параметра `direct_client_logins`. */\n async getDirectClientLogins(\n counterIds: number | number[],\n signal?: AbortSignal,\n ): Promise<string[]> {\n const clients = await this.getDirectClients(counterIds, signal);\n return [...new Set(clients.map((client) => client.chief_login).filter(Boolean))];\n }\n}\n\nfunction toCounterBrief(raw: RawCounter): CounterBrief {\n return {\n id: raw.id,\n name: raw.name ?? '',\n site: raw.site2?.site ?? '',\n mirrors: (raw.mirrors2 ?? [])\n .map((mirror) => (typeof mirror === 'string' ? mirror : mirror?.site))\n .filter((site): site is string => Boolean(site)),\n ...(raw.status ? { status: raw.status } : {}),\n ...(raw.permission ? { permission: raw.permission } : {}),\n ...(raw.owner_login ? { ownerLogin: raw.owner_login } : {}),\n };\n}\n\n/** Приводит адрес к сравнимому виду: без схемы, www и завершающего слэша. */\nfunction normalizeHost(site: string): string {\n return site\n .trim()\n .toLowerCase()\n .replace(/^https?:\\/\\//, '')\n .replace(/^www\\./, '')\n .replace(/\\/+$/, '');\n}\n","/**\n * Даты отчётного периода.\n *\n * Визиты дозаполняются по мере поступления данных: в среднем 99 % визитов завершаются\n * в течение 3 дней после начала. Поэтому окно по умолчанию заканчивается на T-3,\n * иначе последние дни выглядят «просевшими» и портят сравнение периодов.\n */\n\n/** Сколько последних дней считаются недозаполненными. */\nexport const SETTLED_LAG_DAYS = 3;\n\n/** Отчётный период: значения в формате API (`YYYY-MM-DD` или `NdaysAgo`). */\nexport interface DateRange {\n date1: string;\n date2: string;\n}\n\n/**\n * Окно из `days` дней, заканчивающееся за `lagDays` дней до сегодня.\n * `settledRange(30)` → `{ date1: '32daysAgo', date2: '3daysAgo' }`.\n */\nexport function settledRange(days = 30, lagDays: number = SETTLED_LAG_DAYS): DateRange {\n if (days < 1) throw new RangeError('Период должен быть не меньше одного дня');\n return {\n date1: `${lagDays + days - 1}daysAgo`,\n date2: `${lagDays}daysAgo`,\n };\n}\n","/**\n * Проверки запроса до отправки. Каждая пойманная здесь ошибка — это сэкономленный\n * запрос из квоты 200 за 5 минут и понятное сообщение вместо `400 invalid_parameter`.\n */\nimport { RequestValidationError } from '../client/errors.ts';\nimport {\n DEPRECATED_ATTRIBUTIONS,\n hasDimension,\n hasMetric,\n hasPreset,\n namespaceOf,\n} from '../contract/registry.ts';\nimport type { Warning } from '../client/warnings.ts';\nimport type { StatQuery } from './types.ts';\n\n/** Документированные лимиты запроса к API отчётов. */\nexport const LIMITS = {\n maxDimensions: 10,\n maxMetrics: 20,\n maxRowsPerRequest: 100_000,\n maxFilterLength: 10_000,\n maxFilterValues: 100,\n} as const;\n\n/**\n * Пространства имён, которые нельзя смешивать в `dimensions`/`metrics` одного запроса.\n * `ym:pv:` и прочие допустимы только в `filters`.\n */\nfunction namespaces(ids: readonly string[]): Set<string> {\n const result = new Set<string>();\n for (const id of ids) {\n const ns = namespaceOf(id);\n if (ns) result.add(ns);\n }\n return result;\n}\n\nconst ATTRIBUTION_PREFIXES = [\n 'crossDeviceLastSignificant',\n 'crossDeviceFirst',\n 'lastYandexDirectClick',\n 'lastSignificant',\n 'automatic',\n 'first',\n 'last',\n] as const;\n\n/**\n * Приводит идентификатор к форме документации, подставляя обратно плейсхолдеры:\n * `ym:s:lastSearchPhrase` → `ym:s:<attribution>SearchPhrase`,\n * `ym:ad:RUBConvertedAdCost` → `ym:ad:<currency>ConvertedAdCost`,\n * `ym:s:goal123visits` → `ym:s:goal<goal_id>visits`.\n */\nexport function toContractForm(id: string): string {\n const match = /^(ym:[a-z]{1,3}:)(.*)$/.exec(id);\n if (!match) return id;\n const [, prefix, rest] = match as unknown as [string, string, string];\n\n let tail = rest;\n for (const attribution of ATTRIBUTION_PREFIXES) {\n if (tail.startsWith(attribution) && /^[A-Z]/.test(tail.slice(attribution.length))) {\n tail = `<attribution>${tail.slice(attribution.length)}`;\n break;\n }\n }\n tail = tail\n .replace(/\\b(RUB|USD|EUR|YND)/g, '<currency>')\n .replace(/goal\\d+/g, 'goal<goal_id>')\n .replace(/experimentAB\\d+/g, 'experimentAB<experiment_ab>')\n .replace(/datePeriod(day|week|month|quarter|year)/g, 'datePeriod<group>');\n\n return `${prefix}${tail}`;\n}\n\nexport interface ValidationResult {\n warnings: Warning[];\n}\n\n/** Проверяет запрос и возвращает предупреждения; на грубых ошибках бросает исключение. */\nexport function validateQuery(\n query: StatQuery,\n options: { allowUnknownFields?: boolean } = {},\n): ValidationResult {\n const warnings: Warning[] = [];\n const dimensions = query.dimensions ?? [];\n const metrics = query.metrics ?? [];\n\n if (!query.preset && metrics.length === 0) {\n throw new RequestValidationError(\n 'Нужно указать хотя бы одну метрику (metrics) или шаблон отчёта (preset)',\n );\n }\n if (dimensions.length > LIMITS.maxDimensions) {\n throw new RequestValidationError(\n `Группировок в запросе: ${dimensions.length}, максимум ${LIMITS.maxDimensions}`,\n );\n }\n if (metrics.length > LIMITS.maxMetrics) {\n throw new RequestValidationError(\n `Метрик в запросе: ${metrics.length}, максимум ${LIMITS.maxMetrics}`,\n );\n }\n if (query.limit !== undefined && (query.limit < 1 || query.limit > LIMITS.maxRowsPerRequest)) {\n throw new RequestValidationError(\n `limit должен быть в диапазоне 1…${LIMITS.maxRowsPerRequest}, получено ${query.limit}`,\n );\n }\n if (query.offset !== undefined && query.offset < 1) {\n throw new RequestValidationError(`offset начинается с 1, получено ${query.offset}`);\n }\n if (query.filters && query.filters.length > LIMITS.maxFilterLength) {\n throw new RequestValidationError(\n `Длина filters ${query.filters.length} символов, максимум ${LIMITS.maxFilterLength}`,\n );\n }\n\n // В одном запросе нельзя смешивать префиксы группировок и метрик.\n const used = namespaces([...dimensions, ...metrics]);\n if (used.size > 1) {\n throw new RequestValidationError(\n `Нельзя смешивать пространства имён в одном запросе: ${[...used]\n .map((ns) => `ym:${ns}:`)\n .join(', ')}. Разделите на два запроса (смешивать можно только в filters).`,\n );\n }\n\n // Отчёты в пространстве ym:ad: не строятся без логинов клиентов Директа.\n if (used.has('ad') && !query.directClientLogins?.length) {\n throw new RequestValidationError(\n 'Для отчётов ym:ad: обязателен параметр directClientLogins. ' +\n 'Логины доступных клиентов: GET /management/v1/clients?counters=<id>',\n );\n }\n\n if (query.preset && !hasPreset(query.preset)) {\n reportUnknown(`шаблон \"${query.preset}\"`, options, warnings, { preset: query.preset });\n }\n for (const id of dimensions) {\n if (!hasDimension(toContractForm(id))) {\n reportUnknown(`группировка \"${id}\"`, options, warnings, { dimension: id });\n }\n }\n for (const id of metrics) {\n if (!hasMetric(toContractForm(id))) {\n reportUnknown(`метрика \"${id}\"`, options, warnings, { metric: id });\n }\n }\n\n if (query.attribution && query.attribution in DEPRECATED_ATTRIBUTIONS) {\n const replacement = DEPRECATED_ATTRIBUTIONS[query.attribution];\n warnings.push({\n code: 'deprecated_attribution',\n message:\n `Модель атрибуции \"${query.attribution}\" устарела: с 25 июня 2026 года API будет ` +\n `возвращать значения по модели \"${replacement}\". Перейдите на неё заранее.`,\n details: { requested: query.attribution, replacement },\n });\n }\n\n return { warnings };\n}\n\nfunction reportUnknown(\n what: string,\n options: { allowUnknownFields?: boolean },\n warnings: Warning[],\n details: Record<string, unknown>,\n): void {\n const message =\n `Неизвестная ${what} — её нет в снапшоте контракта. ` +\n 'Проверьте написание или обновите снапшот: npm run fetch-docs && npm run parse-contract';\n if (options.allowUnknownFields) {\n warnings.push({ code: 'unknown_field', message, details });\n return;\n }\n throw new RequestValidationError(message);\n}\n","/**\n * API отчётов: `/stat/v1/data` (таблица) и `/stat/v1/data/bytime` (по времени).\n */\nimport type { MetrikaHttpClient, QueryValue } from '../client/http.ts';\nimport type { Warning } from '../client/warnings.ts';\nimport { contractVersion, hasDimension, hasMetric } from '../contract/registry.ts';\nimport { settledRange } from './dates.ts';\nimport type {\n BytimeResponse,\n Report,\n ReportMeta,\n StatDataResponse,\n StatQuery,\n StatRow,\n TimeGroup,\n} from './types.ts';\nimport { LIMITS, toContractForm, validateQuery } from './validate.ts';\n\n/** Размер страницы по умолчанию: максимум, разрешённый API. */\nconst DEFAULT_PAGE_SIZE = LIMITS.maxRowsPerRequest;\n\nexport interface ReportsApiOptions {\n /** Не бросать исключение на группировку, которой нет в снапшоте, а предупреждать. */\n allowUnknownFields?: boolean;\n}\n\nexport interface FetchAllOptions {\n /** Верхняя граница выгрузки. Без неё выгружаются все `total_rows`. */\n maxRows?: number;\n /** Строк за запрос. По умолчанию 100 000 — максимум API. */\n pageSize?: number;\n signal?: AbortSignal;\n}\n\nexport interface BytimeQuery extends StatQuery {\n /** Разбиение шкалы времени. По умолчанию `day`. */\n group?: TimeGroup;\n /** Сколько строк строить, если не заданы `rowIds`. Максимум 30. */\n topKeys?: number;\n /** Явный выбор строк по ключам группировок. */\n rowIds?: string[][];\n}\n\n/** Преобразует запрос библиотеки в query-параметры API. */\nexport function toQueryParams(query: StatQuery, lang: 'ru' | 'en'): Record<string, QueryValue> {\n const range = { date1: query.date1, date2: query.date2 };\n return {\n ids: Array.isArray(query.ids) ? query.ids : [query.ids],\n metrics: query.metrics.length ? query.metrics : undefined,\n dimensions: query.dimensions?.length ? query.dimensions : undefined,\n preset: query.preset,\n date1: range.date1,\n date2: range.date2,\n filters: query.filters,\n sort: query.sort?.length ? query.sort : undefined,\n // Без full редкие фразы выпадают из выборки — именно они и составляют длинный хвост.\n accuracy: query.accuracy ?? 'full',\n proposed_accuracy: query.proposedAccuracy,\n limit: query.limit,\n offset: query.offset,\n attribution: query.attribution,\n currency: query.currency,\n goal_id: query.goalId,\n direct_client_logins: query.directClientLogins?.length\n ? query.directClientLogins\n : undefined,\n include_undefined: query.includeUndefined,\n timezone: query.timezone,\n lang: query.lang ?? lang,\n };\n}\n\n/** Собирает предупреждения о качестве данных из ответа API. */\nexport function inspectResponse(response: StatDataResponse): Warning[] {\n const warnings: Warning[] = [];\n\n if (response.sampled) {\n warnings.push({\n code: 'sampling',\n message:\n `Отчёт построен по выборке ${formatShare(response.sample_share)} данных ` +\n `(${response.sample_size ?? '?'} из ${response.sample_space ?? '?'} строк). ` +\n 'Редкие фразы могли не попасть в результат.',\n details: {\n sampleShare: response.sample_share,\n sampleSize: response.sample_size,\n sampleSpace: response.sample_space,\n },\n });\n }\n\n if (response.contains_sensitive_data) {\n warnings.push({\n code: 'sensitive_data_hidden',\n message:\n 'В ответе могут отсутствовать строки, по которым выборка меньше 10 посетителей: ' +\n 'поисковые фразы относятся к конфиденциальным данным. Это режет длинный хвост запросов.',\n });\n }\n\n if (response.data_lag && response.data_lag > 0) {\n warnings.push({\n code: 'data_lag',\n message:\n `Задержка данных ${Math.round(response.data_lag / 60)} мин — ` +\n 'последние дни периода могут быть неполными.',\n details: { dataLagSeconds: response.data_lag },\n });\n }\n\n for (const id of response.query?.dimensions ?? []) {\n if (!hasDimension(toContractForm(id))) {\n warnings.push({\n code: 'unknown_field',\n message: `API вернул группировку \"${id}\", которой нет в снапшоте контракта ${contractVersion}.`,\n details: { dimension: id },\n });\n }\n }\n for (const id of response.query?.metrics ?? []) {\n if (!hasMetric(toContractForm(id))) {\n warnings.push({\n code: 'unknown_field',\n message: `API вернул метрику \"${id}\", которой нет в снапшоте контракта ${contractVersion}.`,\n details: { metric: id },\n });\n }\n }\n\n return warnings;\n}\n\nfunction formatShare(share: number | undefined): string {\n return share === undefined ? '?' : `${Math.round(share * 100)}%`;\n}\n\n/** Типизированный доступ к API отчётов. */\nexport class ReportsApi {\n constructor(\n private readonly http: MetrikaHttpClient,\n private readonly options: ReportsApiOptions = {},\n ) {}\n\n /** Одна страница отчёта. Сырой ответ API без постобработки. */\n async fetchPage(query: StatQuery, signal?: AbortSignal): Promise<StatDataResponse> {\n const { warnings } = validateQuery(query, this.options);\n warnings.forEach(this.http.warn);\n return this.http.get<StatDataResponse>({\n path: '/stat/v1/data',\n query: toQueryParams(query, this.http.lang),\n scope: 'report',\n signal,\n });\n }\n\n /**\n * Выгружает отчёт целиком, постранично по `total_rows`.\n * Период по умолчанию — 30 дней, заканчивающихся на T-3 (данные визитов дозаполняются ~3 дня).\n */\n async fetchAll(query: StatQuery, options: FetchAllOptions = {}): Promise<Report<StatRow>> {\n const pageSize = Math.min(options.pageSize ?? DEFAULT_PAGE_SIZE, LIMITS.maxRowsPerRequest);\n const defaults = settledRange(30);\n const base: StatQuery = {\n ...query,\n date1: query.date1 ?? defaults.date1,\n date2: query.date2 ?? defaults.date2,\n };\n\n const { warnings: queryWarnings } = validateQuery(base, this.options);\n const warnings: Warning[] = [...queryWarnings];\n warnings.forEach(this.http.warn);\n\n const rows: StatRow[] = [];\n let offset = base.offset ?? 1;\n let requests = 0;\n let totalRows = 0;\n let meta: StatDataResponse | undefined;\n\n for (;;) {\n const remaining = options.maxRows === undefined ? pageSize : options.maxRows - rows.length;\n if (remaining <= 0) break;\n\n const page = await this.http.get<StatDataResponse>({\n path: '/stat/v1/data',\n query: toQueryParams(\n { ...base, limit: Math.min(pageSize, remaining), offset },\n this.http.lang,\n ),\n scope: 'report',\n signal: options.signal,\n });\n requests += 1;\n meta ??= page;\n totalRows = page.total_rows;\n\n if (requests === 1) {\n for (const warning of inspectResponse(page)) {\n warnings.push(warning);\n this.http.warn(warning);\n }\n }\n\n rows.push(...page.data);\n offset += page.data.length;\n\n // total_rows считается от начала отчёта, а не от стартового offset.\n if (page.data.length === 0 || offset > totalRows) break;\n }\n\n if (options.maxRows !== undefined && totalRows > rows.length) {\n const warning: Warning = {\n code: 'truncated',\n message: `Выгружено ${rows.length} строк из ${totalRows}: сработал лимит maxRows.`,\n details: { fetched: rows.length, totalRows },\n };\n warnings.push(warning);\n this.http.warn(warning);\n }\n\n return { rows, meta: buildMeta(meta, rows.length, requests, warnings) };\n }\n\n /** Ленивая постраничная выгрузка — когда весь отчёт не нужно держать в памяти. */\n async *stream(query: StatQuery, options: FetchAllOptions = {}): AsyncGenerator<StatRow> {\n const pageSize = Math.min(options.pageSize ?? DEFAULT_PAGE_SIZE, LIMITS.maxRowsPerRequest);\n const defaults = settledRange(30);\n const base: StatQuery = {\n ...query,\n date1: query.date1 ?? defaults.date1,\n date2: query.date2 ?? defaults.date2,\n };\n validateQuery(base, this.options).warnings.forEach(this.http.warn);\n\n let offset = base.offset ?? 1;\n let emitted = 0;\n let first = true;\n\n for (;;) {\n const remaining = options.maxRows === undefined ? pageSize : options.maxRows - emitted;\n if (remaining <= 0) return;\n\n const page = await this.http.get<StatDataResponse>({\n path: '/stat/v1/data',\n query: toQueryParams(\n { ...base, limit: Math.min(pageSize, remaining), offset },\n this.http.lang,\n ),\n scope: 'report',\n signal: options.signal,\n });\n if (first) {\n inspectResponse(page).forEach(this.http.warn);\n first = false;\n }\n for (const row of page.data) {\n yield row;\n emitted += 1;\n }\n offset += page.data.length;\n if (page.data.length === 0 || offset > page.total_rows) return;\n }\n }\n\n /** Отчёт с разбивкой по времени — для динамики фраз. */\n async bytime(query: BytimeQuery, signal?: AbortSignal): Promise<BytimeResponse> {\n if (query.topKeys !== undefined && (query.topKeys < 1 || query.topKeys > 30)) {\n throw new RangeError(`topKeys должен быть в диапазоне 1…30, получено ${query.topKeys}`);\n }\n const defaults = settledRange(30);\n const base: BytimeQuery = {\n ...query,\n date1: query.date1 ?? defaults.date1,\n date2: query.date2 ?? defaults.date2,\n };\n validateQuery(base, this.options).warnings.forEach(this.http.warn);\n\n return this.http.get<BytimeResponse>({\n path: '/stat/v1/data/bytime',\n query: {\n ...toQueryParams(base, this.http.lang),\n group: base.group ?? 'day',\n top_keys: base.topKeys,\n row_ids: base.rowIds ? JSON.stringify(base.rowIds) : undefined,\n },\n scope: 'report',\n signal,\n });\n }\n}\n\nfunction buildMeta(\n response: StatDataResponse | undefined,\n fetchedRows: number,\n requests: number,\n warnings: Warning[],\n): ReportMeta {\n return {\n contractVersion,\n sampled: response?.sampled ?? false,\n sampleShare: response?.sample_share,\n sampleSize: response?.sample_size,\n sampleSpace: response?.sample_space,\n containsSensitiveData: response?.contains_sensitive_data ?? false,\n dataLagSeconds: response?.data_lag,\n totalRows: response?.total_rows ?? fetchedRows,\n fetchedRows,\n requests,\n warnings,\n };\n}\n","/**\n * Общее для рецептов выгрузки ключевых слов: идентификаторы группировок и метрик,\n * сборка фильтров и безопасное чтение ячеек ответа.\n */\nimport type { Attribution } from '../contract/registry.ts';\nimport type { DimensionValue, StatRow } from '../reports/types.ts';\n\n/** Группировки, на которых держатся рецепты. Форма — как в документации, с плейсхолдерами. */\nexport const DIM = {\n searchPhrase: 'ym:s:<attribution>SearchPhrase',\n searchEngineRoot: 'ym:s:<attribution>SearchEngineRoot',\n trafficSource: 'ym:s:<attribution>TrafficSource',\n isRobot: 'ym:s:isRobot',\n startUrl: 'ym:s:startURL',\n visitDirectSearchPhrase: 'ym:s:<attribution>DirectSearchPhrase',\n visitDirectPhraseOrCond: 'ym:s:<attribution>DirectPhraseOrCond',\n adDirectSearchPhrase: 'ym:ad:<attribution>DirectSearchPhrase',\n adDirectPhraseOrCond: 'ym:ad:<attribution>DirectPhraseOrCond',\n adDirectOrder: 'ym:ad:<attribution>DirectOrder',\n adDirectConditionType: 'ym:ad:<attribution>DirectConditionType',\n} as const;\n\n/** Метрики, на которых держатся рецепты. */\nexport const METRIC = {\n visits: 'ym:s:visits',\n users: 'ym:s:users',\n bounceRate: 'ym:s:bounceRate',\n pageDepth: 'ym:s:pageDepth',\n avgVisitDuration: 'ym:s:avgVisitDurationSeconds',\n anyGoalConversionRate: 'ym:s:anyGoalConversionRate',\n adClicks: 'ym:ad:clicks',\n adVisits: 'ym:ad:visits',\n adUsers: 'ym:ad:users',\n adBounceRate: 'ym:ad:bounceRate',\n adCost: 'ym:ad:<currency>ConvertedAdCost',\n adCostPerVisit: 'ym:ad:<currency>ConvertedAdCostPerVisit',\n} as const;\n\n/** Общие параметры всех рецептов. */\nexport interface KeywordQueryOptions {\n /** Счётчик или счётчики Метрики. */\n counterId: number | number[];\n /** Начало периода. По умолчанию 30 дней, заканчивающихся на T-3. */\n date1?: string;\n date2?: string;\n /** Модель атрибуции. По умолчанию `last`. */\n attribution?: Attribution;\n /** Дополнительный фильтр сегментации — приклеивается к фильтру рецепта через `AND`. */\n filters?: string;\n /** Верхняя граница выгрузки. Без неё выгружается весь отчёт. */\n maxRows?: number;\n signal?: AbortSignal;\n}\n\n/** Склеивает условия фильтра через `AND`, отбрасывая пустые. */\nexport function andFilters(...parts: (string | undefined)[]): string | undefined {\n const clauses = parts.filter((part): part is string => Boolean(part?.trim()));\n if (clauses.length === 0) return undefined;\n return clauses.map((clause) => (clauses.length > 1 ? `(${clause})` : clause)).join(' AND ');\n}\n\n/** Расшифровка значения группировки: имя, если оно есть, иначе идентификатор. */\nexport function text(value: DimensionValue | undefined): string {\n return value?.name ?? value?.id ?? '';\n}\n\n/** Идентификатор значения группировки, если API его отдал. */\nexport function id(value: DimensionValue | undefined): string | undefined {\n return value?.id ?? undefined;\n}\n\n/** Числовое значение метрики; `null` и пропуски превращаются в 0. */\nexport function num(row: StatRow, index: number): number {\n const value = row.metrics[index];\n return typeof value === 'number' && Number.isFinite(value) ? value : 0;\n}\n\n/**\n * Нормализует поисковую фразу для склейки источников: обрезает края,\n * схлопывает пробелы, приводит к нижнему регистру и унифицирует `ё`.\n * Метрика отдаёт одну и ту же фразу с разным регистром из органики и Директа.\n */\nexport function normalizePhrase(phrase: string): string {\n return phrase.trim().replace(/\\s+/g, ' ').toLowerCase().replace(/ё/g, 'е');\n}\n","/**\n * Рецепт C — Яндекс Директ: реальные запросы, клики и расходы.\n *\n * Работает в пространстве `ym:ad:`, поэтому требует `direct_client_logins` —\n * логины клиентов Директа, к кампаниям которых есть доступ у владельца счётчика.\n * Эквивалент шаблона `preset=sources_direct_clicks`, дополненный метрикой `ym:ad:clicks`.\n */\nimport type { Currency } from '../contract/registry.ts';\nimport type { ReportsApi } from '../reports/data.ts';\nimport type { Report, StatRow } from '../reports/types.ts';\nimport { DIM, METRIC, andFilters, id, num, text, type KeywordQueryOptions } from './shared.ts';\n\n/** Строка отчёта по расходам Директа в разрезе запроса и ключевого слова. */\nexport interface DirectCostRow {\n /** Реальный поисковый запрос, по которому показалось объявление. */\n query: string;\n /** Условие показа: ключевое слово или условие ретаргетинга. */\n keyword: string;\n /** Тип условия показа — позволяет отделить ключевики от ретаргетинга. */\n conditionType?: string;\n campaignId?: string;\n campaignName: string;\n /** Клики по рекламе. */\n clicks: number;\n visits: number;\n users: number;\n /** Расходы в валюте отчёта. */\n cost: number;\n /** Средняя стоимость визита. */\n costPerVisit: number;\n bounceRate: number;\n}\n\nexport interface DirectCostOptions extends KeywordQueryOptions {\n /**\n * Логины клиентов Директа. Обязательны: без них API отчётов не строит `ym:ad:`.\n * Получить: `ManagementApi.getDirectClientLogins(counterId)`.\n */\n directClientLogins: string[];\n /** Валюта расходов. По умолчанию — валюта счётчика. */\n currency?: Currency;\n /**\n * Оставить только указанные типы условия показа — так отсекаются условия ретаргетинга.\n * Документация не перечисляет допустимые значения, поэтому список передаётся явно:\n * сначала выгрузите отчёт без фильтра и посмотрите, какие `conditionType` встречаются.\n */\n conditionTypes?: string[];\n}\n\nconst METRICS = [\n METRIC.adClicks,\n METRIC.adVisits,\n METRIC.adUsers,\n METRIC.adCost,\n METRIC.adCostPerVisit,\n METRIC.adBounceRate,\n];\n\n/** Выгружает запросы Директа с кликами и расходами по каждому ключевому слову. */\nexport async function getDirectSearchPhraseCost(\n reports: ReportsApi,\n options: DirectCostOptions,\n): Promise<Report<DirectCostRow>> {\n const report = await reports.fetchAll(\n {\n ids: options.counterId,\n dimensions: [\n DIM.adDirectSearchPhrase,\n DIM.adDirectPhraseOrCond,\n DIM.adDirectConditionType,\n DIM.adDirectOrder,\n ],\n metrics: METRICS,\n filters: andFilters(\n options.conditionTypes?.length\n ? `${DIM.adDirectConditionType}=.(${options.conditionTypes\n .map((type) => `'${type}'`)\n .join(',')})`\n : undefined,\n options.filters,\n ),\n attribution: options.attribution ?? 'last',\n currency: options.currency,\n directClientLogins: options.directClientLogins,\n date1: options.date1,\n date2: options.date2,\n sort: [`-${METRIC.adClicks}`],\n },\n { maxRows: options.maxRows, signal: options.signal },\n );\n\n return { rows: report.rows.map(toDirectCostRow), meta: report.meta };\n}\n\nfunction toDirectCostRow(row: StatRow): DirectCostRow {\n const conditionType = text(row.dimensions[2]);\n const campaignId = id(row.dimensions[3]);\n return {\n query: text(row.dimensions[0]),\n keyword: text(row.dimensions[1]),\n ...(conditionType ? { conditionType } : {}),\n ...(campaignId ? { campaignId } : {}),\n campaignName: text(row.dimensions[3]),\n clicks: num(row, 0),\n visits: num(row, 1),\n users: num(row, 2),\n cost: num(row, 3),\n costPerVisit: num(row, 4),\n bounceRate: num(row, 5),\n };\n}\n","/**\n * Рецепт D — ключевые слова Директа по визитам, без доступа к кампаниям.\n *\n * Работает в пространстве `ym:s:`, поэтому не требует `direct_client_logins`.\n * Отдаёт слова и запросы с качеством визита и конверсией, но без кликов и расходов —\n * их можно получить только рецептом C.\n * Эквивалент шаблона `preset=sources_direct_summary`.\n */\nimport type { ReportsApi } from '../reports/data.ts';\nimport type { Report, StatRow } from '../reports/types.ts';\nimport { DIM, METRIC, andFilters, num, text, type KeywordQueryOptions } from './shared.ts';\n\n/** Строка отчёта по ключевым словам Директа в разрезе визитов. */\nexport interface DirectVisitRow {\n /** Условие показа: ключевое слово или условие ретаргетинга. */\n keyword: string;\n /** Реальный поисковый запрос, по которому показалось объявление. */\n query: string;\n visits: number;\n users: number;\n bounceRate: number;\n /** Конверсия по любой цели, %. */\n anyGoalConversionRate: number;\n}\n\nconst METRICS = [METRIC.visits, METRIC.users, METRIC.bounceRate, METRIC.anyGoalConversionRate];\n\n/** Выгружает ключевые слова и запросы Директа без доступа к рекламным кампаниям. */\nexport async function getDirectKeywordsByVisits(\n reports: ReportsApi,\n options: KeywordQueryOptions & { excludeRobots?: boolean },\n): Promise<Report<DirectVisitRow>> {\n const report = await reports.fetchAll(\n {\n ids: options.counterId,\n dimensions: [DIM.visitDirectPhraseOrCond, DIM.visitDirectSearchPhrase],\n metrics: METRICS,\n filters: andFilters(\n options.excludeRobots === false ? undefined : `${DIM.isRobot}=='No'`,\n options.filters,\n ),\n attribution: options.attribution ?? 'last',\n date1: options.date1,\n date2: options.date2,\n sort: [`-${METRIC.visits}`],\n },\n { maxRows: options.maxRows, signal: options.signal },\n );\n\n return { rows: report.rows.map(toDirectVisitRow), meta: report.meta };\n}\n\nfunction toDirectVisitRow(row: StatRow): DirectVisitRow {\n return {\n keyword: text(row.dimensions[0]),\n query: text(row.dimensions[1]),\n visits: num(row, 0),\n users: num(row, 1),\n bounceRate: num(row, 2),\n anyGoalConversionRate: num(row, 3),\n };\n}\n","/**\n * Рецепт A — поисковые фразы органики: по каким словам сайт находят в поиске.\n *\n * Эквивалент шаблона `preset=sources_search_phrases`, но с отсечкой роботов\n * и `accuracy=full`, иначе длинный хвост фраз выпадает из выборки.\n */\nimport type { ReportsApi } from '../reports/data.ts';\nimport type { Report, StatRow } from '../reports/types.ts';\nimport {\n DIM,\n METRIC,\n andFilters,\n id,\n num,\n text,\n type KeywordQueryOptions,\n} from './shared.ts';\n\n/** Строка отчёта по органическим поисковым фразам. */\nexport interface OrganicPhraseRow {\n /** Поисковая фраза как её отдал API. */\n phrase: string;\n /** Название поисковой системы (Яндекс, Google, …). */\n searchEngine: string;\n /** Идентификатор поисковой системы. */\n searchEngineId?: string;\n visits: number;\n users: number;\n /** Доля отказов, %. */\n bounceRate: number;\n /** Средняя глубина просмотра. */\n pageDepth: number;\n /** Среднее время на сайте, секунды. */\n avgVisitDurationSeconds: number;\n}\n\nexport interface OrganicPhrasesOptions extends KeywordQueryOptions {\n /** Исключить визиты роботов. По умолчанию `true`. */\n excludeRobots?: boolean;\n /** Ограничить конкретными поисковыми системами, например `['yandex']`. */\n searchEngines?: string[];\n}\n\n/** Фильтр рецепта: только переходы из поисковых систем, по умолчанию без роботов. */\nexport function organicFilters(options: OrganicPhrasesOptions): string | undefined {\n const engines = options.searchEngines?.length\n ? `${DIM.searchEngineRoot}=.(${options.searchEngines.map((e) => `'${e}'`).join(',')})`\n : undefined;\n return andFilters(\n `${DIM.trafficSource}=='organic'`,\n options.excludeRobots === false ? undefined : `${DIM.isRobot}=='No'`,\n engines,\n options.filters,\n );\n}\n\nconst METRICS = [\n METRIC.visits,\n METRIC.users,\n METRIC.bounceRate,\n METRIC.pageDepth,\n METRIC.avgVisitDuration,\n];\n\n/** Выгружает поисковые фразы органики со статистикой качества визита. */\nexport async function getOrganicSearchPhrases(\n reports: ReportsApi,\n options: OrganicPhrasesOptions,\n): Promise<Report<OrganicPhraseRow>> {\n const report = await reports.fetchAll(\n {\n ids: options.counterId,\n dimensions: [DIM.searchPhrase, DIM.searchEngineRoot],\n metrics: METRICS,\n filters: organicFilters(options),\n attribution: options.attribution ?? 'last',\n date1: options.date1,\n date2: options.date2,\n sort: [`-${METRIC.visits}`],\n },\n { maxRows: options.maxRows, signal: options.signal },\n );\n\n return { rows: report.rows.map(toOrganicRow), meta: report.meta };\n}\n\nfunction toOrganicRow(row: StatRow): OrganicPhraseRow {\n const engineId = id(row.dimensions[1]);\n return {\n phrase: text(row.dimensions[0]),\n searchEngine: text(row.dimensions[1]),\n ...(engineId ? { searchEngineId: engineId } : {}),\n visits: num(row, 0),\n users: num(row, 1),\n bounceRate: num(row, 2),\n pageDepth: num(row, 3),\n avgVisitDurationSeconds: num(row, 4),\n };\n}\n","/**\n * Рецепт B — фраза × посадочная страница.\n *\n * Связывает ключевое слово с конкретным материалом сайта: основа для того,\n * чтобы понять, какой контент уже отвечает на запрос, а какой ещё нужно написать.\n */\nimport type { ReportsApi } from '../reports/data.ts';\nimport type { Report, StatRow } from '../reports/types.ts';\nimport { organicFilters, type OrganicPhrasesOptions } from './organic.ts';\nimport { DIM, METRIC, num, text } from './shared.ts';\n\n/** Строка отчёта «фраза → страница входа». */\nexport interface PhraseLandingRow {\n phrase: string;\n /** Адрес страницы входа. */\n url: string;\n visits: number;\n users: number;\n bounceRate: number;\n avgVisitDurationSeconds: number;\n}\n\nconst METRICS = [METRIC.visits, METRIC.users, METRIC.bounceRate, METRIC.avgVisitDuration];\n\n/** Выгружает связку «поисковая фраза → посадочная страница» для органики. */\nexport async function getPhraseLandingMap(\n reports: ReportsApi,\n options: OrganicPhrasesOptions,\n): Promise<Report<PhraseLandingRow>> {\n const report = await reports.fetchAll(\n {\n ids: options.counterId,\n dimensions: [DIM.searchPhrase, DIM.startUrl],\n metrics: METRICS,\n filters: organicFilters(options),\n attribution: options.attribution ?? 'last',\n date1: options.date1,\n date2: options.date2,\n sort: [`-${METRIC.visits}`],\n },\n { maxRows: options.maxRows, signal: options.signal },\n );\n\n return { rows: report.rows.map(toLandingRow), meta: report.meta };\n}\n\nfunction toLandingRow(row: StatRow): PhraseLandingRow {\n return {\n phrase: text(row.dimensions[0]),\n url: text(row.dimensions[1]),\n visits: num(row, 0),\n users: num(row, 1),\n bounceRate: num(row, 2),\n avgVisitDurationSeconds: num(row, 3),\n };\n}\n","/**\n * Рецепт E — динамика фраз во времени.\n *\n * Отвечает на вопрос «какие слова сейчас растут»: именно растущие фразы стоит брать\n * в работу, а не те, что просто набрали много визитов за весь период.\n * Ограничение API: не более 30 строк на график (`top_keys`).\n */\nimport type { ReportsApi } from '../reports/data.ts';\nimport type { BytimeRow, TimeGroup } from '../reports/types.ts';\nimport { organicFilters, type OrganicPhrasesOptions } from './organic.ts';\nimport { DIM, METRIC, text } from './shared.ts';\n\n/** Максимум строк, который API отдаёт для отчёта по времени. */\nexport const MAX_TIMELINE_ROWS = 30;\n\n/** Точка временного ряда. */\nexport interface TimelinePoint {\n /** Начало интервала. */\n from: string;\n /** Конец интервала. */\n to: string;\n visits: number;\n}\n\n/** Временной ряд одной фразы. */\nexport interface PhraseTimeline {\n phrase: string;\n points: TimelinePoint[];\n /** Суммарные визиты за период. */\n totalVisits: number;\n /**\n * Отношение визитов второй половины периода к первой.\n * Больше 1 — фраза растёт, меньше 1 — затухает; `null`, если первая половина пуста.\n */\n trend: number | null;\n}\n\nexport interface PhraseTimelineOptions extends OrganicPhrasesOptions {\n /** Разбиение шкалы. По умолчанию `day`. */\n group?: TimeGroup;\n /** Сколько top-фраз строить. По умолчанию 10, максимум 30. */\n topPhrases?: number;\n /** Явный список фраз вместо топа. */\n phrases?: string[];\n}\n\n/** Выгружает динамику визитов по органическим поисковым фразам. */\nexport async function getPhraseTimeline(\n reports: ReportsApi,\n options: PhraseTimelineOptions,\n): Promise<PhraseTimeline[]> {\n const topPhrases = Math.min(options.topPhrases ?? 10, MAX_TIMELINE_ROWS);\n const response = await reports.bytime(\n {\n ids: options.counterId,\n dimensions: [DIM.searchPhrase],\n metrics: [METRIC.visits],\n filters: organicFilters(options),\n attribution: options.attribution ?? 'last',\n date1: options.date1,\n date2: options.date2,\n group: options.group ?? 'day',\n ...(options.phrases?.length\n ? { rowIds: options.phrases.map((phrase) => [phrase]) }\n : { topKeys: topPhrases }),\n },\n options.signal,\n );\n\n const intervals = response.time_intervals ?? [];\n return response.data.map((row) => toTimeline(row, intervals));\n}\n\nfunction toTimeline(row: BytimeRow, intervals: [string, string][]): PhraseTimeline {\n const series = row.metrics[0] ?? [];\n const points: TimelinePoint[] = series.map((value, index) => ({\n from: intervals[index]?.[0] ?? '',\n to: intervals[index]?.[1] ?? '',\n visits: typeof value === 'number' && Number.isFinite(value) ? value : 0,\n }));\n\n return {\n phrase: text(row.dimensions[0]),\n points,\n totalVisits: points.reduce((sum, point) => sum + point.visits, 0),\n trend: computeTrend(points),\n };\n}\n\n/** Отношение суммы визитов второй половины ряда к первой. */\nfunction computeTrend(points: TimelinePoint[]): number | null {\n if (points.length < 2) return null;\n const middle = Math.floor(points.length / 2);\n const sum = (slice: TimelinePoint[]): number =>\n slice.reduce((total, point) => total + point.visits, 0);\n const first = sum(points.slice(0, middle));\n if (first === 0) return null;\n return sum(points.slice(middle)) / first;\n}\n","/**\n * Метки качества данных.\n *\n * Метрика скрывает конфиденциальные данные — в том числе поисковые фразы — если\n * в выборке меньше 10 посетителей. Это ровно тот диапазон, где живёт длинный хвост\n * запросов, поэтому строку рядом с порогом нельзя молча считать полной.\n */\nimport type { ReportMeta } from '../reports/types.ts';\nimport type { Warning } from '../client/warnings.ts';\n\n/** Порог раскрытия конфиденциальных данных в отчётах Метрики. */\nexport const PRIVACY_THRESHOLD_USERS = 10;\n\n/** Оговорки, с которыми нужно читать конкретную запись реестра. */\nexport interface KeywordQuality {\n /** Отчёт построен по неполной выборке. */\n sampled: boolean;\n /** В отчёте могли быть скрыты строки с малой выборкой. */\n sensitiveDataHidden: boolean;\n /**\n * Суммарно посетителей меньше порога раскрытия: рядом с этой записью в отчёте\n * почти наверняка не хватает соседних, отсечённых порогом.\n */\n belowPrivacyThreshold: boolean;\n}\n\n/** Диагностика склеенного реестра. */\nexport interface MergedMeta {\n contractVersion: string;\n /** Хотя бы один из отчётов был семплирован. */\n sampled: boolean;\n /** Минимальная доля выборки среди отчётов — худший случай. */\n minSampleShare?: number;\n containsSensitiveData: boolean;\n /** Сколько записей попало под порог раскрытия. */\n belowPrivacyThreshold: number;\n /** Суммарно запросов к API. */\n requests: number;\n warnings: Warning[];\n /** Из каких отчётов собран реестр. */\n sources: string[];\n}\n\n/**\n * Оговорки уровня отчёта. `belowPrivacyThreshold` здесь всегда `false`:\n * он зависит от суммарного числа посетителей ключевого слова и проставляется\n * в конце склейки — см. `isBelowPrivacyThreshold`.\n */\nexport function qualityOf(meta: ReportMeta): KeywordQuality {\n return {\n sampled: meta.sampled,\n sensitiveDataHidden: meta.containsSensitiveData,\n belowPrivacyThreshold: false,\n };\n}\n\n/**\n * Попадает ли ключевое слово под порог раскрытия.\n *\n * Считать это построчно нельзя: одна фраза приходит несколькими строками —\n * разный регистр написания, разные поисковые системы. Редкий вариант с четырьмя\n * посетителями пометил бы всё слово, у которого суммарно их пятьсот.\n * Поэтому флаг считается один раз по итоговой сумме.\n */\nexport function isBelowPrivacyThreshold(users: number): boolean {\n return users > 0 && users < PRIVACY_THRESHOLD_USERS;\n}\n\n/** Объединяет метки уровня отчёта: запись видна в нескольких выгрузках. */\nexport function mergeQuality(a: KeywordQuality, b: KeywordQuality): KeywordQuality {\n return {\n sampled: a.sampled || b.sampled,\n sensitiveDataHidden: a.sensitiveDataHidden || b.sensitiveDataHidden,\n belowPrivacyThreshold: a.belowPrivacyThreshold || b.belowPrivacyThreshold,\n };\n}\n\n/** Сводит метаданные нескольких отчётов в одну диагностику. */\nexport function mergeMeta(\n entries: { source: string; meta: ReportMeta }[],\n belowPrivacyThreshold: number,\n): MergedMeta {\n const shares = entries\n .map(({ meta }) => meta.sampleShare)\n .filter((share): share is number => typeof share === 'number');\n\n return {\n contractVersion: entries[0]?.meta.contractVersion ?? '',\n sampled: entries.some(({ meta }) => meta.sampled),\n ...(shares.length ? { minSampleShare: Math.min(...shares) } : {}),\n containsSensitiveData: entries.some(({ meta }) => meta.containsSensitiveData),\n belowPrivacyThreshold,\n requests: entries.reduce((sum, { meta }) => sum + meta.requests, 0),\n warnings: entries.flatMap(({ meta }) => meta.warnings),\n sources: entries.map(({ source }) => source),\n };\n}\n","/**\n * Слой нормализации: сводит выгрузки органики и Директа в единый реестр ключевых слов.\n *\n * Ключ склейки — нормализованная фраза реального пользовательского запроса\n * (`SearchPhrase` из органики, `DirectSearchPhrase` из Директа). Купленные ключевые\n * слова Директа (`DirectPhraseOrCond`) — другой уровень агрегации, поэтому они не\n * смешиваются с запросами, а складываются в `direct.keywords` и в отдельную сводку\n * `aggregateDirectKeywords`.\n */\nimport type { Report, ReportMeta } from '../reports/types.ts';\nimport type { DirectCostRow } from './directCost.ts';\nimport type { DirectVisitRow } from './directVisits.ts';\nimport type { PhraseLandingRow } from './landing.ts';\nimport type { OrganicPhraseRow } from './organic.ts';\nimport { normalizePhrase } from './shared.ts';\nimport {\n isBelowPrivacyThreshold,\n mergeMeta,\n mergeQuality,\n qualityOf,\n type KeywordQuality,\n type MergedMeta,\n} from './quality.ts';\n\n/** Откуда в реестре взялась фраза. */\nexport type KeywordSource = 'organic' | 'direct_query';\n\n/** Показатели фразы в органическом поиске. */\nexport interface OrganicStats {\n visits: number;\n users: number;\n bounceRate: number;\n pageDepth: number;\n avgVisitDurationSeconds: number;\n /** Поисковые системы, из которых приходили по этой фразе. */\n searchEngines: string[];\n}\n\n/** Показатели фразы в Яндекс Директе. */\nexport interface DirectStats {\n clicks: number;\n visits: number;\n users: number;\n cost: number;\n costPerVisit: number;\n bounceRate: number;\n /** Купленные ключевые слова (условия показа), по которым показывалось объявление. */\n keywords: string[];\n campaigns: string[];\n /** Конверсия по любой цели, если данные пришли из рецепта по визитам. */\n anyGoalConversionRate?: number;\n}\n\n/** Посадочная страница, на которую приходили по фразе. */\nexport interface KeywordLanding {\n url: string;\n visits: number;\n}\n\n/** Запись реестра ключевых слов. */\nexport interface Keyword {\n /** Нормализованная фраза — ключ склейки. */\n phrase: string;\n /** Написание, как его отдал API (первое встреченное). */\n displayPhrase: string;\n sources: KeywordSource[];\n organic?: OrganicStats;\n direct?: DirectStats;\n landings: KeywordLanding[];\n /** Визиты из всех источников — основная величина для сортировки. */\n totalVisits: number;\n /** Посетители из всех источников. По ним считается порог раскрытия. */\n totalUsers: number;\n quality: KeywordQuality;\n}\n\n/** Реестр ключевых слов и диагностика его сборки. */\nexport interface KeywordRegistry {\n keywords: Keyword[];\n meta: MergedMeta;\n}\n\n/** Выгрузки, из которых собирается реестр. Все части необязательны. */\nexport interface MergeInput {\n organic?: Report<OrganicPhraseRow>;\n landings?: Report<PhraseLandingRow>;\n directCost?: Report<DirectCostRow>;\n directVisits?: Report<DirectVisitRow>;\n}\n\n/** Сводка по купленному ключевому слову Директа. */\nexport interface DirectKeywordSummary {\n keyword: string;\n clicks: number;\n visits: number;\n users: number;\n cost: number;\n /** Реальные запросы, приведшие к показу по этому слову. */\n queries: string[];\n campaigns: string[];\n}\n\n/** Склеивает выгрузки в единый реестр, отсортированный по суммарным визитам. */\nexport function mergeKeywords(input: MergeInput): KeywordRegistry {\n const index = new Map<string, Keyword>();\n const metas: { source: string; meta: ReportMeta }[] = [];\n\n if (input.organic) {\n metas.push({ source: 'organic', meta: input.organic.meta });\n for (const row of input.organic.rows) {\n if (!row.phrase) continue;\n const entry = ensure(index, row.phrase, input.organic.meta);\n addSource(entry, 'organic');\n const stats = (entry.organic ??= emptyOrganic());\n stats.visits += row.visits;\n stats.users += row.users;\n // Отказы и глубина — средние: взвешиваем по визитам и делим в конце.\n stats.bounceRate += row.bounceRate * row.visits;\n stats.pageDepth += row.pageDepth * row.visits;\n stats.avgVisitDurationSeconds += row.avgVisitDurationSeconds * row.visits;\n if (row.searchEngine && !stats.searchEngines.includes(row.searchEngine)) {\n stats.searchEngines.push(row.searchEngine);\n }\n }\n }\n\n if (input.directCost) {\n metas.push({ source: 'directCost', meta: input.directCost.meta });\n for (const row of input.directCost.rows) {\n if (!row.query) continue;\n const entry = ensure(index, row.query, input.directCost.meta);\n addSource(entry, 'direct_query');\n const stats = (entry.direct ??= emptyDirect());\n stats.clicks += row.clicks;\n stats.visits += row.visits;\n stats.users += row.users;\n stats.cost += row.cost;\n stats.bounceRate += row.bounceRate * row.visits;\n pushUnique(stats.keywords, row.keyword);\n pushUnique(stats.campaigns, row.campaignName);\n }\n }\n\n if (input.directVisits) {\n metas.push({ source: 'directVisits', meta: input.directVisits.meta });\n for (const row of input.directVisits.rows) {\n if (!row.query) continue;\n const entry = ensure(index, row.query, input.directVisits.meta);\n addSource(entry, 'direct_query');\n const stats = (entry.direct ??= emptyDirect());\n // Клики и расходы приходят только из рецепта C — здесь дополняем визитами и конверсией.\n if (stats.visits === 0) {\n stats.visits = row.visits;\n stats.users = row.users;\n stats.bounceRate = row.bounceRate * row.visits;\n }\n stats.anyGoalConversionRate = row.anyGoalConversionRate;\n pushUnique(stats.keywords, row.keyword);\n }\n }\n\n if (input.landings) {\n metas.push({ source: 'landings', meta: input.landings.meta });\n for (const row of input.landings.rows) {\n if (!row.phrase || !row.url) continue;\n const entry = ensure(index, row.phrase, input.landings.meta);\n const existing = entry.landings.find((landing) => landing.url === row.url);\n if (existing) existing.visits += row.visits;\n else entry.landings.push({ url: row.url, visits: row.visits });\n }\n }\n\n const keywords = [...index.values()];\n for (const keyword of keywords) finalize(keyword);\n keywords.sort((a, b) => b.totalVisits - a.totalVisits || a.phrase.localeCompare(b.phrase));\n\n const belowThreshold = keywords.filter((k) => k.quality.belowPrivacyThreshold).length;\n return { keywords, meta: mergeMeta(metas, belowThreshold) };\n}\n\n/** Сводит расходы Директа по купленным ключевым словам, а не по запросам. */\nexport function aggregateDirectKeywords(\n report: Report<DirectCostRow>,\n): DirectKeywordSummary[] {\n const index = new Map<string, DirectKeywordSummary>();\n\n for (const row of report.rows) {\n if (!row.keyword) continue;\n const key = normalizePhrase(row.keyword);\n let entry = index.get(key);\n if (!entry) {\n entry = {\n keyword: row.keyword,\n clicks: 0,\n visits: 0,\n users: 0,\n cost: 0,\n queries: [],\n campaigns: [],\n };\n index.set(key, entry);\n }\n entry.clicks += row.clicks;\n entry.visits += row.visits;\n entry.users += row.users;\n entry.cost += row.cost;\n pushUnique(entry.queries, row.query);\n pushUnique(entry.campaigns, row.campaignName);\n }\n\n return [...index.values()].sort((a, b) => b.clicks - a.clicks);\n}\n\nfunction ensure(index: Map<string, Keyword>, displayPhrase: string, meta: ReportMeta): Keyword {\n const phrase = normalizePhrase(displayPhrase);\n let entry = index.get(phrase);\n if (!entry) {\n entry = {\n phrase,\n displayPhrase,\n sources: [],\n landings: [],\n totalVisits: 0,\n totalUsers: 0,\n quality: qualityOf(meta),\n };\n index.set(phrase, entry);\n return entry;\n }\n entry.quality = mergeQuality(entry.quality, qualityOf(meta));\n return entry;\n}\n\nfunction addSource(entry: Keyword, source: KeywordSource): void {\n if (!entry.sources.includes(source)) entry.sources.push(source);\n}\n\nfunction pushUnique(list: string[], value: string): void {\n if (value && !list.includes(value)) list.push(value);\n}\n\nfunction emptyOrganic(): OrganicStats {\n return {\n visits: 0,\n users: 0,\n bounceRate: 0,\n pageDepth: 0,\n avgVisitDurationSeconds: 0,\n searchEngines: [],\n };\n}\n\nfunction emptyDirect(): DirectStats {\n return {\n clicks: 0,\n visits: 0,\n users: 0,\n cost: 0,\n costPerVisit: 0,\n bounceRate: 0,\n keywords: [],\n campaigns: [],\n };\n}\n\n/** Доводит взвешенные суммы до средних и считает итоги. */\nfunction finalize(keyword: Keyword): void {\n if (keyword.organic && keyword.organic.visits > 0) {\n const { visits } = keyword.organic;\n keyword.organic.bounceRate = round(keyword.organic.bounceRate / visits);\n keyword.organic.pageDepth = round(keyword.organic.pageDepth / visits);\n keyword.organic.avgVisitDurationSeconds = round(\n keyword.organic.avgVisitDurationSeconds / visits,\n );\n }\n if (keyword.direct) {\n if (keyword.direct.visits > 0) {\n keyword.direct.bounceRate = round(keyword.direct.bounceRate / keyword.direct.visits);\n keyword.direct.costPerVisit = round(keyword.direct.cost / keyword.direct.visits);\n }\n keyword.direct.cost = round(keyword.direct.cost);\n }\n keyword.landings.sort((a, b) => b.visits - a.visits);\n keyword.totalVisits = (keyword.organic?.visits ?? 0) + (keyword.direct?.visits ?? 0);\n // Посетители из разных источников складываются: пересечение аудиторий Метрика\n // не раскрывает, поэтому это оценка сверху — для порога раскрытия её достаточно.\n keyword.totalUsers = (keyword.organic?.users ?? 0) + (keyword.direct?.users ?? 0);\n keyword.quality.belowPrivacyThreshold = isBelowPrivacyThreshold(keyword.totalUsers);\n}\n\nfunction round(value: number): number {\n return Math.round(value * 100) / 100;\n}\n","/**\n * Фасад библиотеки: клиент, отчёты и рецепты выгрузки ключевых слов в одном объекте.\n */\nimport { MetrikaHttpClient, type MetrikaClientOptions } from './client/http.ts';\nimport { contractParsedAt, contractSourceSha256, contractVersion } from './contract/registry.ts';\nimport { ManagementApi } from './management/api.ts';\nimport { ReportsApi, type ReportsApiOptions } from './reports/data.ts';\nimport type { Report } from './reports/types.ts';\nimport {\n getDirectSearchPhraseCost,\n type DirectCostOptions,\n type DirectCostRow,\n} from './keywords/directCost.ts';\nimport {\n getDirectKeywordsByVisits,\n type DirectVisitRow,\n} from './keywords/directVisits.ts';\nimport { getPhraseLandingMap, type PhraseLandingRow } from './keywords/landing.ts';\nimport {\n getOrganicSearchPhrases,\n type OrganicPhraseRow,\n type OrganicPhrasesOptions,\n} from './keywords/organic.ts';\nimport {\n getPhraseTimeline,\n type PhraseTimeline,\n type PhraseTimelineOptions,\n} from './keywords/timeline.ts';\nimport { mergeKeywords, type KeywordRegistry } from './keywords/merge.ts';\nimport type { KeywordQueryOptions } from './keywords/shared.ts';\n\nexport type MetrikaOptions = MetrikaClientOptions & ReportsApiOptions;\n\n/** Что именно собирать в реестр ключевых слов. */\nexport interface KeywordRegistryOptions extends OrganicPhrasesOptions {\n /** Добавить связку «фраза → посадочная страница». По умолчанию `true`. */\n withLandings?: boolean;\n /**\n * Добавить клики и расходы Директа. По умолчанию `true`.\n * Логины клиентов подставляются автоматически; если доступа к Директу нет,\n * блок пропускается с предупреждением.\n */\n withDirect?: boolean;\n /** Готовые логины клиентов Директа — чтобы не тратить запрос на их получение. */\n directClientLogins?: string[];\n}\n\n/** Точка входа: `new YandexMetrika({ token })`. */\nexport class YandexMetrika {\n readonly http: MetrikaHttpClient;\n readonly reports: ReportsApi;\n readonly management: ManagementApi;\n\n constructor(options: MetrikaOptions) {\n this.http = new MetrikaHttpClient(options);\n this.reports = new ReportsApi(this.http, {\n allowUnknownFields: options.allowUnknownFields ?? false,\n });\n this.management = new ManagementApi(this.http);\n }\n\n /** Версия контракта, по которой собрана библиотека. */\n contract(): { version: string; sourceSha256: string; parsedAt: string } {\n return { version: contractVersion, sourceSha256: contractSourceSha256, parsedAt: contractParsedAt };\n }\n\n /** Рецепт A: поисковые фразы органики. */\n getOrganicSearchPhrases(options: OrganicPhrasesOptions): Promise<Report<OrganicPhraseRow>> {\n return getOrganicSearchPhrases(this.reports, options);\n }\n\n /** Рецепт B: фраза × посадочная страница. */\n getPhraseLandingMap(options: OrganicPhrasesOptions): Promise<Report<PhraseLandingRow>> {\n return getPhraseLandingMap(this.reports, options);\n }\n\n /**\n * Рецепт C: запросы Директа с кликами и расходами.\n * Если `directClientLogins` не передан, логины запрашиваются автоматически.\n */\n async getDirectSearchPhraseCost(\n options: Omit<DirectCostOptions, 'directClientLogins'> & { directClientLogins?: string[] },\n ): Promise<Report<DirectCostRow>> {\n const logins =\n options.directClientLogins ??\n (await this.management.getDirectClientLogins(options.counterId, options.signal));\n return getDirectSearchPhraseCost(this.reports, { ...options, directClientLogins: logins });\n }\n\n /** Рецепт D: ключевые слова Директа по визитам, без доступа к кампаниям. */\n getDirectKeywordsByVisits(\n options: KeywordQueryOptions & { excludeRobots?: boolean },\n ): Promise<Report<DirectVisitRow>> {\n return getDirectKeywordsByVisits(this.reports, options);\n }\n\n /** Рецепт E: динамика фраз во времени. */\n getPhraseTimeline(options: PhraseTimelineOptions): Promise<PhraseTimeline[]> {\n return getPhraseTimeline(this.reports, options);\n }\n\n /**\n * Сквозной сценарий: выгружает органику, посадочные страницы и Директ,\n * склеивает в единый реестр ключевых слов.\n */\n async buildKeywordRegistry(options: KeywordRegistryOptions): Promise<KeywordRegistry> {\n const organic = await this.getOrganicSearchPhrases(options);\n\n const landings =\n options.withLandings === false ? undefined : await this.getPhraseLandingMap(options);\n\n let directCost: Report<DirectCostRow> | undefined;\n let directVisits: Report<DirectVisitRow> | undefined;\n\n if (options.withDirect !== false) {\n const logins =\n options.directClientLogins ??\n (await this.management\n .getDirectClientLogins(options.counterId, options.signal)\n .catch(() => [] as string[]));\n\n if (logins.length > 0) {\n directCost = await getDirectSearchPhraseCost(this.reports, {\n ...options,\n directClientLogins: logins,\n });\n } else {\n this.http.warn({\n code: 'direct_access_missing',\n message:\n 'Нет доступных логинов клиентов Директа — клики и расходы пропущены. ' +\n 'Ключевые слова Директа выгружены по визитам (без кликов и денег).',\n });\n directVisits = await this.getDirectKeywordsByVisits(options);\n }\n }\n\n return mergeKeywords({\n organic,\n ...(landings ? { landings } : {}),\n ...(directCost ? { directCost } : {}),\n ...(directVisits ? { directVisits } : {}),\n });\n }\n}\n","/**\n * Идентификаторы, на которых держатся рецепты библиотеки.\n *\n * `check-contract` падает, если что-то отсюда исчезло или изменилось в документации:\n * это ровно тот набор, поломка которого ломает библиотеку, а не просто расширяет API.\n * Записи в `<attribution>`/`<currency>`-форме — как в документации, до подстановки параметров.\n */\n\n/** Группировки, используемые рецептами. Ключ — идентификатор, значение — где он нужен. */\nexport const USED_DIMENSIONS: Readonly<Record<string, string>> = {\n 'ym:s:<attribution>SearchPhrase': 'organic: поисковая фраза',\n 'ym:s:<attribution>SearchEngineRoot': 'organic: поисковая система',\n 'ym:s:<attribution>TrafficSource': 'organic: фильтр по источнику трафика',\n 'ym:s:isRobot': 'organic: отсечка роботов',\n 'ym:s:startURL': 'landing: посадочная страница',\n 'ym:s:<attribution>DirectSearchPhrase': 'directVisits: реальный запрос Директа',\n 'ym:s:<attribution>DirectPhraseOrCond': 'directVisits: условие показа',\n 'ym:ad:<attribution>DirectSearchPhrase': 'directCost: реальный запрос Директа',\n 'ym:ad:<attribution>DirectPhraseOrCond': 'directCost: условие показа',\n 'ym:ad:<attribution>DirectOrder': 'directCost: кампания',\n 'ym:ad:<attribution>DirectConditionType': 'directCost: тип условия показа',\n};\n\n/** Метрики, используемые рецептами. */\nexport const USED_METRICS: Readonly<Record<string, string>> = {\n 'ym:s:visits': 'organic, directVisits',\n 'ym:s:users': 'organic, directVisits',\n 'ym:s:bounceRate': 'organic, directVisits',\n 'ym:s:pageDepth': 'organic',\n 'ym:s:avgVisitDurationSeconds': 'organic, landing',\n 'ym:s:anyGoalConversionRate': 'directVisits',\n 'ym:ad:clicks': 'directCost: клики по рекламе',\n 'ym:ad:visits': 'directCost',\n 'ym:ad:users': 'directCost',\n 'ym:ad:bounceRate': 'directCost',\n 'ym:ad:<currency>ConvertedAdCost': 'directCost: расходы',\n 'ym:ad:<currency>ConvertedAdCostPerVisit': 'directCost: стоимость визита',\n};\n\n/** Шаблоны, на которые библиотека ссылается в документации и тестах. */\nexport const USED_PRESETS: Readonly<Record<string, string>> = {\n sources_search_phrases: 'эквивалент рецепта organic без отсечки роботов',\n sources_direct_summary: 'эквивалент рецепта directVisits',\n sources_direct_clicks: 'эквивалент рецепта directCost',\n};\n"],"mappings":";AAIO,IAAM,kBAAkB;AAGxB,IAAM,uBAAuB;AAG7B,IAAM,mBAAmB;AAGzB,IAAM,gBAAqC,oBAAI,IAAI;AAAA,EACxD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGM,IAAM,aAAkC,oBAAI,IAAI;AAAA,EACrD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGM,IAAM,aAAkC,oBAAI,IAAI;AAAA,EACrD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;;;ACryCD,IAAM,eAAe;AAGd,SAAS,YAAYA,KAAgC;AAC1D,SAAO,aAAa,KAAKA,GAAE,IAAI,CAAC;AAClC;AAuBO,IAAM,0BAAiE;AAAA,EAC5E,OAAO;AAAA,EACP,kBAAkB;AAAA,EAClB,0BAA0B;AAC5B;AAMO,SAAS,aAAaC,KAAqB;AAChD,SAAO,cAAc,IAAIA,GAAE;AAC7B;AAGO,SAAS,UAAUA,KAAqB;AAC7C,SAAO,WAAW,IAAIA,GAAE;AAC1B;AAGO,SAAS,UAAUA,KAAqB;AAC7C,SAAO,WAAW,IAAIA,GAAE;AAC1B;;;AChDO,IAAM,eAAN,cAA2B,MAAM;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,SAAiB,SAK1B;AACD,UAAM,OAAO;AACb,SAAK,OAAO,WAAW;AACvB,SAAK,SAAS,QAAQ;AACtB,SAAK,YAAY,QAAQ;AACzB,SAAK,UAAU,QAAQ;AACvB,SAAK,aAAa,QAAQ;AAAA,EAC5B;AACF;AAGO,IAAM,aAAN,cAAyB,aAAa;AAAA;AAAA,EAElC;AAAA,EAET,YACE,SACA,SACA;AACA,UAAM,SAAS,OAAO;AACtB,SAAK,eAAe,QAAQ;AAAA,EAC9B;AACF;AAGO,IAAM,YAAN,cAAwB,aAAa;AAAC;AAGtC,IAAM,sBAAN,cAAkC,aAAa;AAAC;AAGhD,IAAM,gBAAN,cAA4B,aAAa;AAAC;AAG1C,IAAM,cAAN,cAA0B,aAAa;AAAC;AAGxC,IAAM,yBAAN,cAAqC,MAAM;AAAA,EAChD,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAEA,IAAM,aAAa,oBAAI,IAAI,CAAC,iBAAiB,gBAAgB,iBAAiB,oBAAoB,CAAC;AACnG,IAAM,eAAe,oBAAI,IAAI,CAAC,iBAAiB,SAAS,CAAC;AAMzD,IAAM,iBAAmD;AAAA,EACvD,sBAAsB;AAAA,EACtB,yBAAyB;AAAA,EACzB,uBAAuB,IAAI;AAAA,EAC3B,8BAA8B,IAAI;AAAA,EAClC,yBAAyB,KAAK;AAAA,EAC9B,uBAAuB,KAAK;AAC9B;AAGO,SAAS,eACd,QACA,MACA,YACc;AACd,QAAM,UAAU,MAAM,UAAU,CAAC;AACjC,QAAM,YAAY,QAAQ,CAAC,GAAG,cAAc,QAAQ,MAAM;AAC1D,QAAM,UACJ,QAAQ,CAAC,GAAG,WAAW,MAAM,WAAW,yNAA+C,MAAM;AAC/F,QAAM,UAAU,EAAE,QAAQ,WAAW,SAAS,WAAW;AACzD,QAAM,OAAO,GAAG,OAAO,KAAK,SAAS,UAAU,MAAM;AAErD,MAAI,WAAW,OAAO,UAAU,WAAW,QAAQ,GAAG;AACpD,WAAO,IAAI,WAAW,MAAM;AAAA,MAC1B,GAAG;AAAA,MACH,cAAc,eAAe,SAAS,KAAK;AAAA,IAC7C,CAAC;AAAA,EACH;AACA,MAAI,WAAW,OAAO,WAAW,OAAO,WAAW,IAAI,SAAS,GAAG;AACjE,WAAO,IAAI,UAAU,MAAM,OAAO;AAAA,EACpC;AACA,MAAI,WAAW,OAAO,cAAc,YAAa,QAAO,IAAI,cAAc,MAAM,OAAO;AACvF,MAAI,UAAU,OAAO,aAAa,IAAI,SAAS,EAAG,QAAO,IAAI,YAAY,MAAM,OAAO;AACtF,SAAO,IAAI,oBAAoB,MAAM,OAAO;AAC9C;AAGO,SAAS,YAAY,OAAyB;AACnD,SAAO,iBAAiB,cAAc,iBAAiB;AACzD;;;AC9FA,IAAM,SAAS;AACf,IAAM,eAAe,IAAI,KAAK;AAE9B,IAAM,eAAe,CAAC,OACpB,IAAI,QAAQ,CAAC,YAAY;AACvB,aAAW,SAAS,EAAE;AACxB,CAAC;AAGH,SAAS,OAAO,WAA2B;AACzC,SAAO,KAAK,MAAM,YAAY,KAAU;AAC1C;AAGA,SAAS,MAAM,YAAsB,KAAa,UAAwB;AACxE,QAAM,SAAS,MAAM;AACrB,MAAI,OAAO;AACX,SAAO,OAAO,WAAW,UAAU,WAAW,IAAI,KAAM,OAAQ,SAAQ;AACxE,MAAI,OAAO,EAAG,YAAW,OAAO,GAAG,IAAI;AACzC;AAEO,IAAM,cAAN,MAAkB;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,WAAW;AAAA,EACF,eAAyB,CAAC;AAAA,EAC1B,eAAyB,CAAC;AAAA,EACnC,SAAS;AAAA,EACT,WAAW;AAAA;AAAA,EAEF,UAA0B,CAAC;AAAA,EAE5C,YAAY,UAA4B,CAAC,GAAG;AAC1C,SAAK,gBAAgB,QAAQ,iBAAiB;AAC9C,SAAK,YAAY,QAAQ,aAAa;AACtC,SAAK,iBAAiB,QAAQ,kBAAkB;AAChD,SAAK,SAAS,QAAQ,UAAU;AAChC,SAAK,MAAM,QAAQ,OAAO,KAAK;AAC/B,SAAK,QAAQ,QAAQ,SAAS;AAAA,EAChC;AAAA;AAAA,EAGA,MAAM,SAAY,OAAmB,IAAkC;AACrE,UAAM,KAAK,QAAQ,KAAK;AACxB,QAAI;AACF,aAAO,MAAM,GAAG;AAAA,IAClB,UAAE;AACA,WAAK,QAAQ;AAAA,IACf;AAAA,EACF;AAAA;AAAA,EAGA,QAA0F;AACxF,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,KAAK,cAAc,KAAK,MAAM;AACpC,UAAM,KAAK,cAAc,KAAK,YAAY;AAC1C,SAAK,QAAQ,GAAG;AAChB,WAAO;AAAA,MACL,UAAU,KAAK;AAAA,MACf,YAAY,KAAK,aAAa;AAAA,MAC9B,iBAAiB,KAAK,aAAa;AAAA,MACnC,OAAO,KAAK;AAAA,IACd;AAAA,EACF;AAAA,EAEQ,QAAQ,KAAmB;AACjC,UAAM,MAAM,OAAO,GAAG;AACtB,QAAI,QAAQ,KAAK,QAAQ;AACvB,WAAK,SAAS;AACd,WAAK,WAAW;AAAA,IAClB;AAAA,EACF;AAAA,EAEA,MAAc,QAAQ,OAAkC;AACtD,eAAS;AACP,YAAM,MAAM,KAAK,IAAI;AACrB,YAAM,KAAK,cAAc,KAAK,MAAM;AACpC,YAAM,KAAK,cAAc,KAAK,YAAY;AAC1C,WAAK,QAAQ,GAAG;AAEhB,YAAM,OAAO,KAAK,OAAO,OAAO,GAAG;AACnC,UAAI,SAAS,GAAG;AACd,aAAK,YAAY;AACjB,aAAK,aAAa,KAAK,GAAG;AAC1B,aAAK,YAAY;AACjB,YAAI,UAAU,SAAU,MAAK,aAAa,KAAK,GAAG;AAClD;AAAA,MACF;AAEA,UAAI,KAAK,WAAW,KAAK,SAAS,OAAO,mBAAmB;AAE1D,cAAM,IAAI,QAAc,CAAC,YAAY,KAAK,QAAQ,KAAK,OAAO,CAAC;AAC/D;AAAA,MACF;AACA,YAAM,KAAK,MAAM,KAAK,IAAI,MAAM,YAAY,CAAC;AAAA,IAC/C;AAAA,EACF;AAAA;AAAA,EAGQ,OAAO,OAAmB,KAAqB;AACrD,QAAI,KAAK,YAAY,KAAK,QAAQ;AAChC,YAAM,gBAAgB,OAAO,GAAG,IAAI,KAAK;AACzC,aAAO,eAAe;AAAA,IACxB;AACA,QAAI,KAAK,aAAa,UAAU,KAAK,WAAW;AAC9C,aAAO,KAAK,aAAa,CAAC,IAAK,SAAS;AAAA,IAC1C;AACA,QAAI,UAAU,YAAY,KAAK,aAAa,UAAU,KAAK,gBAAgB;AACzE,aAAO,KAAK,aAAa,CAAC,IAAK,eAAe;AAAA,IAChD;AACA,QAAI,KAAK,YAAY,KAAK,cAAe,QAAO,OAAO;AACvD,WAAO;AAAA,EACT;AAAA,EAEQ,UAAgB;AACtB,SAAK,YAAY;AACjB,SAAK,QAAQ,MAAM,IAAI;AAAA,EACzB;AACF;;;ACzHO,IAAM,wBAAwC,CAAC,YAAY;AAChE,UAAQ,KAAK,8BAA8B,QAAQ,IAAI,KAAK,QAAQ,OAAO,EAAE;AAC/E;;;ACxBO,IAAM,mBAAmB;AAmChC,IAAM,QAAQ,CAAC,OACb,IAAI,QAAQ,CAAC,YAAY;AACvB,aAAW,SAAS,EAAE;AACxB,CAAC;AAUI,SAAS,eAAe,SAG7B;AACA,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,SAAyB,CAAC;AAEhC,aAAW,UAAU,SAAS;AAC5B,QAAI,OAAO,SAAS;AAClB,iBAAW,MAAM,OAAO,MAAM;AAC9B;AAAA,IACF;AACA,UAAM,UAAU,MAAY,WAAW,MAAM,OAAO,MAAM;AAC1D,WAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AACxD,WAAO,KAAK,MAAM,OAAO,oBAAoB,SAAS,OAAO,CAAC;AAAA,EAChE;AAEA,SAAO;AAAA,IACL,QAAQ,WAAW;AAAA,IACnB,SAAS,MAAM;AACb,iBAAW,OAAO,OAAQ,KAAI;AAAA,IAChC;AAAA,EACF;AACF;AAGA,SAAS,UAAU,OAA+C;AAChE,SAAO,MAAM,QAAQ,KAAK,IAAI,MAAM,KAAK,GAAG,IAAI,OAAO,KAAK;AAC9D;AAEO,SAAS,SACd,SACA,MACA,QAAoC,CAAC,GAC7B;AACR,QAAM,MAAM,IAAI,IAAI,MAAM,OAAO;AACjC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,QAAI,UAAU,OAAW;AACzB,QAAI,aAAa,IAAI,KAAK,UAAU,KAAK,CAAC;AAAA,EAC5C;AACA,SAAO,IAAI,SAAS;AACtB;AAGO,IAAM,oBAAN,MAAwB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EAEQ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,SAA+B;AACzC,QAAI,CAAC,QAAQ,MAAO,OAAM,IAAI,MAAM,8KAAuC;AAC3E,SAAK,QAAQ,QAAQ;AACrB,SAAK,UAAU,QAAQ,WAAW;AAClC,SAAK,YAAY,QAAQ,SAAS,WAAW,MAAM,KAAK,UAAU;AAClE,SAAK,aAAa,QAAQ,cAAc;AACxC,SAAK,kBAAkB,QAAQ,mBAAmB;AAClD,SAAK,YAAY,QAAQ,aAAa;AACtC,SAAK,OAAO,QAAQ,QAAQ;AAC5B,SAAK,OAAO,QAAQ,aAAa;AACjC,SAAK,UACH,QAAQ,qBAAqB,cACzB,QAAQ,YACR,IAAI,YAAY,QAAQ,SAAS;AAAA,EACzC;AAAA;AAAA,EAGA,MAAM,IAAO,SAAqC;AAChD,UAAM,MAAM,SAAS,KAAK,SAAS,QAAQ,MAAM,QAAQ,KAAK;AAC9D,QAAI;AAEJ,aAAS,UAAU,GAAG,WAAW,KAAK,YAAY,WAAW,GAAG;AAC9D,UAAI;AACF,eAAO,MAAM,KAAK,QAAQ,SAAS,QAAQ,OAAO,MAAM,KAAK,KAAQ,KAAK,QAAQ,MAAM,CAAC;AAAA,MAC3F,SAAS,OAAO;AACd,oBAAY;AACZ,YAAI,CAAC,YAAY,KAAK,KAAK,YAAY,KAAK,WAAY,OAAM;AAC9D,cAAM,QAAQ,KAAK,WAAW,OAAO,OAAO;AAC5C,YAAI,UAAU,OAAW,OAAM;AAC/B,cAAM,MAAM,KAAK;AAAA,MACnB;AAAA,IACF;AACA,UAAM;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,WAAW,OAAgB,SAAqC;AACtE,UAAM,WAAY,MAAoC;AACtD,UAAM,UAAU,KAAK,IAAI,MAAQ,KAAK,SAAS,KAAK,eAAe;AACnE,UAAM,QAAQ,YAAY;AAC1B,WAAO,QAAQ,KAAK,kBAAkB,SAAY;AAAA,EACpD;AAAA,EAEA,MAAc,KAAQ,KAAa,QAAkC;AACnE,UAAM,UAAU,YAAY,QAAQ,KAAK,SAAS;AAClD,UAAM,WAAW,eAAe,SAAS,CAAC,QAAQ,OAAO,IAAI,CAAC,OAAO,CAAC;AAEtE,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,KAAK,UAAU,KAAK;AAAA,QACnC,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,eAAe,SAAS,KAAK,KAAK;AAAA,UAClC,QAAQ;AAAA,UACR,cAAc,sCAAsC,eAAe;AAAA,QACrE;AAAA,QACA,QAAQ,SAAS;AAAA,MACnB,CAAC;AAAA,IACH,UAAE;AACA,eAAS,QAAQ;AAAA,IACnB;AAEA,UAAMC,QAAO,MAAM,SAAS,KAAK;AACjC,UAAM,OAAgBA,QAAO,SAASA,KAAI,IAAI;AAE9C,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,eAAe,SAAS,QAAQ,MAAkC,GAAG;AAAA,IAC7E;AACA,WAAO;AAAA,EACT;AACF;AAEA,SAAS,SAASA,OAAuB;AACvC,MAAI;AACF,WAAO,KAAK,MAAMA,KAAI;AAAA,EACxB,QAAQ;AACN,WAAO,EAAE,SAASA,MAAK,MAAM,GAAG,GAAG,EAAE;AAAA,EACvC;AACF;;;AC7HO,IAAM,qBAAN,cAAiC,MAAM;AAAA,EACnC;AAAA,EAET,YAAY,SAAiB,YAA4B;AACvD,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AACF;AAEO,IAAM,gBAAN,MAAoB;AAAA,EACzB,YAA6B,MAAyB;AAAzB;AAAA,EAA0B;AAAA,EAA1B;AAAA;AAAA,EAG7B,MAAM,YAAY,UAA8B,CAAC,GAA4B;AAC3E,UAAM,WAAW,MAAM,KAAK,KAAK,IAAsB;AAAA,MACrD,MAAM;AAAA,MACN,OAAO;AAAA,QACL,eAAe,QAAQ;AAAA,QACvB,YAAY,QAAQ,YAAY,SAAS,QAAQ,aAAa;AAAA,QAC9D,UAAU,QAAQ;AAAA,QAClB,QAAQ,QAAQ;AAAA;AAAA,QAEhB,OAAO;AAAA,MACT;AAAA,MACA,OAAO;AAAA,MACP,QAAQ,QAAQ;AAAA,IAClB,CAAC;AACD,YAAQ,SAAS,YAAY,CAAC,GAAG,IAAI,cAAc;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,kBAAkB,MAAc,QAA6C;AACjF,UAAM,SAAS,cAAc,IAAI;AACjC,UAAM,WAAW,MAAM,KAAK,YAAY;AAAA,MACtC,cAAc;AAAA,MACd,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,IAC7B,CAAC;AAGD,UAAM,QAAQ,SAAS;AAAA,MACrB,CAAC,YACC,cAAc,QAAQ,IAAI,MAAM,UAChC,QAAQ,QAAQ,KAAK,CAAC,WAAW,cAAc,MAAM,MAAM,MAAM;AAAA,IACrE;AACA,UAAM,UAAU,MAAM,SAAS,IAAI,QAAQ;AAE3C,QAAI,QAAQ,WAAW,EAAG,QAAO,QAAQ,CAAC;AAE1C,QAAI,QAAQ,WAAW,GAAG;AACxB,YAAM,IAAI;AAAA,QACR,iGAAsB,IAAI;AAAA,QAE1B,CAAC;AAAA,MACH;AAAA,IACF;AACA,UAAM,IAAI;AAAA,MACR,mCAAU,IAAI,mMACT,QAAQ,IAAI,CAAC,YAAY,GAAG,QAAQ,EAAE,KAAK,QAAQ,IAAI,GAAG,EAAE,KAAK,IAAI,CAAC;AAAA,MAE3E;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,iBACJ,YACA,QACyB;AACzB,UAAM,WAAW,MAAM,QAAQ,UAAU,IAAI,aAAa,CAAC,UAAU;AACrE,UAAM,WAAW,MAAM,KAAK,KAAK,IAAqB;AAAA,MACpD,MAAM;AAAA,MACN,OAAO,EAAE,SAAS;AAAA,MAClB,OAAO;AAAA,MACP;AAAA,IACF,CAAC;AACD,WAAO,SAAS,WAAW,CAAC;AAAA,EAC9B;AAAA;AAAA,EAGA,MAAM,sBACJ,YACA,QACmB;AACnB,UAAM,UAAU,MAAM,KAAK,iBAAiB,YAAY,MAAM;AAC9D,WAAO,CAAC,GAAG,IAAI,IAAI,QAAQ,IAAI,CAAC,WAAW,OAAO,WAAW,EAAE,OAAO,OAAO,CAAC,CAAC;AAAA,EACjF;AACF;AAEA,SAAS,eAAe,KAA+B;AACrD,SAAO;AAAA,IACL,IAAI,IAAI;AAAA,IACR,MAAM,IAAI,QAAQ;AAAA,IAClB,MAAM,IAAI,OAAO,QAAQ;AAAA,IACzB,UAAU,IAAI,YAAY,CAAC,GACxB,IAAI,CAAC,WAAY,OAAO,WAAW,WAAW,SAAS,QAAQ,IAAK,EACpE,OAAO,CAAC,SAAyB,QAAQ,IAAI,CAAC;AAAA,IACjD,GAAI,IAAI,SAAS,EAAE,QAAQ,IAAI,OAAO,IAAI,CAAC;AAAA,IAC3C,GAAI,IAAI,aAAa,EAAE,YAAY,IAAI,WAAW,IAAI,CAAC;AAAA,IACvD,GAAI,IAAI,cAAc,EAAE,YAAY,IAAI,YAAY,IAAI,CAAC;AAAA,EAC3D;AACF;AAGA,SAAS,cAAc,MAAsB;AAC3C,SAAO,KACJ,KAAK,EACL,YAAY,EACZ,QAAQ,gBAAgB,EAAE,EAC1B,QAAQ,UAAU,EAAE,EACpB,QAAQ,QAAQ,EAAE;AACvB;;;AC/KO,IAAM,mBAAmB;AAYzB,SAAS,aAAa,OAAO,IAAI,UAAkB,kBAA6B;AACrF,MAAI,OAAO,EAAG,OAAM,IAAI,WAAW,8MAAyC;AAC5E,SAAO;AAAA,IACL,OAAO,GAAG,UAAU,OAAO,CAAC;AAAA,IAC5B,OAAO,GAAG,OAAO;AAAA,EACnB;AACF;;;ACXO,IAAM,SAAS;AAAA,EACpB,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB,iBAAiB;AACnB;AAMA,SAAS,WAAW,KAAqC;AACvD,QAAM,SAAS,oBAAI,IAAY;AAC/B,aAAWC,OAAM,KAAK;AACpB,UAAM,KAAK,YAAYA,GAAE;AACzB,QAAI,GAAI,QAAO,IAAI,EAAE;AAAA,EACvB;AACA,SAAO;AACT;AAEA,IAAM,uBAAuB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAQO,SAAS,eAAeA,KAAoB;AACjD,QAAM,QAAQ,yBAAyB,KAAKA,GAAE;AAC9C,MAAI,CAAC,MAAO,QAAOA;AACnB,QAAM,CAAC,EAAE,QAAQ,IAAI,IAAI;AAEzB,MAAI,OAAO;AACX,aAAW,eAAe,sBAAsB;AAC9C,QAAI,KAAK,WAAW,WAAW,KAAK,SAAS,KAAK,KAAK,MAAM,YAAY,MAAM,CAAC,GAAG;AACjF,aAAO,gBAAgB,KAAK,MAAM,YAAY,MAAM,CAAC;AACrD;AAAA,IACF;AAAA,EACF;AACA,SAAO,KACJ,QAAQ,wBAAwB,YAAY,EAC5C,QAAQ,YAAY,eAAe,EACnC,QAAQ,oBAAoB,6BAA6B,EACzD,QAAQ,4CAA4C,mBAAmB;AAE1E,SAAO,GAAG,MAAM,GAAG,IAAI;AACzB;AAOO,SAAS,cACd,OACA,UAA4C,CAAC,GAC3B;AAClB,QAAM,WAAsB,CAAC;AAC7B,QAAM,aAAa,MAAM,cAAc,CAAC;AACxC,QAAM,UAAU,MAAM,WAAW,CAAC;AAElC,MAAI,CAAC,MAAM,UAAU,QAAQ,WAAW,GAAG;AACzC,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,MAAI,WAAW,SAAS,OAAO,eAAe;AAC5C,UAAM,IAAI;AAAA,MACR,yHAA0B,WAAW,MAAM,sDAAc,OAAO,aAAa;AAAA,IAC/E;AAAA,EACF;AACA,MAAI,QAAQ,SAAS,OAAO,YAAY;AACtC,UAAM,IAAI;AAAA,MACR,2FAAqB,QAAQ,MAAM,sDAAc,OAAO,UAAU;AAAA,IACpE;AAAA,EACF;AACA,MAAI,MAAM,UAAU,WAAc,MAAM,QAAQ,KAAK,MAAM,QAAQ,OAAO,oBAAoB;AAC5F,UAAM,IAAI;AAAA,MACR,4IAAmC,OAAO,iBAAiB,sDAAc,MAAM,KAAK;AAAA,IACtF;AAAA,EACF;AACA,MAAI,MAAM,WAAW,UAAa,MAAM,SAAS,GAAG;AAClD,UAAM,IAAI,uBAAuB,kIAAmC,MAAM,MAAM,EAAE;AAAA,EACpF;AACA,MAAI,MAAM,WAAW,MAAM,QAAQ,SAAS,OAAO,iBAAiB;AAClE,UAAM,IAAI;AAAA,MACR,0CAAiB,MAAM,QAAQ,MAAM,uGAAuB,OAAO,eAAe;AAAA,IACpF;AAAA,EACF;AAGA,QAAM,OAAO,WAAW,CAAC,GAAG,YAAY,GAAG,OAAO,CAAC;AACnD,MAAI,KAAK,OAAO,GAAG;AACjB,UAAM,IAAI;AAAA,MACR,mRAAuD,CAAC,GAAG,IAAI,EAC5D,IAAI,CAAC,OAAO,MAAM,EAAE,GAAG,EACvB,KAAK,IAAI,CAAC;AAAA,IACf;AAAA,EACF;AAGA,MAAI,KAAK,IAAI,IAAI,KAAK,CAAC,MAAM,oBAAoB,QAAQ;AACvD,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AAEA,MAAI,MAAM,UAAU,CAAC,UAAU,MAAM,MAAM,GAAG;AAC5C,kBAAc,yCAAW,MAAM,MAAM,KAAK,SAAS,UAAU,EAAE,QAAQ,MAAM,OAAO,CAAC;AAAA,EACvF;AACA,aAAWA,OAAM,YAAY;AAC3B,QAAI,CAAC,aAAa,eAAeA,GAAE,CAAC,GAAG;AACrC,oBAAc,uEAAgBA,GAAE,KAAK,SAAS,UAAU,EAAE,WAAWA,IAAG,CAAC;AAAA,IAC3E;AAAA,EACF;AACA,aAAWA,OAAM,SAAS;AACxB,QAAI,CAAC,UAAU,eAAeA,GAAE,CAAC,GAAG;AAClC,oBAAc,+CAAYA,GAAE,KAAK,SAAS,UAAU,EAAE,QAAQA,IAAG,CAAC;AAAA,IACpE;AAAA,EACF;AAEA,MAAI,MAAM,eAAe,MAAM,eAAe,yBAAyB;AACrE,UAAM,cAAc,wBAAwB,MAAM,WAAW;AAC7D,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,SACE,gGAAqB,MAAM,WAAW,4TACJ,WAAW;AAAA,MAC/C,SAAS,EAAE,WAAW,MAAM,aAAa,YAAY;AAAA,IACvD,CAAC;AAAA,EACH;AAEA,SAAO,EAAE,SAAS;AACpB;AAEA,SAAS,cACP,MACA,SACA,UACA,SACM;AACN,QAAM,UACJ,sEAAe,IAAI;AAErB,MAAI,QAAQ,oBAAoB;AAC9B,aAAS,KAAK,EAAE,MAAM,iBAAiB,SAAS,QAAQ,CAAC;AACzD;AAAA,EACF;AACA,QAAM,IAAI,uBAAuB,OAAO;AAC1C;;;AC7JA,IAAM,oBAAoB,OAAO;AAyB1B,SAAS,cAAc,OAAkB,MAA+C;AAC7F,QAAM,QAAQ,EAAE,OAAO,MAAM,OAAO,OAAO,MAAM,MAAM;AACvD,SAAO;AAAA,IACL,KAAK,MAAM,QAAQ,MAAM,GAAG,IAAI,MAAM,MAAM,CAAC,MAAM,GAAG;AAAA,IACtD,SAAS,MAAM,QAAQ,SAAS,MAAM,UAAU;AAAA,IAChD,YAAY,MAAM,YAAY,SAAS,MAAM,aAAa;AAAA,IAC1D,QAAQ,MAAM;AAAA,IACd,OAAO,MAAM;AAAA,IACb,OAAO,MAAM;AAAA,IACb,SAAS,MAAM;AAAA,IACf,MAAM,MAAM,MAAM,SAAS,MAAM,OAAO;AAAA;AAAA,IAExC,UAAU,MAAM,YAAY;AAAA,IAC5B,mBAAmB,MAAM;AAAA,IACzB,OAAO,MAAM;AAAA,IACb,QAAQ,MAAM;AAAA,IACd,aAAa,MAAM;AAAA,IACnB,UAAU,MAAM;AAAA,IAChB,SAAS,MAAM;AAAA,IACf,sBAAsB,MAAM,oBAAoB,SAC5C,MAAM,qBACN;AAAA,IACJ,mBAAmB,MAAM;AAAA,IACzB,UAAU,MAAM;AAAA,IAChB,MAAM,MAAM,QAAQ;AAAA,EACtB;AACF;AAGO,SAAS,gBAAgB,UAAuC;AACrE,QAAM,WAAsB,CAAC;AAE7B,MAAI,SAAS,SAAS;AACpB,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,SACE,2IAA6B,YAAY,SAAS,YAAY,CAAC,0CAC3D,SAAS,eAAe,GAAG,iBAAO,SAAS,gBAAgB,GAAG;AAAA,MAEpE,SAAS;AAAA,QACP,aAAa,SAAS;AAAA,QACtB,YAAY,SAAS;AAAA,QACrB,aAAa,SAAS;AAAA,MACxB;AAAA,IACF,CAAC;AAAA,EACH;AAEA,MAAI,SAAS,yBAAyB;AACpC,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,SACE;AAAA,IAEJ,CAAC;AAAA,EACH;AAEA,MAAI,SAAS,YAAY,SAAS,WAAW,GAAG;AAC9C,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,SACE,yFAAmB,KAAK,MAAM,SAAS,WAAW,EAAE,CAAC;AAAA,MAEvD,SAAS,EAAE,gBAAgB,SAAS,SAAS;AAAA,IAC/C,CAAC;AAAA,EACH;AAEA,aAAWC,OAAM,SAAS,OAAO,cAAc,CAAC,GAAG;AACjD,QAAI,CAAC,aAAa,eAAeA,GAAE,CAAC,GAAG;AACrC,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,SAAS,gHAA2BA,GAAE,mLAAuC,eAAe;AAAA,QAC5F,SAAS,EAAE,WAAWA,IAAG;AAAA,MAC3B,CAAC;AAAA,IACH;AAAA,EACF;AACA,aAAWA,OAAM,SAAS,OAAO,WAAW,CAAC,GAAG;AAC9C,QAAI,CAAC,UAAU,eAAeA,GAAE,CAAC,GAAG;AAClC,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,SAAS,wFAAuBA,GAAE,mLAAuC,eAAe;AAAA,QACxF,SAAS,EAAE,QAAQA,IAAG;AAAA,MACxB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,YAAY,OAAmC;AACtD,SAAO,UAAU,SAAY,MAAM,GAAG,KAAK,MAAM,QAAQ,GAAG,CAAC;AAC/D;AAGO,IAAM,aAAN,MAAiB;AAAA,EACtB,YACmB,MACA,UAA6B,CAAC,GAC/C;AAFiB;AACA;AAAA,EAChB;AAAA,EAFgB;AAAA,EACA;AAAA;AAAA,EAInB,MAAM,UAAU,OAAkB,QAAiD;AACjF,UAAM,EAAE,SAAS,IAAI,cAAc,OAAO,KAAK,OAAO;AACtD,aAAS,QAAQ,KAAK,KAAK,IAAI;AAC/B,WAAO,KAAK,KAAK,IAAsB;AAAA,MACrC,MAAM;AAAA,MACN,OAAO,cAAc,OAAO,KAAK,KAAK,IAAI;AAAA,MAC1C,OAAO;AAAA,MACP;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,SAAS,OAAkB,UAA2B,CAAC,GAA6B;AACxF,UAAM,WAAW,KAAK,IAAI,QAAQ,YAAY,mBAAmB,OAAO,iBAAiB;AACzF,UAAM,WAAW,aAAa,EAAE;AAChC,UAAM,OAAkB;AAAA,MACtB,GAAG;AAAA,MACH,OAAO,MAAM,SAAS,SAAS;AAAA,MAC/B,OAAO,MAAM,SAAS,SAAS;AAAA,IACjC;AAEA,UAAM,EAAE,UAAU,cAAc,IAAI,cAAc,MAAM,KAAK,OAAO;AACpE,UAAM,WAAsB,CAAC,GAAG,aAAa;AAC7C,aAAS,QAAQ,KAAK,KAAK,IAAI;AAE/B,UAAM,OAAkB,CAAC;AACzB,QAAI,SAAS,KAAK,UAAU;AAC5B,QAAI,WAAW;AACf,QAAI,YAAY;AAChB,QAAI;AAEJ,eAAS;AACP,YAAM,YAAY,QAAQ,YAAY,SAAY,WAAW,QAAQ,UAAU,KAAK;AACpF,UAAI,aAAa,EAAG;AAEpB,YAAM,OAAO,MAAM,KAAK,KAAK,IAAsB;AAAA,QACjD,MAAM;AAAA,QACN,OAAO;AAAA,UACL,EAAE,GAAG,MAAM,OAAO,KAAK,IAAI,UAAU,SAAS,GAAG,OAAO;AAAA,UACxD,KAAK,KAAK;AAAA,QACZ;AAAA,QACA,OAAO;AAAA,QACP,QAAQ,QAAQ;AAAA,MAClB,CAAC;AACD,kBAAY;AACZ,eAAS;AACT,kBAAY,KAAK;AAEjB,UAAI,aAAa,GAAG;AAClB,mBAAW,WAAW,gBAAgB,IAAI,GAAG;AAC3C,mBAAS,KAAK,OAAO;AACrB,eAAK,KAAK,KAAK,OAAO;AAAA,QACxB;AAAA,MACF;AAEA,WAAK,KAAK,GAAG,KAAK,IAAI;AACtB,gBAAU,KAAK,KAAK;AAGpB,UAAI,KAAK,KAAK,WAAW,KAAK,SAAS,UAAW;AAAA,IACpD;AAEA,QAAI,QAAQ,YAAY,UAAa,YAAY,KAAK,QAAQ;AAC5D,YAAM,UAAmB;AAAA,QACvB,MAAM;AAAA,QACN,SAAS,0DAAa,KAAK,MAAM,gDAAa,SAAS;AAAA,QACvD,SAAS,EAAE,SAAS,KAAK,QAAQ,UAAU;AAAA,MAC7C;AACA,eAAS,KAAK,OAAO;AACrB,WAAK,KAAK,KAAK,OAAO;AAAA,IACxB;AAEA,WAAO,EAAE,MAAM,MAAM,UAAU,MAAM,KAAK,QAAQ,UAAU,QAAQ,EAAE;AAAA,EACxE;AAAA;AAAA,EAGA,OAAO,OAAO,OAAkB,UAA2B,CAAC,GAA4B;AACtF,UAAM,WAAW,KAAK,IAAI,QAAQ,YAAY,mBAAmB,OAAO,iBAAiB;AACzF,UAAM,WAAW,aAAa,EAAE;AAChC,UAAM,OAAkB;AAAA,MACtB,GAAG;AAAA,MACH,OAAO,MAAM,SAAS,SAAS;AAAA,MAC/B,OAAO,MAAM,SAAS,SAAS;AAAA,IACjC;AACA,kBAAc,MAAM,KAAK,OAAO,EAAE,SAAS,QAAQ,KAAK,KAAK,IAAI;AAEjE,QAAI,SAAS,KAAK,UAAU;AAC5B,QAAI,UAAU;AACd,QAAI,QAAQ;AAEZ,eAAS;AACP,YAAM,YAAY,QAAQ,YAAY,SAAY,WAAW,QAAQ,UAAU;AAC/E,UAAI,aAAa,EAAG;AAEpB,YAAM,OAAO,MAAM,KAAK,KAAK,IAAsB;AAAA,QACjD,MAAM;AAAA,QACN,OAAO;AAAA,UACL,EAAE,GAAG,MAAM,OAAO,KAAK,IAAI,UAAU,SAAS,GAAG,OAAO;AAAA,UACxD,KAAK,KAAK;AAAA,QACZ;AAAA,QACA,OAAO;AAAA,QACP,QAAQ,QAAQ;AAAA,MAClB,CAAC;AACD,UAAI,OAAO;AACT,wBAAgB,IAAI,EAAE,QAAQ,KAAK,KAAK,IAAI;AAC5C,gBAAQ;AAAA,MACV;AACA,iBAAW,OAAO,KAAK,MAAM;AAC3B,cAAM;AACN,mBAAW;AAAA,MACb;AACA,gBAAU,KAAK,KAAK;AACpB,UAAI,KAAK,KAAK,WAAW,KAAK,SAAS,KAAK,WAAY;AAAA,IAC1D;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,OAAO,OAAoB,QAA+C;AAC9E,QAAI,MAAM,YAAY,WAAc,MAAM,UAAU,KAAK,MAAM,UAAU,KAAK;AAC5E,YAAM,IAAI,WAAW,mMAAkD,MAAM,OAAO,EAAE;AAAA,IACxF;AACA,UAAM,WAAW,aAAa,EAAE;AAChC,UAAM,OAAoB;AAAA,MACxB,GAAG;AAAA,MACH,OAAO,MAAM,SAAS,SAAS;AAAA,MAC/B,OAAO,MAAM,SAAS,SAAS;AAAA,IACjC;AACA,kBAAc,MAAM,KAAK,OAAO,EAAE,SAAS,QAAQ,KAAK,KAAK,IAAI;AAEjE,WAAO,KAAK,KAAK,IAAoB;AAAA,MACnC,MAAM;AAAA,MACN,OAAO;AAAA,QACL,GAAG,cAAc,MAAM,KAAK,KAAK,IAAI;AAAA,QACrC,OAAO,KAAK,SAAS;AAAA,QACrB,UAAU,KAAK;AAAA,QACf,SAAS,KAAK,SAAS,KAAK,UAAU,KAAK,MAAM,IAAI;AAAA,MACvD;AAAA,MACA,OAAO;AAAA,MACP;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEA,SAAS,UACP,UACA,aACA,UACA,UACY;AACZ,SAAO;AAAA,IACL;AAAA,IACA,SAAS,UAAU,WAAW;AAAA,IAC9B,aAAa,UAAU;AAAA,IACvB,YAAY,UAAU;AAAA,IACtB,aAAa,UAAU;AAAA,IACvB,uBAAuB,UAAU,2BAA2B;AAAA,IAC5D,gBAAgB,UAAU;AAAA,IAC1B,WAAW,UAAU,cAAc;AAAA,IACnC;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AC7SO,IAAM,MAAM;AAAA,EACjB,cAAc;AAAA,EACd,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,SAAS;AAAA,EACT,UAAU;AAAA,EACV,yBAAyB;AAAA,EACzB,yBAAyB;AAAA,EACzB,sBAAsB;AAAA,EACtB,sBAAsB;AAAA,EACtB,eAAe;AAAA,EACf,uBAAuB;AACzB;AAGO,IAAM,SAAS;AAAA,EACpB,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,kBAAkB;AAAA,EAClB,uBAAuB;AAAA,EACvB,UAAU;AAAA,EACV,UAAU;AAAA,EACV,SAAS;AAAA,EACT,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,gBAAgB;AAClB;AAmBO,SAAS,cAAc,OAAmD;AAC/E,QAAM,UAAU,MAAM,OAAO,CAAC,SAAyB,QAAQ,MAAM,KAAK,CAAC,CAAC;AAC5E,MAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,SAAO,QAAQ,IAAI,CAAC,WAAY,QAAQ,SAAS,IAAI,IAAI,MAAM,MAAM,MAAO,EAAE,KAAK,OAAO;AAC5F;AAGO,SAAS,KAAK,OAA2C;AAC9D,SAAO,OAAO,QAAQ,OAAO,MAAM;AACrC;AAGO,SAAS,GAAG,OAAuD;AACxE,SAAO,OAAO,MAAM;AACtB;AAGO,SAAS,IAAI,KAAc,OAAuB;AACvD,QAAM,QAAQ,IAAI,QAAQ,KAAK;AAC/B,SAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IAAI,QAAQ;AACvE;AAOO,SAAS,gBAAgB,QAAwB;AACtD,SAAO,OAAO,KAAK,EAAE,QAAQ,QAAQ,GAAG,EAAE,YAAY,EAAE,QAAQ,MAAM,QAAG;AAC3E;;;ACnCA,IAAM,UAAU;AAAA,EACd,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACT;AAGA,eAAsB,0BACpB,SACA,SACgC;AAChC,QAAM,SAAS,MAAM,QAAQ;AAAA,IAC3B;AAAA,MACE,KAAK,QAAQ;AAAA,MACb,YAAY;AAAA,QACV,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,MACN;AAAA,MACA,SAAS;AAAA,MACT,SAAS;AAAA,QACP,QAAQ,gBAAgB,SACpB,GAAG,IAAI,qBAAqB,MAAM,QAAQ,eACvC,IAAI,CAAC,SAAS,IAAI,IAAI,GAAG,EACzB,KAAK,GAAG,CAAC,MACZ;AAAA,QACJ,QAAQ;AAAA,MACV;AAAA,MACA,aAAa,QAAQ,eAAe;AAAA,MACpC,UAAU,QAAQ;AAAA,MAClB,oBAAoB,QAAQ;AAAA,MAC5B,OAAO,QAAQ;AAAA,MACf,OAAO,QAAQ;AAAA,MACf,MAAM,CAAC,IAAI,OAAO,QAAQ,EAAE;AAAA,IAC9B;AAAA,IACA,EAAE,SAAS,QAAQ,SAAS,QAAQ,QAAQ,OAAO;AAAA,EACrD;AAEA,SAAO,EAAE,MAAM,OAAO,KAAK,IAAI,eAAe,GAAG,MAAM,OAAO,KAAK;AACrE;AAEA,SAAS,gBAAgB,KAA6B;AACpD,QAAM,gBAAgB,KAAK,IAAI,WAAW,CAAC,CAAC;AAC5C,QAAM,aAAa,GAAG,IAAI,WAAW,CAAC,CAAC;AACvC,SAAO;AAAA,IACL,OAAO,KAAK,IAAI,WAAW,CAAC,CAAC;AAAA,IAC7B,SAAS,KAAK,IAAI,WAAW,CAAC,CAAC;AAAA,IAC/B,GAAI,gBAAgB,EAAE,cAAc,IAAI,CAAC;AAAA,IACzC,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;AAAA,IACnC,cAAc,KAAK,IAAI,WAAW,CAAC,CAAC;AAAA,IACpC,QAAQ,IAAI,KAAK,CAAC;AAAA,IAClB,QAAQ,IAAI,KAAK,CAAC;AAAA,IAClB,OAAO,IAAI,KAAK,CAAC;AAAA,IACjB,MAAM,IAAI,KAAK,CAAC;AAAA,IAChB,cAAc,IAAI,KAAK,CAAC;AAAA,IACxB,YAAY,IAAI,KAAK,CAAC;AAAA,EACxB;AACF;;;ACrFA,IAAMC,WAAU,CAAC,OAAO,QAAQ,OAAO,OAAO,OAAO,YAAY,OAAO,qBAAqB;AAG7F,eAAsB,0BACpB,SACA,SACiC;AACjC,QAAM,SAAS,MAAM,QAAQ;AAAA,IAC3B;AAAA,MACE,KAAK,QAAQ;AAAA,MACb,YAAY,CAAC,IAAI,yBAAyB,IAAI,uBAAuB;AAAA,MACrE,SAASA;AAAA,MACT,SAAS;AAAA,QACP,QAAQ,kBAAkB,QAAQ,SAAY,GAAG,IAAI,OAAO;AAAA,QAC5D,QAAQ;AAAA,MACV;AAAA,MACA,aAAa,QAAQ,eAAe;AAAA,MACpC,OAAO,QAAQ;AAAA,MACf,OAAO,QAAQ;AAAA,MACf,MAAM,CAAC,IAAI,OAAO,MAAM,EAAE;AAAA,IAC5B;AAAA,IACA,EAAE,SAAS,QAAQ,SAAS,QAAQ,QAAQ,OAAO;AAAA,EACrD;AAEA,SAAO,EAAE,MAAM,OAAO,KAAK,IAAI,gBAAgB,GAAG,MAAM,OAAO,KAAK;AACtE;AAEA,SAAS,iBAAiB,KAA8B;AACtD,SAAO;AAAA,IACL,SAAS,KAAK,IAAI,WAAW,CAAC,CAAC;AAAA,IAC/B,OAAO,KAAK,IAAI,WAAW,CAAC,CAAC;AAAA,IAC7B,QAAQ,IAAI,KAAK,CAAC;AAAA,IAClB,OAAO,IAAI,KAAK,CAAC;AAAA,IACjB,YAAY,IAAI,KAAK,CAAC;AAAA,IACtB,uBAAuB,IAAI,KAAK,CAAC;AAAA,EACnC;AACF;;;ACjBO,SAAS,eAAe,SAAoD;AACjF,QAAM,UAAU,QAAQ,eAAe,SACnC,GAAG,IAAI,gBAAgB,MAAM,QAAQ,cAAc,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,KAAK,GAAG,CAAC,MACjF;AACJ,SAAO;AAAA,IACL,GAAG,IAAI,aAAa;AAAA,IACpB,QAAQ,kBAAkB,QAAQ,SAAY,GAAG,IAAI,OAAO;AAAA,IAC5D;AAAA,IACA,QAAQ;AAAA,EACV;AACF;AAEA,IAAMC,WAAU;AAAA,EACd,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACT;AAGA,eAAsB,wBACpB,SACA,SACmC;AACnC,QAAM,SAAS,MAAM,QAAQ;AAAA,IAC3B;AAAA,MACE,KAAK,QAAQ;AAAA,MACb,YAAY,CAAC,IAAI,cAAc,IAAI,gBAAgB;AAAA,MACnD,SAASA;AAAA,MACT,SAAS,eAAe,OAAO;AAAA,MAC/B,aAAa,QAAQ,eAAe;AAAA,MACpC,OAAO,QAAQ;AAAA,MACf,OAAO,QAAQ;AAAA,MACf,MAAM,CAAC,IAAI,OAAO,MAAM,EAAE;AAAA,IAC5B;AAAA,IACA,EAAE,SAAS,QAAQ,SAAS,QAAQ,QAAQ,OAAO;AAAA,EACrD;AAEA,SAAO,EAAE,MAAM,OAAO,KAAK,IAAI,YAAY,GAAG,MAAM,OAAO,KAAK;AAClE;AAEA,SAAS,aAAa,KAAgC;AACpD,QAAM,WAAW,GAAG,IAAI,WAAW,CAAC,CAAC;AACrC,SAAO;AAAA,IACL,QAAQ,KAAK,IAAI,WAAW,CAAC,CAAC;AAAA,IAC9B,cAAc,KAAK,IAAI,WAAW,CAAC,CAAC;AAAA,IACpC,GAAI,WAAW,EAAE,gBAAgB,SAAS,IAAI,CAAC;AAAA,IAC/C,QAAQ,IAAI,KAAK,CAAC;AAAA,IAClB,OAAO,IAAI,KAAK,CAAC;AAAA,IACjB,YAAY,IAAI,KAAK,CAAC;AAAA,IACtB,WAAW,IAAI,KAAK,CAAC;AAAA,IACrB,yBAAyB,IAAI,KAAK,CAAC;AAAA,EACrC;AACF;;;AC5EA,IAAMC,WAAU,CAAC,OAAO,QAAQ,OAAO,OAAO,OAAO,YAAY,OAAO,gBAAgB;AAGxF,eAAsB,oBACpB,SACA,SACmC;AACnC,QAAM,SAAS,MAAM,QAAQ;AAAA,IAC3B;AAAA,MACE,KAAK,QAAQ;AAAA,MACb,YAAY,CAAC,IAAI,cAAc,IAAI,QAAQ;AAAA,MAC3C,SAASA;AAAA,MACT,SAAS,eAAe,OAAO;AAAA,MAC/B,aAAa,QAAQ,eAAe;AAAA,MACpC,OAAO,QAAQ;AAAA,MACf,OAAO,QAAQ;AAAA,MACf,MAAM,CAAC,IAAI,OAAO,MAAM,EAAE;AAAA,IAC5B;AAAA,IACA,EAAE,SAAS,QAAQ,SAAS,QAAQ,QAAQ,OAAO;AAAA,EACrD;AAEA,SAAO,EAAE,MAAM,OAAO,KAAK,IAAI,YAAY,GAAG,MAAM,OAAO,KAAK;AAClE;AAEA,SAAS,aAAa,KAAgC;AACpD,SAAO;AAAA,IACL,QAAQ,KAAK,IAAI,WAAW,CAAC,CAAC;AAAA,IAC9B,KAAK,KAAK,IAAI,WAAW,CAAC,CAAC;AAAA,IAC3B,QAAQ,IAAI,KAAK,CAAC;AAAA,IAClB,OAAO,IAAI,KAAK,CAAC;AAAA,IACjB,YAAY,IAAI,KAAK,CAAC;AAAA,IACtB,yBAAyB,IAAI,KAAK,CAAC;AAAA,EACrC;AACF;;;AC1CO,IAAM,oBAAoB;AAkCjC,eAAsB,kBACpB,SACA,SAC2B;AAC3B,QAAM,aAAa,KAAK,IAAI,QAAQ,cAAc,IAAI,iBAAiB;AACvE,QAAM,WAAW,MAAM,QAAQ;AAAA,IAC7B;AAAA,MACE,KAAK,QAAQ;AAAA,MACb,YAAY,CAAC,IAAI,YAAY;AAAA,MAC7B,SAAS,CAAC,OAAO,MAAM;AAAA,MACvB,SAAS,eAAe,OAAO;AAAA,MAC/B,aAAa,QAAQ,eAAe;AAAA,MACpC,OAAO,QAAQ;AAAA,MACf,OAAO,QAAQ;AAAA,MACf,OAAO,QAAQ,SAAS;AAAA,MACxB,GAAI,QAAQ,SAAS,SACjB,EAAE,QAAQ,QAAQ,QAAQ,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,IACpD,EAAE,SAAS,WAAW;AAAA,IAC5B;AAAA,IACA,QAAQ;AAAA,EACV;AAEA,QAAM,YAAY,SAAS,kBAAkB,CAAC;AAC9C,SAAO,SAAS,KAAK,IAAI,CAAC,QAAQ,WAAW,KAAK,SAAS,CAAC;AAC9D;AAEA,SAAS,WAAW,KAAgB,WAA+C;AACjF,QAAM,SAAS,IAAI,QAAQ,CAAC,KAAK,CAAC;AAClC,QAAM,SAA0B,OAAO,IAAI,CAAC,OAAO,WAAW;AAAA,IAC5D,MAAM,UAAU,KAAK,IAAI,CAAC,KAAK;AAAA,IAC/B,IAAI,UAAU,KAAK,IAAI,CAAC,KAAK;AAAA,IAC7B,QAAQ,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IAAI,QAAQ;AAAA,EACxE,EAAE;AAEF,SAAO;AAAA,IACL,QAAQ,KAAK,IAAI,WAAW,CAAC,CAAC;AAAA,IAC9B;AAAA,IACA,aAAa,OAAO,OAAO,CAAC,KAAK,UAAU,MAAM,MAAM,QAAQ,CAAC;AAAA,IAChE,OAAO,aAAa,MAAM;AAAA,EAC5B;AACF;AAGA,SAAS,aAAa,QAAwC;AAC5D,MAAI,OAAO,SAAS,EAAG,QAAO;AAC9B,QAAM,SAAS,KAAK,MAAM,OAAO,SAAS,CAAC;AAC3C,QAAM,MAAM,CAAC,UACX,MAAM,OAAO,CAAC,OAAO,UAAU,QAAQ,MAAM,QAAQ,CAAC;AACxD,QAAM,QAAQ,IAAI,OAAO,MAAM,GAAG,MAAM,CAAC;AACzC,MAAI,UAAU,EAAG,QAAO;AACxB,SAAO,IAAI,OAAO,MAAM,MAAM,CAAC,IAAI;AACrC;;;ACvFO,IAAM,0BAA0B;AAqChC,SAAS,UAAU,MAAkC;AAC1D,SAAO;AAAA,IACL,SAAS,KAAK;AAAA,IACd,qBAAqB,KAAK;AAAA,IAC1B,uBAAuB;AAAA,EACzB;AACF;AAUO,SAAS,wBAAwB,OAAwB;AAC9D,SAAO,QAAQ,KAAK,QAAQ;AAC9B;AAGO,SAAS,aAAa,GAAmB,GAAmC;AACjF,SAAO;AAAA,IACL,SAAS,EAAE,WAAW,EAAE;AAAA,IACxB,qBAAqB,EAAE,uBAAuB,EAAE;AAAA,IAChD,uBAAuB,EAAE,yBAAyB,EAAE;AAAA,EACtD;AACF;AAGO,SAAS,UACd,SACA,uBACY;AACZ,QAAM,SAAS,QACZ,IAAI,CAAC,EAAE,KAAK,MAAM,KAAK,WAAW,EAClC,OAAO,CAAC,UAA2B,OAAO,UAAU,QAAQ;AAE/D,SAAO;AAAA,IACL,iBAAiB,QAAQ,CAAC,GAAG,KAAK,mBAAmB;AAAA,IACrD,SAAS,QAAQ,KAAK,CAAC,EAAE,KAAK,MAAM,KAAK,OAAO;AAAA,IAChD,GAAI,OAAO,SAAS,EAAE,gBAAgB,KAAK,IAAI,GAAG,MAAM,EAAE,IAAI,CAAC;AAAA,IAC/D,uBAAuB,QAAQ,KAAK,CAAC,EAAE,KAAK,MAAM,KAAK,qBAAqB;AAAA,IAC5E;AAAA,IACA,UAAU,QAAQ,OAAO,CAAC,KAAK,EAAE,KAAK,MAAM,MAAM,KAAK,UAAU,CAAC;AAAA,IAClE,UAAU,QAAQ,QAAQ,CAAC,EAAE,KAAK,MAAM,KAAK,QAAQ;AAAA,IACrD,SAAS,QAAQ,IAAI,CAAC,EAAE,OAAO,MAAM,MAAM;AAAA,EAC7C;AACF;;;ACOO,SAAS,cAAc,OAAoC;AAChE,QAAM,QAAQ,oBAAI,IAAqB;AACvC,QAAM,QAAgD,CAAC;AAEvD,MAAI,MAAM,SAAS;AACjB,UAAM,KAAK,EAAE,QAAQ,WAAW,MAAM,MAAM,QAAQ,KAAK,CAAC;AAC1D,eAAW,OAAO,MAAM,QAAQ,MAAM;AACpC,UAAI,CAAC,IAAI,OAAQ;AACjB,YAAM,QAAQ,OAAO,OAAO,IAAI,QAAQ,MAAM,QAAQ,IAAI;AAC1D,gBAAU,OAAO,SAAS;AAC1B,YAAM,QAAS,MAAM,YAAY,aAAa;AAC9C,YAAM,UAAU,IAAI;AACpB,YAAM,SAAS,IAAI;AAEnB,YAAM,cAAc,IAAI,aAAa,IAAI;AACzC,YAAM,aAAa,IAAI,YAAY,IAAI;AACvC,YAAM,2BAA2B,IAAI,0BAA0B,IAAI;AACnE,UAAI,IAAI,gBAAgB,CAAC,MAAM,cAAc,SAAS,IAAI,YAAY,GAAG;AACvE,cAAM,cAAc,KAAK,IAAI,YAAY;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AAEA,MAAI,MAAM,YAAY;AACpB,UAAM,KAAK,EAAE,QAAQ,cAAc,MAAM,MAAM,WAAW,KAAK,CAAC;AAChE,eAAW,OAAO,MAAM,WAAW,MAAM;AACvC,UAAI,CAAC,IAAI,MAAO;AAChB,YAAM,QAAQ,OAAO,OAAO,IAAI,OAAO,MAAM,WAAW,IAAI;AAC5D,gBAAU,OAAO,cAAc;AAC/B,YAAM,QAAS,MAAM,WAAW,YAAY;AAC5C,YAAM,UAAU,IAAI;AACpB,YAAM,UAAU,IAAI;AACpB,YAAM,SAAS,IAAI;AACnB,YAAM,QAAQ,IAAI;AAClB,YAAM,cAAc,IAAI,aAAa,IAAI;AACzC,iBAAW,MAAM,UAAU,IAAI,OAAO;AACtC,iBAAW,MAAM,WAAW,IAAI,YAAY;AAAA,IAC9C;AAAA,EACF;AAEA,MAAI,MAAM,cAAc;AACtB,UAAM,KAAK,EAAE,QAAQ,gBAAgB,MAAM,MAAM,aAAa,KAAK,CAAC;AACpE,eAAW,OAAO,MAAM,aAAa,MAAM;AACzC,UAAI,CAAC,IAAI,MAAO;AAChB,YAAM,QAAQ,OAAO,OAAO,IAAI,OAAO,MAAM,aAAa,IAAI;AAC9D,gBAAU,OAAO,cAAc;AAC/B,YAAM,QAAS,MAAM,WAAW,YAAY;AAE5C,UAAI,MAAM,WAAW,GAAG;AACtB,cAAM,SAAS,IAAI;AACnB,cAAM,QAAQ,IAAI;AAClB,cAAM,aAAa,IAAI,aAAa,IAAI;AAAA,MAC1C;AACA,YAAM,wBAAwB,IAAI;AAClC,iBAAW,MAAM,UAAU,IAAI,OAAO;AAAA,IACxC;AAAA,EACF;AAEA,MAAI,MAAM,UAAU;AAClB,UAAM,KAAK,EAAE,QAAQ,YAAY,MAAM,MAAM,SAAS,KAAK,CAAC;AAC5D,eAAW,OAAO,MAAM,SAAS,MAAM;AACrC,UAAI,CAAC,IAAI,UAAU,CAAC,IAAI,IAAK;AAC7B,YAAM,QAAQ,OAAO,OAAO,IAAI,QAAQ,MAAM,SAAS,IAAI;AAC3D,YAAM,WAAW,MAAM,SAAS,KAAK,CAAC,YAAY,QAAQ,QAAQ,IAAI,GAAG;AACzE,UAAI,SAAU,UAAS,UAAU,IAAI;AAAA,UAChC,OAAM,SAAS,KAAK,EAAE,KAAK,IAAI,KAAK,QAAQ,IAAI,OAAO,CAAC;AAAA,IAC/D;AAAA,EACF;AAEA,QAAM,WAAW,CAAC,GAAG,MAAM,OAAO,CAAC;AACnC,aAAW,WAAW,SAAU,UAAS,OAAO;AAChD,WAAS,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,EAAE,eAAe,EAAE,OAAO,cAAc,EAAE,MAAM,CAAC;AAEzF,QAAM,iBAAiB,SAAS,OAAO,CAAC,MAAM,EAAE,QAAQ,qBAAqB,EAAE;AAC/E,SAAO,EAAE,UAAU,MAAM,UAAU,OAAO,cAAc,EAAE;AAC5D;AAGO,SAAS,wBACd,QACwB;AACxB,QAAM,QAAQ,oBAAI,IAAkC;AAEpD,aAAW,OAAO,OAAO,MAAM;AAC7B,QAAI,CAAC,IAAI,QAAS;AAClB,UAAM,MAAM,gBAAgB,IAAI,OAAO;AACvC,QAAI,QAAQ,MAAM,IAAI,GAAG;AACzB,QAAI,CAAC,OAAO;AACV,cAAQ;AAAA,QACN,SAAS,IAAI;AAAA,QACb,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,MAAM;AAAA,QACN,SAAS,CAAC;AAAA,QACV,WAAW,CAAC;AAAA,MACd;AACA,YAAM,IAAI,KAAK,KAAK;AAAA,IACtB;AACA,UAAM,UAAU,IAAI;AACpB,UAAM,UAAU,IAAI;AACpB,UAAM,SAAS,IAAI;AACnB,UAAM,QAAQ,IAAI;AAClB,eAAW,MAAM,SAAS,IAAI,KAAK;AACnC,eAAW,MAAM,WAAW,IAAI,YAAY;AAAA,EAC9C;AAEA,SAAO,CAAC,GAAG,MAAM,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AAC/D;AAEA,SAAS,OAAO,OAA6B,eAAuB,MAA2B;AAC7F,QAAM,SAAS,gBAAgB,aAAa;AAC5C,MAAI,QAAQ,MAAM,IAAI,MAAM;AAC5B,MAAI,CAAC,OAAO;AACV,YAAQ;AAAA,MACN;AAAA,MACA;AAAA,MACA,SAAS,CAAC;AAAA,MACV,UAAU,CAAC;AAAA,MACX,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,SAAS,UAAU,IAAI;AAAA,IACzB;AACA,UAAM,IAAI,QAAQ,KAAK;AACvB,WAAO;AAAA,EACT;AACA,QAAM,UAAU,aAAa,MAAM,SAAS,UAAU,IAAI,CAAC;AAC3D,SAAO;AACT;AAEA,SAAS,UAAU,OAAgB,QAA6B;AAC9D,MAAI,CAAC,MAAM,QAAQ,SAAS,MAAM,EAAG,OAAM,QAAQ,KAAK,MAAM;AAChE;AAEA,SAAS,WAAW,MAAgB,OAAqB;AACvD,MAAI,SAAS,CAAC,KAAK,SAAS,KAAK,EAAG,MAAK,KAAK,KAAK;AACrD;AAEA,SAAS,eAA6B;AACpC,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,yBAAyB;AAAA,IACzB,eAAe,CAAC;AAAA,EAClB;AACF;AAEA,SAAS,cAA2B;AAClC,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,MAAM;AAAA,IACN,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,UAAU,CAAC;AAAA,IACX,WAAW,CAAC;AAAA,EACd;AACF;AAGA,SAAS,SAAS,SAAwB;AACxC,MAAI,QAAQ,WAAW,QAAQ,QAAQ,SAAS,GAAG;AACjD,UAAM,EAAE,OAAO,IAAI,QAAQ;AAC3B,YAAQ,QAAQ,aAAa,MAAM,QAAQ,QAAQ,aAAa,MAAM;AACtE,YAAQ,QAAQ,YAAY,MAAM,QAAQ,QAAQ,YAAY,MAAM;AACpE,YAAQ,QAAQ,0BAA0B;AAAA,MACxC,QAAQ,QAAQ,0BAA0B;AAAA,IAC5C;AAAA,EACF;AACA,MAAI,QAAQ,QAAQ;AAClB,QAAI,QAAQ,OAAO,SAAS,GAAG;AAC7B,cAAQ,OAAO,aAAa,MAAM,QAAQ,OAAO,aAAa,QAAQ,OAAO,MAAM;AACnF,cAAQ,OAAO,eAAe,MAAM,QAAQ,OAAO,OAAO,QAAQ,OAAO,MAAM;AAAA,IACjF;AACA,YAAQ,OAAO,OAAO,MAAM,QAAQ,OAAO,IAAI;AAAA,EACjD;AACA,UAAQ,SAAS,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM;AACnD,UAAQ,eAAe,QAAQ,SAAS,UAAU,MAAM,QAAQ,QAAQ,UAAU;AAGlF,UAAQ,cAAc,QAAQ,SAAS,SAAS,MAAM,QAAQ,QAAQ,SAAS;AAC/E,UAAQ,QAAQ,wBAAwB,wBAAwB,QAAQ,UAAU;AACpF;AAEA,SAAS,MAAM,OAAuB;AACpC,SAAO,KAAK,MAAM,QAAQ,GAAG,IAAI;AACnC;;;ACpPO,IAAM,gBAAN,MAAoB;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,SAAyB;AACnC,SAAK,OAAO,IAAI,kBAAkB,OAAO;AACzC,SAAK,UAAU,IAAI,WAAW,KAAK,MAAM;AAAA,MACvC,oBAAoB,QAAQ,sBAAsB;AAAA,IACpD,CAAC;AACD,SAAK,aAAa,IAAI,cAAc,KAAK,IAAI;AAAA,EAC/C;AAAA;AAAA,EAGA,WAAwE;AACtE,WAAO,EAAE,SAAS,iBAAiB,cAAc,sBAAsB,UAAU,iBAAiB;AAAA,EACpG;AAAA;AAAA,EAGA,wBAAwB,SAAmE;AACzF,WAAO,wBAAwB,KAAK,SAAS,OAAO;AAAA,EACtD;AAAA;AAAA,EAGA,oBAAoB,SAAmE;AACrF,WAAO,oBAAoB,KAAK,SAAS,OAAO;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,0BACJ,SACgC;AAChC,UAAM,SACJ,QAAQ,sBACP,MAAM,KAAK,WAAW,sBAAsB,QAAQ,WAAW,QAAQ,MAAM;AAChF,WAAO,0BAA0B,KAAK,SAAS,EAAE,GAAG,SAAS,oBAAoB,OAAO,CAAC;AAAA,EAC3F;AAAA;AAAA,EAGA,0BACE,SACiC;AACjC,WAAO,0BAA0B,KAAK,SAAS,OAAO;AAAA,EACxD;AAAA;AAAA,EAGA,kBAAkB,SAA2D;AAC3E,WAAO,kBAAkB,KAAK,SAAS,OAAO;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,qBAAqB,SAA2D;AACpF,UAAM,UAAU,MAAM,KAAK,wBAAwB,OAAO;AAE1D,UAAM,WACJ,QAAQ,iBAAiB,QAAQ,SAAY,MAAM,KAAK,oBAAoB,OAAO;AAErF,QAAI;AACJ,QAAI;AAEJ,QAAI,QAAQ,eAAe,OAAO;AAChC,YAAM,SACJ,QAAQ,sBACP,MAAM,KAAK,WACT,sBAAsB,QAAQ,WAAW,QAAQ,MAAM,EACvD,MAAM,MAAM,CAAC,CAAa;AAE/B,UAAI,OAAO,SAAS,GAAG;AACrB,qBAAa,MAAM,0BAA0B,KAAK,SAAS;AAAA,UACzD,GAAG;AAAA,UACH,oBAAoB;AAAA,QACtB,CAAC;AAAA,MACH,OAAO;AACL,aAAK,KAAK,KAAK;AAAA,UACb,MAAM;AAAA,UACN,SACE;AAAA,QAEJ,CAAC;AACD,uBAAe,MAAM,KAAK,0BAA0B,OAAO;AAAA,MAC7D;AAAA,IACF;AAEA,WAAO,cAAc;AAAA,MACnB;AAAA,MACA,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,MAC/B,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;AAAA,MACnC,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,IACzC,CAAC;AAAA,EACH;AACF;;;ACvIO,IAAM,kBAAoD;AAAA,EAC/D,kCAAkC;AAAA,EAClC,sCAAsC;AAAA,EACtC,mCAAmC;AAAA,EACnC,gBAAgB;AAAA,EAChB,iBAAiB;AAAA,EACjB,wCAAwC;AAAA,EACxC,wCAAwC;AAAA,EACxC,yCAAyC;AAAA,EACzC,yCAAyC;AAAA,EACzC,kCAAkC;AAAA,EAClC,0CAA0C;AAC5C;AAGO,IAAM,eAAiD;AAAA,EAC5D,eAAe;AAAA,EACf,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,gCAAgC;AAAA,EAChC,8BAA8B;AAAA,EAC9B,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,oBAAoB;AAAA,EACpB,mCAAmC;AAAA,EACnC,2CAA2C;AAC7C;AAGO,IAAM,eAAiD;AAAA,EAC5D,wBAAwB;AAAA,EACxB,wBAAwB;AAAA,EACxB,uBAAuB;AACzB;","names":["id","id","text","id","id","METRICS","METRICS","METRICS"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ezmar/yandex-metric-parser-lib",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Типизированная обёртка над API отчётов Яндекс Метрики: поисковые фразы органики, ключевые слова и расходы Яндекс Директа",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"yandex",
|
|
7
|
+
"metrika",
|
|
8
|
+
"metrica",
|
|
9
|
+
"yandex-direct",
|
|
10
|
+
"seo",
|
|
11
|
+
"keywords",
|
|
12
|
+
"analytics"
|
|
13
|
+
],
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/OGRomva/yandex-metric-parser-lib.git"
|
|
18
|
+
},
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/OGRomva/yandex-metric-parser-lib/issues"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://github.com/OGRomva/yandex-metric-parser-lib#readme",
|
|
23
|
+
"type": "module",
|
|
24
|
+
"main": "./dist/index.cjs",
|
|
25
|
+
"module": "./dist/index.js",
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"import": "./dist/index.js",
|
|
31
|
+
"require": "./dist/index.cjs"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"dist",
|
|
36
|
+
"README.md"
|
|
37
|
+
],
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=18"
|
|
40
|
+
},
|
|
41
|
+
"publishConfig": {
|
|
42
|
+
"access": "public"
|
|
43
|
+
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "tsup",
|
|
46
|
+
"typecheck": "tsc --noEmit",
|
|
47
|
+
"test": "vitest run",
|
|
48
|
+
"test:watch": "vitest",
|
|
49
|
+
"fetch-docs": "tsx scripts/fetch-docs.ts",
|
|
50
|
+
"parse-contract": "tsx scripts/parse-contract.ts",
|
|
51
|
+
"check-contract": "tsx scripts/check-contract.ts",
|
|
52
|
+
"get-token": "tsx scripts/get-token.ts",
|
|
53
|
+
"prepublishOnly": "npm run typecheck && npm test && npm run build"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@types/node": "^22.10.2",
|
|
57
|
+
"tsup": "^8.3.5",
|
|
58
|
+
"tsx": "^4.19.2",
|
|
59
|
+
"typescript": "^5.7.2",
|
|
60
|
+
"vitest": "^2.1.8"
|
|
61
|
+
}
|
|
62
|
+
}
|