diff --git a/types/radio-browser/.npmignore b/types/radio-browser/.npmignore new file mode 100644 index 00000000000000..93e307400a5456 --- /dev/null +++ b/types/radio-browser/.npmignore @@ -0,0 +1,5 @@ +* +!**/*.d.ts +!**/*.d.cts +!**/*.d.mts +!**/*.d.*.ts diff --git a/types/radio-browser/index.d.ts b/types/radio-browser/index.d.ts new file mode 100644 index 00000000000000..97af2fd5752cf2 --- /dev/null +++ b/types/radio-browser/index.d.ts @@ -0,0 +1,274 @@ +interface ServerStats { + supported_version: number; + software_version: string; + status: string; + stations: number; + stations_broken: number; + tags: number; + clicks_last_hour: number; + clicks_last_day: number; + languages: number; + countries: number; +} + +interface Station { + changeuuid: string; + stationuuid: string; + name: string; + url: string; + url_resolved: string; + homepage: string; + favicon: string; + tags: string; + country: string; + countrycode: string; + state: string; + iso_3166_2: string; + language: string; + languagecodes: string; + votes: number; + lastchangetime: string; + lastchangetime_iso8601: string; + codec: string; + bitrate: number; + hls: number; + lastcheckok: number; + lastchecktime: string; + lastchecktime_iso8601: string; + lastcheckoktime: string; + lastcheckoktime_iso8601: string; + lastlocalchecktime: string; + lastlocalchecktime_iso8601: string; + clicktimestamp: string; + clicktimestamp_iso8601: string | null; + clickcount: number; + clicktrend: number; + ssl_error: number; + geo_lat: number | null; + geo_long: number | null; + geo_distance?: number | null; + has_extended_info?: boolean; +} + +interface StationCheck { + checkuuid: string; + stationuuid: string; + source: string; + codec: string; + bitrate: number; + hls: number; + ok: number; + timestamp: string; + timestamp_iso8601: string; + urlcache: string; + metainfo_overrides_database: number; + public: number | null; + name: string | null; + description: string | null; + tags: string | null; + countrycode: string | null; + countrysubdivisioncode: string | null; + homepage: string | null; + favicon: string | null; + loadbalancer: string | null; + server_software: string | null; + sampling: number | null; + timing_ms: number; + languagecodes: string | null; + ssl_error: number; + geo_lat: number | null; + geo_long: number | null; +} + +interface StationCheckStep { + stepuuid: string; + parent_stepuuid: string | null; + checkuuid: string; + stationuuid: string; + url: string; + urltype: string | null; + error: string | null; + creation_iso8601: string; +} + +interface Click { + stationuuid: string; + clickuuid: string; + clicktimestamp_iso8601: string; + clicktimestamp: string; +} + +interface ClickStationResult { + ok: boolean; + message: string; + stationuuid: string; + name: string; + url: string; +} + +interface AddStationResult { + ok: boolean; + message: string; + uuid: string; +} + +interface VoteResult { + ok: boolean; + message: string; +} + +interface CategoryItem { + name: string; + stationcount: number; + iso_3166_1?: string; + iso_639?: string | null; + country?: string; +} + +interface ServerConfig { + check_enabled: boolean; + prometheus_exporter_enabled: boolean; + pull_servers: unknown[]; + tcp_timeout_seconds: number; + broken_stations_never_working_timeout_seconds: number; + broken_stations_timeout_seconds: number; + checks_timeout_seconds: number; + click_valid_timeout_seconds: number; + clicks_timeout_seconds: number; + mirror_pull_interval_seconds: number; + update_caches_interval_seconds: number; + server_name: string; + server_location: string; + server_country_code: string; + check_retries: number; + check_batchsize: number; + check_pause_seconds: number; + api_threads: number; + cache_type: string; + cache_ttl: number; + language_replace_filepath: string; + language_to_code_filepath: string; +} + +interface AddStationParams { + url: string; + name?: string; + homepage?: string; + favicon?: string; + tags?: string; + country?: string; + countrycode?: string; + state?: string; + language?: string; + codec?: string; + bitrate?: number; + hls?: number; + geo_lat?: number; + geo_long?: number; +} + +type CategoryType = "countries" | "countrycodes" | "codecs" | "states" | "languages" | "tags"; + +type FilterByType = + | "uuid" + | "name" + | "nameexact" + | "codec" + | "codecexact" + | "country" + | "countryexact" + | "countrycodeexact" + | "state" + | "stateexact" + | "language" + | "languageexact" + | "tag" + | "tagexact" + | "url" + | "topclick" + | "topvote" + | "lastclick" + | "lastchange" + | "improvable" + | "broken"; + +interface StationFilter { + by?: FilterByType; + searchterm?: string; + name?: string; + nameExact?: boolean; + country?: string; + countryExact?: string; + countrycodeExact?: string; + state?: string; + stateExact?: string; + language?: string; + languageExact?: string; + tag?: string; + tagExact?: string; + codec?: string; + bitrateMin?: number; + bitrateMax?: number; + hasGeoInfo?: boolean; + hasExtendedInfo?: boolean; + isHLS?: boolean; + order?: string; + reverse?: boolean; + offset?: number; + limit?: number; + hidebroken?: boolean; + url?: string; + lastchangeuuid?: string; + seconds?: number; +} + +interface CategoryFilter { + country?: string; + searchterm?: string; + order?: string; + reverse?: boolean; + hidebroken?: boolean; + limit?: number; + offset?: number; +} + +declare const RadioBrowser: { + service_url: string | null; + + readonly filter_by_types: string[]; + readonly category_types: readonly CategoryType[]; + + getRandomHost(): Promise; + getCategory(category: CategoryType, filter?: CategoryFilter): Promise; + /** @deprecated Use getCategory('countries', filter) */ + getCountries(filter?: CategoryFilter): Promise; + /** @deprecated Use getCategory('codecs', filter) */ + getCodecs(filter?: CategoryFilter): Promise; + /** @deprecated Use getCategory('states', filter) */ + getStates(filter?: CategoryFilter): Promise; + /** @deprecated Use getCategory('languages', filter) */ + getLanguages(filter?: CategoryFilter): Promise; + /** @deprecated Use getCategory('tags', filter) */ + getTags(filter?: CategoryFilter): Promise; + + getStations(filter?: StationFilter): Promise; + getChecks(stationuuid?: string, seconds?: number): Promise; + getChecksteps(uuids: string[]): Promise; + getClicks(stationuuid?: string, seconds?: number): Promise; + + clickStation(stationuuid: string): Promise; + searchStations(params: StationFilter): Promise; + voteStation(stationuuid: string): Promise; + deleteStation(stationuuid: string): Promise<{ ok: boolean; message: string }>; + /** @deprecated Not supported by radio-browser.info */ + undeleteStation(stationuuid: string): Promise; + addStation(params: AddStationParams): Promise; + /** @deprecated Not supported by radio-browser.info */ + editStation(stationuuid: string, params: Partial): Promise; + + getServerStats(): Promise; + getServerMirrors(): Promise>; + getServerConfig(): Promise; +}; + +export = RadioBrowser; diff --git a/types/radio-browser/package.json b/types/radio-browser/package.json new file mode 100644 index 00000000000000..5dfabc7c929500 --- /dev/null +++ b/types/radio-browser/package.json @@ -0,0 +1,17 @@ +{ + "private": true, + "name": "@types/radio-browser", + "version": "2.2.9999", + "projects": [ + "https://github.com/nepodev/radio-browser" + ], + "devDependencies": { + "@types/radio-browser": "workspace:." + }, + "owners": [ + { + "name": "Raphael Oliveira", + "githubUsername": "CodeBeater" + } + ] +} diff --git a/types/radio-browser/radio-browser-tests.ts b/types/radio-browser/radio-browser-tests.ts new file mode 100644 index 00000000000000..66d676efecce8a --- /dev/null +++ b/types/radio-browser/radio-browser-tests.ts @@ -0,0 +1,161 @@ +import RadioBrowser = require("radio-browser"); + +// Properties +RadioBrowser.service_url; // $ExpectType string | null +RadioBrowser.filter_by_types; // $ExpectType string[] +RadioBrowser.category_types; // $ExpectType readonly CategoryType[] + +// getRandomHost +RadioBrowser.getRandomHost(); // $ExpectType Promise + +// getCategory +RadioBrowser.getCategory("countries"); // $ExpectType Promise +RadioBrowser.getCategory("countries", { searchterm: "de" }); // $ExpectType Promise +RadioBrowser.getCategory("tags", { limit: 5, order: "stationcount", reverse: true }); // $ExpectType Promise + +// @ts-expect-error - invalid category type +RadioBrowser.getCategory(123); +// @ts-expect-error - invalid category string +RadioBrowser.getCategory("invalid"); + +// Deprecated methods +RadioBrowser.getCountries(); // $ExpectType Promise +RadioBrowser.getCodecs({ order: "stationcount" }); // $ExpectType Promise +RadioBrowser.getStates({ country: "Germany" }); // $ExpectType Promise +RadioBrowser.getLanguages({ reverse: true }); // $ExpectType Promise +RadioBrowser.getTags({ hidebroken: true }); // $ExpectType Promise + +// getStations +RadioBrowser.getStations(); // $ExpectType Promise +RadioBrowser.getStations({ limit: 5, by: "topvote" }); // $ExpectType Promise +// $ExpectType Promise +RadioBrowser.getStations({ + by: "tag", + searchterm: "jazz", + order: "name", + reverse: false, + offset: 0, + limit: 10, + hidebroken: true, +}); + +// @ts-expect-error - invalid by value +RadioBrowser.getStations({ by: "invalid" }); + +// getChecks +RadioBrowser.getChecks(); // $ExpectType Promise +RadioBrowser.getChecks("some-uuid", 3600); // $ExpectType Promise + +// getChecksteps +RadioBrowser.getChecksteps(["uuid1", "uuid2"]); // $ExpectType Promise + +// getClicks +RadioBrowser.getClicks(); // $ExpectType Promise +RadioBrowser.getClicks("some-uuid", 86400); // $ExpectType Promise + +// clickStation +RadioBrowser.clickStation("station-uuid"); // $ExpectType Promise + +// searchStations +RadioBrowser.searchStations({ name: "jazz", limit: 10 }); // $ExpectType Promise +RadioBrowser.searchStations({ tag: "rock", hasGeoInfo: true, isHLS: false }); // $ExpectType Promise + +// voteStation +RadioBrowser.voteStation("station-uuid"); // $ExpectType Promise + +// deleteStation +RadioBrowser.deleteStation("station-uuid"); // $ExpectType Promise<{ ok: boolean; message: string }> + +// undeleteStation (deprecated) +RadioBrowser.undeleteStation("station-uuid"); // $ExpectType Promise + +// addStation +RadioBrowser.addStation({ url: "http://example.com/stream", name: "Test" }); // $ExpectType Promise +RadioBrowser.addStation({ url: "http://example.com/stream", tags: "jazz", country: "Germany", bitrate: 128 }); // $ExpectType Promise + +// @ts-expect-error - missing required url param +RadioBrowser.addStation({ name: "Test" }); + +// editStation (deprecated) +RadioBrowser.editStation("station-uuid", { name: "New Name" }); // $ExpectType Promise + +// getServerStats +RadioBrowser.getServerStats(); // $ExpectType Promise + +// getServerMirrors +RadioBrowser.getServerMirrors(); // $ExpectType Promise<{ ip: string; name: string }[]> + +// getServerConfig +RadioBrowser.getServerConfig(); // $ExpectType Promise + +// service_url setter +RadioBrowser.service_url = "https://de1.api.radio-browser.info/"; +RadioBrowser.service_url = null; + +// Test station properties +RadioBrowser.getStations({ limit: 1 }).then((stations) => { + if (stations.length > 0) { + stations[0].name; // $ExpectType string + stations[0].stationuuid; // $ExpectType string + stations[0].votes; // $ExpectType number + stations[0].clickcount; // $ExpectType number + stations[0].codec; // $ExpectType string + stations[0].bitrate; // $ExpectType number + stations[0].tags; // $ExpectType string + stations[0].countrycode; // $ExpectType string + stations[0].geo_lat; // $ExpectType number | null + stations[0].has_extended_info; // $ExpectType boolean | undefined + stations[0].clicktimestamp_iso8601; // $ExpectType string | null + stations[0].geo_distance; // $ExpectType number | null | undefined + } +}); + +// Test server stats +RadioBrowser.getServerStats().then((stats) => { + stats.stations; // $ExpectType number + stats.tags; // $ExpectType number + stats.languages; // $ExpectType number + stats.countries; // $ExpectType number + stats.status; // $ExpectType string +}); + +// Test category item properties +RadioBrowser.getCategory("countries", { limit: 1 }).then((items) => { + if (items.length > 0) { + items[0].name; // $ExpectType string + items[0].stationcount; // $ExpectType number + items[0].iso_3166_1; // $ExpectType string | undefined + items[0].iso_639; // $ExpectType string | null | undefined + items[0].country; // $ExpectType string | undefined + } +}); + +// Test server config properties +RadioBrowser.getServerConfig().then((config) => { + config.check_enabled; // $ExpectType boolean + config.api_threads; // $ExpectType number + config.cache_type; // $ExpectType string + config.server_name; // $ExpectType string +}); + +// Test click station result properties +RadioBrowser.clickStation("station-uuid").then((result) => { + result.ok; // $ExpectType boolean + result.message; // $ExpectType string + result.stationuuid; // $ExpectType string + result.name; // $ExpectType string + result.url; // $ExpectType string +}); + +// Test add station result properties +RadioBrowser.addStation({ url: "http://example.com" }).then((result) => { + result.ok; // $ExpectType boolean + result.message; // $ExpectType string + result.uuid; // $ExpectType string +}); + +// Test vote result properties +RadioBrowser.voteStation("station-uuid").then((result) => { + result.ok; // $ExpectType boolean + result.message; // $ExpectType string +}); diff --git a/types/radio-browser/tsconfig.json b/types/radio-browser/tsconfig.json new file mode 100644 index 00000000000000..9806a095a2e87a --- /dev/null +++ b/types/radio-browser/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "module": "node16", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "radio-browser-tests.ts", + "index.d.ts" + ] +} diff --git a/types/semver/functions/truncate.d.ts b/types/semver/functions/truncate.d.ts new file mode 100644 index 00000000000000..19532c294eb1da --- /dev/null +++ b/types/semver/functions/truncate.d.ts @@ -0,0 +1,10 @@ +import SemVer = require("../classes/semver"); +import semver = require("../index"); + +declare function truncate( + version: string | SemVer, + truncation: semver.ReleaseType, + optionsOrLoose?: boolean | semver.Options, +): string | null; + +export = truncate; diff --git a/types/semver/index.d.ts b/types/semver/index.d.ts index eb0721baa54e8e..66757648dfebb3 100644 --- a/types/semver/index.d.ts +++ b/types/semver/index.d.ts @@ -16,6 +16,7 @@ import semverCompareLoose = require("./functions/compare-loose"); import semverCompareBuild = require("./functions/compare-build"); import semverSort = require("./functions/sort"); import semverRsort = require("./functions/rsort"); +import semverTruncate = require("./functions/truncate"); export { semverClean as clean, @@ -32,6 +33,7 @@ export { semverRcompare as rcompare, semverRsort as rsort, semverSort as sort, + semverTruncate as truncate, semverValid as valid, }; diff --git a/types/semver/package.json b/types/semver/package.json index 83c0bd1a8cb793..8d0888068ea3e4 100644 --- a/types/semver/package.json +++ b/types/semver/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@types/semver", - "version": "7.7.9999", + "version": "7.8.9999", "projects": [ "https://github.com/npm/node-semver" ], diff --git a/types/semver/semver-tests.ts b/types/semver/semver-tests.ts index 8c2220bf4deb9b..c48bc491362483 100644 --- a/types/semver/semver-tests.ts +++ b/types/semver/semver-tests.ts @@ -51,6 +51,7 @@ import semverCompareLoose = require("semver/functions/compare-loose"); import semverCompareBuild = require("semver/functions/compare-build"); import semverSort = require("semver/functions/sort"); import semverRsort = require("semver/functions/rsort"); +import semverTruncate = require("semver/functions/truncate"); // low-level comparators between versions import semverGt = require("semver/functions/gt"); @@ -87,6 +88,7 @@ semverMinVersion(">=1.0.0", { loose: false }); // $ExpectType SemVer | null semverMinVersion(">=1.0.0", { includePrerelease: false }); // $ExpectType SemVer | null semverValid(semverCoerce("v2")); // $ExpectType string | null semverValid(semverCoerce("42.6.7.9.3-alpha")); // $ExpectType string | null +semverTruncate("1.2.3", "patch"); // $ExpectType string | null // v6 tests diff --git a/types/wicg-ua-client-hints/.npmignore b/types/wicg-ua-client-hints/.npmignore new file mode 100644 index 00000000000000..93e307400a5456 --- /dev/null +++ b/types/wicg-ua-client-hints/.npmignore @@ -0,0 +1,5 @@ +* +!**/*.d.ts +!**/*.d.cts +!**/*.d.mts +!**/*.d.*.ts diff --git a/types/wicg-ua-client-hints/index.d.ts b/types/wicg-ua-client-hints/index.d.ts new file mode 100644 index 00000000000000..aa9afcb16db678 --- /dev/null +++ b/types/wicg-ua-client-hints/index.d.ts @@ -0,0 +1,55 @@ +export {}; + +declare global { + // https://wicg.github.io/ua-client-hints/#dictdef-navigatoruabrandversion + interface NavigatorUABrandVersion { + brand: string; + version: string; + } + // https://wicg.github.io/ua-client-hints/#dictdef-uadatavalues + interface UADataValues { + architecture: string; + bitness: string; + brands: NavigatorUABrandVersion[]; + formFactors: string[]; + fullVersionList: NavigatorUABrandVersion[]; + model: string; + mobile: boolean; + platform: string; + platformVersion: string; + /** + * @deprecated in favor of fullVersionList + */ + uaFullVersion: string; + wow64: boolean; + } + + // https://wicg.github.io/ua-client-hints/#dictdef-ualowentropyjson + interface UALowEntropyJSON { + brands: NavigatorUABrandVersion[]; + mobile: boolean; + platform: string; + } + + // https://wicg.github.io/ua-client-hints/#navigatoruadata + interface NavigatorUAData { + readonly brands: NavigatorUABrandVersion[]; + readonly mobile: boolean; + readonly platform: string; + getHighEntropyValues(hints: string[]): Promise; + toJSON(): UALowEntropyJSON; + } + + // https://wicg.github.io/ua-client-hints/#navigatorua + interface NavigatorUA { + /** + * Available only in secure contexts. + */ + readonly userAgentData: NavigatorUAData; + } + + // eslint-disable-next-line @typescript-eslint/no-empty-interface + interface Navigator extends NavigatorUA {} + // eslint-disable-next-line @typescript-eslint/no-empty-interface + interface WorkerNavigator extends NavigatorUA {} +} diff --git a/types/wicg-ua-client-hints/package.json b/types/wicg-ua-client-hints/package.json new file mode 100644 index 00000000000000..cc04c9bcbe9ec3 --- /dev/null +++ b/types/wicg-ua-client-hints/package.json @@ -0,0 +1,19 @@ +{ + "private": true, + "name": "@types/wicg-ua-client-hints", + "version": "2026.2.9999", + "nonNpm": true, + "nonNpmDescription": "User Agent Client Hints", + "projects": [ + "https://github.com/WICG/ua-client-hints/" + ], + "devDependencies": { + "@types/wicg-ua-client-hints": "workspace:." + }, + "owners": [ + { + "name": "Jeremy Nguyen", + "githubUsername": "jeremy-code" + } + ] +} diff --git a/types/wicg-ua-client-hints/tsconfig.json b/types/wicg-ua-client-hints/tsconfig.json new file mode 100644 index 00000000000000..046575a5d54689 --- /dev/null +++ b/types/wicg-ua-client-hints/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "module": "node16", + "lib": ["es6", "dom"], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": ["index.d.ts", "wicg-ua-client-hints-tests.ts"] +} diff --git a/types/wicg-ua-client-hints/wicg-ua-client-hints-tests.ts b/types/wicg-ua-client-hints/wicg-ua-client-hints-tests.ts new file mode 100644 index 00000000000000..31ec701aa37081 --- /dev/null +++ b/types/wicg-ua-client-hints/wicg-ua-client-hints-tests.ts @@ -0,0 +1,23 @@ +(async () => { + const userAgentData = window.navigator.userAgentData; + + // $ExpectType string + const platform = userAgentData.platform; + // @ts-expect-error + userAgentData.mobile = true; + + const isChromium = navigator.userAgentData.brands.some( + (data) => data.brand == "Chromium", + ); + const isMobile = userAgentData.mobile; + const isMacOS = userAgentData.platform === "macOS"; + + const highEntropyValues = await userAgentData.getHighEntropyValues([ + "architecture", + ]); + // $ExpectType string + const architecture = highEntropyValues.architecture; + + // $ExpectType boolean + const lowEntropyMobile = userAgentData.toJSON().mobile; +})();