@parseapi/sdk 1.10.0 → 1.10.1

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/dist/index.d.ts CHANGED
@@ -1059,6 +1059,128 @@ interface Emoji {
1059
1059
  interface EmojiSearch {
1060
1060
  q: string;
1061
1061
  emojis: Emoji[];
1062
+ total?: number;
1063
+ next_offset?: number | null;
1064
+ }
1065
+ interface EmojiBrowse {
1066
+ emojis: Emoji[];
1067
+ total: number;
1068
+ next_offset: number | null;
1069
+ }
1070
+ interface EmojiVariant {
1071
+ emoji: string;
1072
+ tones: string[];
1073
+ }
1074
+ interface EmojiArtwork {
1075
+ svg?: string;
1076
+ png?: Record<string, string>;
1077
+ /** Only present when this asset has different rights from its provider. */
1078
+ license?: string;
1079
+ license_url?: string;
1080
+ attribution?: string;
1081
+ }
1082
+ interface EmojiSource {
1083
+ id: string;
1084
+ version: string | null;
1085
+ source_url: string;
1086
+ license: string;
1087
+ license_url: string;
1088
+ }
1089
+ interface EmojiNotice {
1090
+ id: string;
1091
+ license: string;
1092
+ notice: string;
1093
+ }
1094
+ interface EmojiArtworkSource {
1095
+ style: string;
1096
+ version: string | null;
1097
+ unicode_version: string | null;
1098
+ source_url: string;
1099
+ license: string;
1100
+ license_url: string;
1101
+ attribution: string;
1102
+ notices: string[];
1103
+ loaded_coverage?: {
1104
+ svg: number;
1105
+ png: number;
1106
+ };
1107
+ flag_license?: {
1108
+ license: string;
1109
+ license_url: string;
1110
+ description: string;
1111
+ };
1112
+ }
1113
+ interface EmojiMetadata {
1114
+ edition: string;
1115
+ max_version: string | null;
1116
+ source_version: string;
1117
+ total: number;
1118
+ sources: EmojiSource[];
1119
+ artwork_sources: EmojiArtworkSource[];
1120
+ notices: EmojiNotice[];
1121
+ completeness: {
1122
+ missing_count: number;
1123
+ unexpected_count: number;
1124
+ };
1125
+ shortcode_sources?: Record<string, EmojiShortcodeSourceMetadata>;
1126
+ [field: string]: unknown;
1127
+ }
1128
+ interface EmojiCatalogScope {
1129
+ filters: Record<string, string>;
1130
+ total: number;
1131
+ complete_inventory: boolean;
1132
+ }
1133
+ interface EmojiNativeSearchFacts {
1134
+ name: string | null;
1135
+ keywords: string[];
1136
+ order?: number | null;
1137
+ }
1138
+ interface EmojiCatalogSearchFacts {
1139
+ native: Record<string, EmojiNativeSearchFacts>;
1140
+ localized_keywords?: string[];
1141
+ }
1142
+ interface EmojiCatalogData {
1143
+ profile?: 'full' | 'compact';
1144
+ scope?: Omit<EmojiCatalogScope, 'total'>;
1145
+ search?: EmojiCatalogSearchFacts;
1146
+ localization?: EmojiCatalogLocalization;
1147
+ metadata: EmojiMetadata;
1148
+ total: number;
1149
+ emojis: Emoji[];
1150
+ forms: Record<string, string>;
1151
+ shortcodes: Record<'cldr' | 'github' | 'slack' | 'discord', Record<string, string[]>>;
1152
+ legacy: Record<string, string>;
1153
+ }
1154
+ interface EmojiCatalogLocalization {
1155
+ requested_locale: string | null;
1156
+ resolved_locale: string | null;
1157
+ translated_names: number;
1158
+ translated_keywords: number;
1159
+ fallback_names: number;
1160
+ fallback_keywords: number;
1161
+ }
1162
+ interface EmojiShortcodeSourceMetadata {
1163
+ records: number;
1164
+ missing_records: number;
1165
+ ambiguous_aliases: number;
1166
+ }
1167
+ interface EmojiCategory {
1168
+ category: string;
1169
+ subcategories: string[];
1170
+ }
1171
+ interface EmojiCategories {
1172
+ categories: EmojiCategory[];
1173
+ }
1174
+ /** UTF-16 code-unit positions. End is exclusive. */
1175
+ interface EmojiPosition {
1176
+ start: number;
1177
+ end: number;
1178
+ }
1179
+ /** Original input UTF-16 positions; end is exclusive. */
1180
+ interface EmojiUnresolved extends EmojiPosition {
1181
+ emoji?: string;
1182
+ shortcode?: string;
1183
+ reason: 'unknown' | 'ambiguous' | 'unavailable';
1062
1184
  }
1063
1185
  interface Address {
1064
1186
  address: string | null;
@@ -1586,12 +1708,16 @@ interface DateInfoDeep {
1586
1708
  days_in_month: number | null;
1587
1709
  }
1588
1710
  interface EmojiDeep {
1711
+ subcategory?: string | null;
1712
+ base?: string | null;
1713
+ variants?: EmojiVariant[];
1589
1714
  codepoints: string[];
1590
1715
  hex: string;
1591
1716
  status: string | null;
1592
1717
  version: string | null;
1593
1718
  keywords: string[];
1594
1719
  skins: EmojiSkin[];
1720
+ artwork?: Record<string, EmojiArtwork>;
1595
1721
  }
1596
1722
  interface NaicsDeep {
1597
1723
  description: string | null;
@@ -1749,6 +1875,15 @@ interface IbanDeep {
1749
1875
  branch: string | null;
1750
1876
  account: string | null;
1751
1877
  }
1878
+ interface EmojiParse {
1879
+ emojis: (Emoji & {
1880
+ positions: EmojiPosition[];
1881
+ })[];
1882
+ }
1883
+ interface EmojiConversion {
1884
+ text: string;
1885
+ unresolved: EmojiUnresolved[];
1886
+ }
1752
1887
 
1753
1888
  /** A proposed task contains operation counts, never lookup inputs. */
1754
1889
  interface PreflightOperation {
@@ -1908,6 +2043,73 @@ interface AgentTaskResult<T = unknown> {
1908
2043
  };
1909
2044
  }
1910
2045
 
2046
+ interface EmojiCatalogLookupOptions {
2047
+ deep?: boolean;
2048
+ shortcodeSource?: string;
2049
+ }
2050
+ interface EmojiCatalogSearchOptions {
2051
+ deep?: boolean;
2052
+ limit?: number;
2053
+ offset?: number;
2054
+ category?: string;
2055
+ subcategory?: string;
2056
+ version?: string;
2057
+ maxVersion?: string;
2058
+ includeSkinTones?: boolean;
2059
+ }
2060
+ interface EmojiCatalogParseOptions {
2061
+ deep?: boolean;
2062
+ }
2063
+ interface EmojiCatalogConvertOptions {
2064
+ direction: 'to_shortcodes' | 'to_emoji';
2065
+ shortcodeSource: 'cldr' | 'github' | 'slack' | 'discord';
2066
+ }
2067
+ interface EmojiCatalogRegexOptions {
2068
+ qualifiedOnly?: boolean;
2069
+ components?: boolean;
2070
+ }
2071
+ /** A local validation or resolution failure. No HTTP request was made. */
2072
+ declare class EmojiCatalogError extends Error {
2073
+ readonly code: 'validation_error' | 'not_found' | 'invalid_catalog';
2074
+ constructor(code: 'validation_error' | 'not_found' | 'invalid_catalog', message: string);
2075
+ }
2076
+ /** Immutable local snapshot. All operations are synchronous and use no network. */
2077
+ declare class EmojiCatalog {
2078
+ private readonly data;
2079
+ private readonly byGlyph;
2080
+ private readonly names;
2081
+ private readonly aliases;
2082
+ private readonly sourceAliases;
2083
+ private readonly encodings;
2084
+ private readonly searchFacts;
2085
+ private readonly categoryKeys;
2086
+ private readonly subcategoryKeys;
2087
+ private readonly filterCache;
2088
+ private searchReady;
2089
+ private readonly compareNames;
2090
+ private segmenter?;
2091
+ constructor(data: EmojiCatalogData);
2092
+ /** Build once on first search; shared normalized strings avoid repeated annotation copies. */
2093
+ private ensureSearch;
2094
+ private encoding;
2095
+ /** Evidence for the full server inventory; scope() identifies this downloaded subset. */
2096
+ metadata(): EmojiMetadata;
2097
+ /** Filters, local record count and whether this download contains the full server inventory. */
2098
+ scope(): EmojiCatalogScope;
2099
+ lookup(input: string, options?: EmojiCatalogLookupOptions): Emoji;
2100
+ search(query: string, options?: EmojiCatalogSearchOptions): EmojiSearch;
2101
+ browse(options?: EmojiCatalogSearchOptions): EmojiBrowse;
2102
+ /** Unknown and ambiguous inputs remain literal; positions refer to untouched input. */
2103
+ convert(text: string, options: EmojiCatalogConvertOptions): EmojiConversion;
2104
+ /** Whole-grapheme predicate. Use parse() to extract emoji from prose with positions. */
2105
+ regex(options?: EmojiCatalogRegexOptions): RegExp;
2106
+ categories(): EmojiCategories;
2107
+ parse(text: string, options?: EmojiCatalogParseOptions): EmojiParse;
2108
+ private project;
2109
+ private page;
2110
+ private filtered;
2111
+ }
2112
+
1911
2113
  /** Every non-2xx response from the API. Branch on `code`, never on `message`. */
1912
2114
  declare class ParseAPIError extends Error {
1913
2115
  /** HTTP status */
@@ -2194,10 +2396,28 @@ type WeatherOptions = DeepOption & {
2194
2396
  /** Past UTC day, YYYY-MM-DD. Requires paid deep and populates deep.history alongside current. */
2195
2397
  date?: string;
2196
2398
  } & RequestOptions;
2197
- type EmojiOptions = LanguageOption & DeepOption & RequestOptions;
2399
+ type EmojiOptions = LanguageOption & {
2400
+ shortcodeSource?: string;
2401
+ } & DeepOption & RequestOptions;
2198
2402
  type EmojiSearchOptions = LanguageOption & {
2199
2403
  limit?: number;
2404
+ category?: string;
2405
+ subcategory?: string;
2406
+ version?: string;
2407
+ maxVersion?: string;
2408
+ includeSkinTones?: boolean;
2409
+ offset?: number;
2200
2410
  } & DeepOption & RequestOptions;
2411
+ /** Complete catalog download; Deep defaults true. JSON supports offline EmojiCatalog. */
2412
+ type EmojiCatalogOptions = Omit<EmojiSearchOptions, 'limit' | 'offset'> & {
2413
+ profile?: 'full' | 'compact';
2414
+ };
2415
+ type EmojiBrowseOptions = EmojiSearchOptions;
2416
+ type EmojiParseOptions = LanguageOption & DeepOption & RequestOptions;
2417
+ type EmojiConvertOptions = RequestOptions & {
2418
+ direction: 'to_shortcodes' | 'to_emoji';
2419
+ shortcodeSource: 'cldr' | 'github' | 'slack' | 'discord';
2420
+ };
2201
2421
  interface DeepOption {
2202
2422
  /** Request endpoint-specific enrichment. Email/VAT checks are metered. Reference depth can be pooled or included with a paid plan. See the operation's help. */
2203
2423
  deep?: boolean;
@@ -2343,6 +2563,13 @@ declare function parseAPI(apiKey?: string, options?: ParseAPIOptions): {
2343
2563
  weather: (lat: number, lon: number, opts?: WeatherOptions) => Promise<Weather>;
2344
2564
  emoji: ((emoji: string, opts?: EmojiOptions) => Promise<Emoji>) & {
2345
2565
  search: (query: string, opts?: EmojiSearchOptions) => Promise<EmojiSearch>;
2566
+ browse: (opts?: EmojiBrowseOptions) => Promise<EmojiBrowse>;
2567
+ categories: (opts?: RequestOptions) => Promise<EmojiCategories>;
2568
+ convert: (text: string, opts: EmojiConvertOptions) => Promise<EmojiConversion>;
2569
+ /** Extract complete sequences. Positions use UTF-16 code units; end is exclusive. */
2570
+ catalog: (opts?: EmojiCatalogOptions) => Promise<EmojiCatalogData>;
2571
+ metadata: (opts?: RequestOptions) => Promise<EmojiMetadata>;
2572
+ parse: (text: string, opts?: EmojiParseOptions) => Promise<EmojiParse>;
2346
2573
  };
2347
2574
  };
2348
2575
  type ParseAPIClient = ReturnType<typeof parseAPI>;
@@ -2355,4 +2582,4 @@ type IbanOptions = {
2355
2582
  type NpiOptions = LanguageOption & DeepOption & RequestOptions;
2356
2583
  type BinOptions = DeepOption & RequestOptions;
2357
2584
 
2358
- export { type Address, type AddressOptions, type AddressSearch, type AddressSearchOptions, type AddressSuggestion, type AgentTask, type AgentTaskInput, type AgentTaskLookupInput, type AgentTaskResult, type Asn, type AsnOptions, type Bank, type BankChecks, type BankDeep, type BankDirectory, type BankIssue, type BankOptions, type BankRequirementField, type BankRequirements, type BankRequirementsOptions, type BankUsAch, type BankUsAchChecks, type BankUsAchInput, type Bin, type BinOptions, type Bloc, type BlocCountries, type BlocCountriesOptions, type BlocCountryItem, type BlocOptions, type Caller, type CallerOptions, type Card, type CardDeep, type CardOptions, type Carrier, type CarrierDeep, type CarrierOptions, type City, type CityDeep, type CityIdOptions, type CityNearby, type CityNearbyOptions, type CityNearest, type CityNearestOptions, type CityOptions, type CitySearch, type CitySearchOptions, type Company, type CompanyCandidate, type CompanyCountry, type CompanyCoverage, type CompanyCoverageOptions, type CompanyDeep, type CompanyEmailAddress, type CompanyIdOptions, type CompanyMatch, type CompanyOptions, type CompanyPhoneNumber, type CompanyProfile, type CompanyProfileAddress, type CompanyProfileDeep, type CompanyProfileDomain, type CompanyProfileEmail, type CompanyProfileEmployees, type CompanyProfileFounding, type CompanyProfileIdentifier, type CompanyProfileIndustry, type CompanyProfileJurisdiction, type CompanyProfileListing, type CompanyProfilePhone, type CompanyProfileRegistration, type CompanyProfileRegistrationAddress, type CompanyProfileRegistrationLegalForm, type CompanyProfileSource, type CompanyProfileWebsite, type CompanySearch, type CompanySearchOptions, type CompanySocialProfile, type Continent, type ContinentCountries, type ContinentCountriesOptions, type ContinentCountryItem, type ContinentOptions, type Country, type CountryDeep, type CountryElevationPoint, type CountryEmergency, type CountryOptions, type CountryStateItem, type CountryStates, type CountryStatesOptions, type Currency, type CurrencyDeep, type CurrencyOptions, type CurrencyRate, type CurrencyRateOptions, type DateInfo, type DateInfoDeep, type DateOptions, type DateTodayOptions, type Deep, type District, type DistrictDeep, type DistrictOptions, type Dns, type DnsOptions, type DnsRecord, type Domain, type DomainDeep, type DomainOptions, type DomainRegistration, type Elevation, type ElevationLocations, type ElevationOptions, type Email, type EmailDeep, type EmailOptions, type Emoji, type EmojiDeep, type EmojiOptions, type EmojiSearch, type EmojiSearchOptions, type EmojiSkin, type Hlr, type HlrDeep, type HlrOptions, type Holiday, type HolidayDate, type HolidayDateOptions, type HolidayOptions, type HolidayYear, type Iban, type IbanDeep, type IbanOptions, type Industry, type IndustryChild, type IndustryCorrection, type IndustryDeep, type IndustryExclusion, type IndustryMatch, type IndustryOptions, type IndustrySearch, type IndustrySearchItem, type IndustrySearchOptions, type Ip, type IpDeep, type IpOptions, type IpSelfOptions, type Language, type LanguageDeep, type LanguageOption, type LanguageOptions, type Mac, type MacOptions, type Measure, type MeasureChoice, type MeasureOptions, type MeasureUnit, type MeasureUnits, type MeasureUnitsOptions, type Mx, type MxOptions, type MxRecord, type Naics, type NaicsChild, type NaicsCorrection, type NaicsDeep, type NaicsExclusion, type NaicsMatch, type NaicsOptions, type NaicsSearch, type NaicsSearchItem, type NaicsSearchOptions, type Name, type NameDeep, type NameOptions, type Npi, type NpiDeep, type NpiEnrollment, type NpiOptions, type ParseAPIClient, ParseAPIError, type ParseAPIOptions, type Phone, type PhoneDeep, type PhoneOptions, type Point, type PointCity, type PointDeep, type PointOptions, type Postal, type PostalDeep, type PostalDistance, type PostalDistanceEnd, type PostalDistanceOptions, type PostalLocality, type PostalMetro, type PostalMetrosDeep, type PostalNearby, type PostalNearbyItem, type PostalNearbyOptions, type PostalOptions, type Preflight, type PreflightCost, type PreflightEmailCapacity, type PreflightOperation, type PreflightOperationEstimate, type PreflightPooledCapacity, type PreflightSpendCapacity, type PreflightTask, type PropertyTax, type Provider, type ProviderDeep, type ProviderEnrollment, type ProviderOptions, type ProviderSource, type ProviderSources, type ProviderTaxonomy, type RequestOptions, type Stack, type StackOptions, type StackTechnology, type State, type StateDeep, type StateDistrictDeep, type StateDistrictItem, type StateDistricts, type StateDistrictsOptions, type StateOptions, type Tariff, type TariffDeep, type TariffMeasure, type TariffOptions, type TariffSearch, type TariffSearchHit, type TariffSearchOptions, type Time, type TimeAtOptions, type TimeLocation, type TimeLocationCandidate, type TimeLocationInput, type TimeOptions, type TimeResolution, type TimeResolutionAlternative, type TimeSeason, type TimeTransition, type TimeTransitionState, type TimeZoneEntry, type TimeZones, type TimeZonesOptions, type Timezone, type TimezoneAtOptions, type TimezoneConversionTarget, type TimezoneConversionTargetDeep, type TimezoneDeep, type TimezoneNextDst, type TimezoneOptions, type Useragent, type UseragentBrowserBrand, type UseragentBrowserDeep, type UseragentDeep, type UseragentDeviceDeep, type UseragentEngineDeep, type UseragentOptions, type UseragentOsDeep, type Vat, type VatAddress, type VatDeep, type VatOptions, type Vehicle, type VehicleDeep, type VehicleOptions, type VehicleRecall, type Vin, type VinDeep, type VinOptions, type VinRecall, type Weather, type WeatherAir, type WeatherAlert, type WeatherCurrent, type WeatherCurrentDeep, type WeatherDay, type WeatherDeep, type WeatherForecastPeriod, type WeatherHistory, type WeatherHour, type WeatherMinute, type WeatherOptions, type WeatherStation, parseAPI };
2585
+ export { type Address, type AddressOptions, type AddressSearch, type AddressSearchOptions, type AddressSuggestion, type AgentTask, type AgentTaskInput, type AgentTaskLookupInput, type AgentTaskResult, type Asn, type AsnOptions, type Bank, type BankChecks, type BankDeep, type BankDirectory, type BankIssue, type BankOptions, type BankRequirementField, type BankRequirements, type BankRequirementsOptions, type BankUsAch, type BankUsAchChecks, type BankUsAchInput, type Bin, type BinOptions, type Bloc, type BlocCountries, type BlocCountriesOptions, type BlocCountryItem, type BlocOptions, type Caller, type CallerOptions, type Card, type CardDeep, type CardOptions, type Carrier, type CarrierDeep, type CarrierOptions, type City, type CityDeep, type CityIdOptions, type CityNearby, type CityNearbyOptions, type CityNearest, type CityNearestOptions, type CityOptions, type CitySearch, type CitySearchOptions, type Company, type CompanyCandidate, type CompanyCountry, type CompanyCoverage, type CompanyCoverageOptions, type CompanyDeep, type CompanyEmailAddress, type CompanyIdOptions, type CompanyMatch, type CompanyOptions, type CompanyPhoneNumber, type CompanyProfile, type CompanyProfileAddress, type CompanyProfileDeep, type CompanyProfileDomain, type CompanyProfileEmail, type CompanyProfileEmployees, type CompanyProfileFounding, type CompanyProfileIdentifier, type CompanyProfileIndustry, type CompanyProfileJurisdiction, type CompanyProfileListing, type CompanyProfilePhone, type CompanyProfileRegistration, type CompanyProfileRegistrationAddress, type CompanyProfileRegistrationLegalForm, type CompanyProfileSource, type CompanyProfileWebsite, type CompanySearch, type CompanySearchOptions, type CompanySocialProfile, type Continent, type ContinentCountries, type ContinentCountriesOptions, type ContinentCountryItem, type ContinentOptions, type Country, type CountryDeep, type CountryElevationPoint, type CountryEmergency, type CountryOptions, type CountryStateItem, type CountryStates, type CountryStatesOptions, type Currency, type CurrencyDeep, type CurrencyOptions, type CurrencyRate, type CurrencyRateOptions, type DateInfo, type DateInfoDeep, type DateOptions, type DateTodayOptions, type Deep, type District, type DistrictDeep, type DistrictOptions, type Dns, type DnsOptions, type DnsRecord, type Domain, type DomainDeep, type DomainOptions, type DomainRegistration, type Elevation, type ElevationLocations, type ElevationOptions, type Email, type EmailDeep, type EmailOptions, type Emoji, type EmojiArtwork, type EmojiArtworkSource, type EmojiBrowse, type EmojiBrowseOptions, EmojiCatalog, type EmojiCatalogConvertOptions, type EmojiCatalogData, EmojiCatalogError, type EmojiCatalogLocalization, type EmojiCatalogLookupOptions, type EmojiCatalogOptions, type EmojiCatalogParseOptions, type EmojiCatalogRegexOptions, type EmojiCatalogScope, type EmojiCatalogSearchFacts, type EmojiCatalogSearchOptions, type EmojiCategories, type EmojiCategory, type EmojiConversion, type EmojiConvertOptions, type EmojiDeep, type EmojiMetadata, type EmojiNativeSearchFacts, type EmojiNotice, type EmojiOptions, type EmojiParse, type EmojiParseOptions, type EmojiPosition, type EmojiSearch, type EmojiSearchOptions, type EmojiShortcodeSourceMetadata, type EmojiSkin, type EmojiSource, type EmojiUnresolved, type EmojiVariant, type Hlr, type HlrDeep, type HlrOptions, type Holiday, type HolidayDate, type HolidayDateOptions, type HolidayOptions, type HolidayYear, type Iban, type IbanDeep, type IbanOptions, type Industry, type IndustryChild, type IndustryCorrection, type IndustryDeep, type IndustryExclusion, type IndustryMatch, type IndustryOptions, type IndustrySearch, type IndustrySearchItem, type IndustrySearchOptions, type Ip, type IpDeep, type IpOptions, type IpSelfOptions, type Language, type LanguageDeep, type LanguageOption, type LanguageOptions, type Mac, type MacOptions, type Measure, type MeasureChoice, type MeasureOptions, type MeasureUnit, type MeasureUnits, type MeasureUnitsOptions, type Mx, type MxOptions, type MxRecord, type Naics, type NaicsChild, type NaicsCorrection, type NaicsDeep, type NaicsExclusion, type NaicsMatch, type NaicsOptions, type NaicsSearch, type NaicsSearchItem, type NaicsSearchOptions, type Name, type NameDeep, type NameOptions, type Npi, type NpiDeep, type NpiEnrollment, type NpiOptions, type ParseAPIClient, ParseAPIError, type ParseAPIOptions, type Phone, type PhoneDeep, type PhoneOptions, type Point, type PointCity, type PointDeep, type PointOptions, type Postal, type PostalDeep, type PostalDistance, type PostalDistanceEnd, type PostalDistanceOptions, type PostalLocality, type PostalMetro, type PostalMetrosDeep, type PostalNearby, type PostalNearbyItem, type PostalNearbyOptions, type PostalOptions, type Preflight, type PreflightCost, type PreflightEmailCapacity, type PreflightOperation, type PreflightOperationEstimate, type PreflightPooledCapacity, type PreflightSpendCapacity, type PreflightTask, type PropertyTax, type Provider, type ProviderDeep, type ProviderEnrollment, type ProviderOptions, type ProviderSource, type ProviderSources, type ProviderTaxonomy, type RequestOptions, type Stack, type StackOptions, type StackTechnology, type State, type StateDeep, type StateDistrictDeep, type StateDistrictItem, type StateDistricts, type StateDistrictsOptions, type StateOptions, type Tariff, type TariffDeep, type TariffMeasure, type TariffOptions, type TariffSearch, type TariffSearchHit, type TariffSearchOptions, type Time, type TimeAtOptions, type TimeLocation, type TimeLocationCandidate, type TimeLocationInput, type TimeOptions, type TimeResolution, type TimeResolutionAlternative, type TimeSeason, type TimeTransition, type TimeTransitionState, type TimeZoneEntry, type TimeZones, type TimeZonesOptions, type Timezone, type TimezoneAtOptions, type TimezoneConversionTarget, type TimezoneConversionTargetDeep, type TimezoneDeep, type TimezoneNextDst, type TimezoneOptions, type Useragent, type UseragentBrowserBrand, type UseragentBrowserDeep, type UseragentDeep, type UseragentDeviceDeep, type UseragentEngineDeep, type UseragentOptions, type UseragentOsDeep, type Vat, type VatAddress, type VatDeep, type VatOptions, type Vehicle, type VehicleDeep, type VehicleOptions, type VehicleRecall, type Vin, type VinDeep, type VinOptions, type VinRecall, type Weather, type WeatherAir, type WeatherAlert, type WeatherCurrent, type WeatherCurrentDeep, type WeatherDay, type WeatherDeep, type WeatherForecastPeriod, type WeatherHistory, type WeatherHour, type WeatherMinute, type WeatherOptions, type WeatherStation, parseAPI };
package/dist/index.js CHANGED
@@ -1,3 +1,260 @@
1
+ // src/emoji-catalog.ts
2
+ var EmojiCatalogError = class extends Error {
3
+ constructor(code, message) {
4
+ super(message);
5
+ this.code = code;
6
+ this.name = "EmojiCatalogError";
7
+ }
8
+ };
9
+ var sources = ["cldr", "github", "slack", "discord"];
10
+ var stripColons = (value) => value.trim().replace(/^:+|:+$/g, "");
11
+ var normalizeName = (value) => stripColons(value).toLowerCase().replace(/[\s_-]+/g, "_");
12
+ var normalizeSearch = (value) => normalizeName(value).normalize("NFD").replace(new RegExp("\\p{M}", "gu"), "").replace(/œ/g, "oe").replace(/æ/g, "ae").replace(/ß/g, "ss");
13
+ var legacyName = (value) => stripColons(value).toLowerCase().replace(/\s+/g, "_");
14
+ var filterKey = (value) => value.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
15
+ var versionCompare = (a, b) => {
16
+ const left = a.split(".").map(Number), right = b.split(".").map(Number);
17
+ return (left[0] ?? 0) - (right[0] ?? 0) || (left[1] ?? 0) - (right[1] ?? 0);
18
+ };
19
+ var invalid = (message) => {
20
+ throw new EmojiCatalogError("validation_error", message);
21
+ };
22
+ var EmojiCatalog = class {
23
+ data;
24
+ byGlyph = /* @__PURE__ */ new Map();
25
+ names = /* @__PURE__ */ new Map();
26
+ aliases = /* @__PURE__ */ new Map();
27
+ sourceAliases = /* @__PURE__ */ new Map();
28
+ encodings = /* @__PURE__ */ new Map();
29
+ searchFacts = /* @__PURE__ */ new Map();
30
+ categoryKeys = /* @__PURE__ */ new Set();
31
+ subcategoryKeys = /* @__PURE__ */ new Set();
32
+ filterCache = /* @__PURE__ */ new Map();
33
+ searchReady = false;
34
+ compareNames;
35
+ segmenter;
36
+ constructor(data) {
37
+ if (!data || !Array.isArray(data.emojis) || !data.forms || !data.shortcodes || !data.legacy || !data.metadata?.source_version) {
38
+ throw new EmojiCatalogError("invalid_catalog", "Use the JSON response from GET /emoji/catalog.");
39
+ }
40
+ this.data = structuredClone(data);
41
+ this.compareNames = new Intl.Collator(this.data.localization?.resolved_locale ?? void 0).compare;
42
+ const add = (map, key, glyph) => {
43
+ if (!key) return;
44
+ if (!map.has(key)) map.set(key, /* @__PURE__ */ new Set());
45
+ map.get(key).add(glyph);
46
+ };
47
+ for (const row of this.data.emojis) {
48
+ if (!row?.emoji || !row.deep?.version || !Array.isArray(row.deep.keywords)) {
49
+ throw new EmojiCatalogError("invalid_catalog", "Offline catalogs require the default deep=true export.");
50
+ }
51
+ this.byGlyph.set(row.emoji, row);
52
+ add(this.names, normalizeName(row.name), row.emoji);
53
+ for (const alias of row.shortcodes) add(this.aliases, normalizeName(alias), row.emoji);
54
+ this.categoryKeys.add(filterKey(row.category ?? ""));
55
+ this.subcategoryKeys.add(filterKey(row.deep.subcategory ?? ""));
56
+ }
57
+ for (const source of sources) {
58
+ if (!this.data.shortcodes[source]) throw new EmojiCatalogError("invalid_catalog", `Catalog is missing the ${source} shortcode map.`);
59
+ }
60
+ }
61
+ /** Build once on first search; shared normalized strings avoid repeated annotation copies. */
62
+ ensureSearch() {
63
+ if (this.searchReady) return;
64
+ const cache = /* @__PURE__ */ new Map(), normal = (value) => {
65
+ let result = cache.get(value);
66
+ if (result === void 0) {
67
+ result = normalizeSearch(value);
68
+ cache.set(value, result);
69
+ }
70
+ return result;
71
+ };
72
+ for (const source of sources) for (const [alias, glyphs] of Object.entries(this.data.shortcodes[source])) {
73
+ const value = normal(alias);
74
+ for (const glyph of glyphs) if (this.byGlyph.has(glyph)) {
75
+ if (!this.sourceAliases.has(glyph)) this.sourceAliases.set(glyph, /* @__PURE__ */ new Set());
76
+ this.sourceAliases.get(glyph).add(value);
77
+ }
78
+ }
79
+ const localizedKeywords = new Set(this.data.search?.localized_keywords ?? []);
80
+ for (const row of this.data.emojis) {
81
+ const native = this.data.search?.native[row.emoji];
82
+ const names = [...new Set([row.name, native?.name].filter((name) => typeof name === "string").map(normal))];
83
+ const primaryShorts = [...new Set(row.shortcodes.map(normal))];
84
+ const shorts = [.../* @__PURE__ */ new Set([...primaryShorts, ...this.sourceAliases.get(row.emoji) ?? []])];
85
+ const keywords = [...new Set([...row.deep?.keywords ?? [], ...native?.keywords ?? []].map(normal))];
86
+ const allNames = [...names, ...shorts];
87
+ this.searchFacts.set(row.emoji, { names, primaryShorts, shorts, keywords, translatedKeywords: this.data.localization?.resolved_locale && localizedKeywords.has(row.emoji) ? (row.deep?.keywords ?? []).map(normal) : [], allNames, blob: [.../* @__PURE__ */ new Set([...allNames, ...keywords])].join(" ") });
88
+ }
89
+ this.sourceAliases.clear();
90
+ this.searchReady = true;
91
+ }
92
+ encoding(source) {
93
+ let map = this.encodings.get(source);
94
+ if (!map) {
95
+ map = /* @__PURE__ */ new Map();
96
+ for (const [alias, glyphs] of Object.entries(this.data.shortcodes[source])) if (glyphs.length === 1 && this.byGlyph.has(glyphs[0]) && !map.has(glyphs[0])) map.set(glyphs[0], `:${stripColons(alias)}:`);
97
+ this.encodings.set(source, map);
98
+ }
99
+ return map;
100
+ }
101
+ /** Evidence for the full server inventory; scope() identifies this downloaded subset. */
102
+ metadata() {
103
+ return structuredClone(this.data.metadata);
104
+ }
105
+ /** Filters, local record count and whether this download contains the full server inventory. */
106
+ scope() {
107
+ return structuredClone({ ...this.data.scope, filters: this.data.scope?.filters ?? {}, total: this.data.total, complete_inventory: this.data.scope?.complete_inventory ?? this.data.total === this.data.metadata.total });
108
+ }
109
+ lookup(input, options = {}) {
110
+ if (typeof input !== "string" || !input.trim() || input.trim().length > 512) invalid("Emoji input must contain 1\u2013512 characters.");
111
+ const value = input.trim(), source = options.shortcodeSource;
112
+ if (source && !sources.includes(source)) invalid("shortcodeSource must be cldr, github, slack or discord.");
113
+ let glyph = this.byGlyph.has(value) ? value : void 0;
114
+ if (!glyph && !source && Object.hasOwn(this.data.legacy, legacyName(value))) glyph = this.data.legacy[legacyName(value)];
115
+ if (!glyph) {
116
+ let form = value;
117
+ if (/^(?:U\+)?[0-9A-F]{4,6}(?:[\s,-]+(?:U\+)?[0-9A-F]{4,6})*$/i.test(value)) {
118
+ const points = value.split(/[\s,-]+/).map((part) => Number.parseInt(part.replace(/^U\+/i, ""), 16));
119
+ if (points.length > 32 || points.some((cp) => cp > 1114111 || cp >= 55296 && cp <= 57343)) invalid("Unicode codepoints must be valid scalar values.");
120
+ form = String.fromCodePoint(...points);
121
+ } else if (/^U\+/i.test(value)) invalid("Use Unicode codepoints such as U+1F680 or U+2764 U+FE0F.");
122
+ const canonical = Object.hasOwn(this.data.forms, form) ? this.data.forms[form] : form;
123
+ if (canonical && this.byGlyph.has(canonical)) glyph = canonical;
124
+ }
125
+ if (!glyph) {
126
+ const candidates = /* @__PURE__ */ new Set();
127
+ for (const key of /* @__PURE__ */ new Set([stripColons(value).toLowerCase(), normalizeName(value)])) {
128
+ for (const name of source ? [source] : sources) {
129
+ const dictionary = this.data.shortcodes[name];
130
+ if (Object.hasOwn(dictionary, key)) {
131
+ for (const candidate of dictionary[key] ?? []) if (this.byGlyph.has(candidate)) candidates.add(candidate);
132
+ }
133
+ }
134
+ }
135
+ if (!source) for (const candidate of this.aliases.get(normalizeName(value)) ?? []) candidates.add(candidate);
136
+ if (!source || !candidates.size && !/^:.*:$/.test(value)) for (const candidate of this.names.get(normalizeName(value)) ?? []) candidates.add(candidate);
137
+ if (candidates.size > 1) invalid("Emoji shortcode is ambiguous. Set shortcodeSource to cldr, github, slack or discord.");
138
+ glyph = candidates.values().next().value;
139
+ }
140
+ const row = glyph ? this.byGlyph.get(glyph) : void 0;
141
+ if (!row) throw new EmojiCatalogError("not_found", "Emoji not found in this downloaded catalog.");
142
+ return this.project(row, options.deep === true);
143
+ }
144
+ search(query, options = {}) {
145
+ if (typeof query !== "string" || !query.trim() || query.trim().length > 256) invalid("Search query must contain 1\u2013256 characters.");
146
+ return this.page(query.trim(), options);
147
+ }
148
+ browse(options = {}) {
149
+ const { q, ...result } = this.page("", options);
150
+ return result;
151
+ }
152
+ /** Unknown and ambiguous inputs remain literal; positions refer to untouched input. */
153
+ convert(text, options) {
154
+ if (!options || !["to_shortcodes", "to_emoji"].includes(options.direction)) invalid("Direction must be to_shortcodes or to_emoji.");
155
+ if (!sources.includes(options.shortcodeSource)) invalid("shortcodeSource must be cldr, github, slack or discord.");
156
+ const parsed = this.parse(text), replacements = [], unresolved = [];
157
+ if (options.direction === "to_shortcodes") {
158
+ const encodings = this.encoding(options.shortcodeSource);
159
+ for (const row of parsed.emojis) {
160
+ const shortcode = encodings.get(row.emoji);
161
+ for (const position of row.positions) if (shortcode) replacements.push({ emoji: row.emoji, shortcode, ...position });
162
+ else unresolved.push({ emoji: row.emoji, ...position, reason: "unavailable" });
163
+ }
164
+ } else for (const match of text.matchAll(/:[^:\s]{1,128}:/gu)) {
165
+ const shortcode = match[0], start = match.index, end = start + shortcode.length;
166
+ try {
167
+ const row = this.lookup(shortcode, { shortcodeSource: options.shortcodeSource });
168
+ replacements.push({ emoji: row.emoji, shortcode, start, end });
169
+ } catch (error) {
170
+ if (!(error instanceof EmojiCatalogError)) throw error;
171
+ unresolved.push({ shortcode, start, end, reason: error.code === "not_found" ? "unknown" : "ambiguous" });
172
+ }
173
+ }
174
+ replacements.sort((a, b) => a.start - b.start);
175
+ unresolved.sort((a, b) => a.start - b.start);
176
+ let cursor = 0;
177
+ const chunks = [];
178
+ for (const row of replacements) {
179
+ chunks.push(text.slice(cursor, row.start), options.direction === "to_shortcodes" ? row.shortcode : row.emoji);
180
+ cursor = row.end;
181
+ }
182
+ chunks.push(text.slice(cursor));
183
+ return { text: chunks.join(""), unresolved };
184
+ }
185
+ /** Whole-grapheme predicate. Use parse() to extract emoji from prose with positions. */
186
+ regex(options = {}) {
187
+ const forms = options.qualifiedOnly ? [...this.byGlyph.keys()] : Object.keys(this.data.forms).filter((form) => this.byGlyph.has(this.data.forms[form]));
188
+ if (options.components) forms.push(...["\u{1F3FB}", "\u{1F3FC}", "\u{1F3FD}", "\u{1F3FE}", "\u{1F3FF}", "\u{1F9B0}", "\u{1F9B1}", "\u{1F9B2}", "\u{1F9B3}"]);
189
+ const escaped = [...new Set(forms)].sort((a, b) => b.length - a.length || (a < b ? -1 : 1)).map((form) => form.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
190
+ return new RegExp(`^(?:${escaped.length ? escaped.join("|") : "(?!)"})$`, "u");
191
+ }
192
+ categories() {
193
+ const groups = /* @__PURE__ */ new Map();
194
+ for (const row of this.data.emojis) {
195
+ if (!row.category) continue;
196
+ if (!groups.has(row.category)) groups.set(row.category, /* @__PURE__ */ new Set());
197
+ if (row.deep?.subcategory) groups.get(row.category).add(row.deep.subcategory);
198
+ }
199
+ return { categories: [...groups].map(([category, subcategories]) => ({ category, subcategories: [...subcategories] })) };
200
+ }
201
+ parse(text, options = {}) {
202
+ if (typeof text !== "string" || text.length > 16e3) invalid("Text must be a string of at most 16000 UTF-16 code units.");
203
+ const found = /* @__PURE__ */ new Map();
204
+ this.segmenter ??= new Intl.Segmenter("en", { granularity: "grapheme" });
205
+ for (const { segment, index } of this.segmenter.segment(text)) {
206
+ const canonical = Object.hasOwn(this.data.forms, segment) ? this.data.forms[segment] : segment;
207
+ const row = canonical ? this.byGlyph.get(canonical) : void 0;
208
+ if (!row) continue;
209
+ if (!found.has(row.emoji)) found.set(row.emoji, { ...this.project(row, options.deep === true), positions: [] });
210
+ const result = found.get(row.emoji);
211
+ result.positions.push({ start: index, end: index + segment.length });
212
+ }
213
+ return { emojis: [...found.values()] };
214
+ }
215
+ project(row, deep) {
216
+ const { emoji, name, shortcodes, category } = row;
217
+ return { emoji, name, shortcodes: [...shortcodes], category, ...deep ? { deep: structuredClone(row.deep) } : {} };
218
+ }
219
+ page(query, options) {
220
+ if (options.limit !== void 0 && (!Number.isSafeInteger(options.limit) || options.limit < 1)) invalid("Limit must be a positive integer.");
221
+ const limit = Math.min(options.limit ?? 20, 50), offset = options.offset ?? 0;
222
+ if (!Number.isSafeInteger(offset) || offset < 0 || offset > 1e5) invalid("Offset must be an integer between 0 and 100000.");
223
+ for (const [key, known] of [["category", this.categoryKeys], ["subcategory", this.subcategoryKeys]]) {
224
+ if (options[key] !== void 0 && (!options[key].trim() || !known.has(filterKey(options[key])))) invalid(`Unknown emoji ${key}. Use categories() to find supported values.`);
225
+ }
226
+ for (const key of ["version", "maxVersion"]) if (options[key] !== void 0 && (!/^\d{1,2}\.\d{1,2}$/.test(options[key]) || versionCompare(options[key], this.data.metadata.source_version) > 0)) invalid(`${key} must be an Emoji version no newer than ${this.data.metadata.source_version}.`);
227
+ let rows = this.filtered(options);
228
+ if (query) {
229
+ this.ensureSearch();
230
+ const needle = normalizeSearch(query), words = needle.split("_").filter(Boolean);
231
+ const scored = rows.flatMap((row) => {
232
+ const { names, primaryShorts, shorts, keywords, translatedKeywords, allNames, blob } = this.searchFacts.get(row.emoji);
233
+ if (!blob.includes(needle) && !(words.length > 1 && words.every((word) => blob.includes(word)))) return [];
234
+ const score = primaryShorts.includes(needle) || names.includes(needle) ? 0 : shorts.includes(needle) ? 0.5 : allNames.some((value) => value.startsWith(needle)) ? 1 : translatedKeywords.includes(needle) ? 1.5 : allNames.some((value) => value.includes(needle)) ? 2 : words.length > 1 && allNames.some((value) => words.every((word) => value.includes(word))) ? 2.5 : keywords.some((value) => value.includes(needle)) ? 3 : words.length > 1 && words.every((word) => blob.includes(word)) ? 4 : 100;
235
+ return score === 100 ? [] : [{ row, score }];
236
+ });
237
+ rows = scored.sort((a, b) => a.score - b.score || (this.data.localization?.resolved_locale ? this.compareNames(a.row.name, b.row.name) || a.row.emoji.localeCompare(b.row.emoji) : a.row.name.localeCompare(b.row.name))).map(({ row }) => row);
238
+ }
239
+ const page = rows.slice(offset, offset + limit), paged = !query || ["category", "subcategory", "version", "maxVersion", "includeSkinTones", "offset"].some((key) => options[key] !== void 0);
240
+ return { q: query, emojis: page.map((row) => this.project(row, options.deep === true)), ...paged ? { total: rows.length, next_offset: offset + page.length < rows.length ? offset + page.length : null } : {} };
241
+ }
242
+ filtered(options) {
243
+ for (const [key2, known] of [["category", this.categoryKeys], ["subcategory", this.subcategoryKeys]]) {
244
+ if (options[key2] !== void 0 && (!options[key2].trim() || !known.has(filterKey(options[key2])))) invalid(`Unknown emoji ${key2}. Use categories() to find supported values.`);
245
+ }
246
+ for (const key2 of ["version", "maxVersion"]) if (options[key2] !== void 0 && (!/^\d{1,2}\.\d{1,2}$/.test(options[key2]) || versionCompare(options[key2], this.data.metadata.source_version) > 0)) invalid(`${key2} must be an Emoji version no newer than ${this.data.metadata.source_version}.`);
247
+ if (options.includeSkinTones !== false && options.category === void 0 && options.subcategory === void 0 && options.version === void 0 && options.maxVersion === void 0) return this.data.emojis;
248
+ const key = JSON.stringify([options.includeSkinTones === false, options.category === void 0 ? null : filterKey(options.category), options.subcategory === void 0 ? null : filterKey(options.subcategory), options.version, options.maxVersion]);
249
+ const cached = this.filterCache.get(key);
250
+ if (cached) return cached;
251
+ const rows = this.data.emojis.filter((row) => (options.includeSkinTones !== false || !/[\u{1F3FB}-\u{1F3FF}]/u.test(row.emoji)) && (options.category === void 0 || filterKey(row.category ?? "") === filterKey(options.category)) && (options.subcategory === void 0 || filterKey(row.deep?.subcategory ?? "") === filterKey(options.subcategory)) && (options.version === void 0 || versionCompare(row.deep.version, options.version) === 0) && (options.maxVersion === void 0 || versionCompare(row.deep.version, options.maxVersion) <= 0));
252
+ if (this.filterCache.size >= 32) this.filterCache.delete(this.filterCache.keys().next().value);
253
+ this.filterCache.set(key, rows);
254
+ return rows;
255
+ }
256
+ };
257
+
1
258
  // src/index.ts
2
259
  var VERSION = "1.10.0";
3
260
  var API_VERSION = "2.0.0";
@@ -403,13 +660,23 @@ function parseAPI(apiKey, options = {}) {
403
660
  /** Get current conditions in metric and imperial units. Paid deep adds specialist current measurements, forecasts and related detail. With deep, date selects a past UTC day (YYYY-MM-DD) in deep.history alongside current conditions. Date alone does not request history. */
404
661
  weather: (lat, lon, opts) => request("/weather", { lat, lon, date: opts?.date, ...deepQuery(opts) }, void 0, opts),
405
662
  emoji: Object.assign(
406
- (emoji, opts) => request(`/emoji/${enc(emoji)}`, deepQuery(opts), void 0, opts),
663
+ (emoji, opts) => request(`/emoji/${enc(emoji)}`, { shortcode_source: opts?.shortcodeSource, ...deepQuery(opts) }, void 0, opts),
407
664
  {
408
- search: (query, opts) => request("/emoji", { q: query, limit: opts?.limit, ...deepQuery(opts) }, void 0, opts)
665
+ search: (query, opts) => request("/emoji", { q: query, ...emojiFilters(opts), ...deepQuery(opts) }, void 0, opts),
666
+ browse: (opts) => request("/emoji", { ...emojiFilters(opts), ...deepQuery(opts) }, void 0, opts),
667
+ categories: (opts) => request("/emoji/categories", void 0, void 0, requestControls(opts)),
668
+ convert: (text, opts) => request("/emoji/convert", { direction: opts.direction, shortcode_source: opts.shortcodeSource }, void 0, opts, { text }),
669
+ /** Extract complete sequences. Positions use UTF-16 code units; end is exclusive. */
670
+ catalog: (opts) => request("/emoji/catalog", { ...emojiFilters(opts), profile: opts?.profile, deep: opts?.deep ?? true }, void 0, opts),
671
+ metadata: (opts) => request("/emoji/metadata", void 0, void 0, requestControls(opts)),
672
+ parse: (text, opts) => request("/emoji/parse", deepQuery(opts), void 0, opts, { text })
409
673
  }
410
674
  )
411
675
  };
412
676
  }
677
+ function emojiFilters(opts) {
678
+ return { limit: opts?.limit, category: opts?.category, subcategory: opts?.subcategory, version: opts?.version, max_version: opts?.maxVersion, include_skin_tones: opts?.includeSkinTones, offset: opts?.offset };
679
+ }
413
680
  function timeSource(timezone, options = {}) {
414
681
  const values = { ip: options.ip, city: options.city, country: options.country, state: options.state, iata: options.iata, icao: options.icao, unlocode: options.unlocode, address: options.address };
415
682
  const primary = [options.ip, options.city, options.iata, options.icao, options.unlocode, options.address].filter((value) => value !== void 0);
@@ -429,6 +696,8 @@ function timeTargets(targets, to) {
429
696
  return targets.join(",");
430
697
  }
431
698
  export {
699
+ EmojiCatalog,
700
+ EmojiCatalogError,
432
701
  ParseAPIError,
433
702
  parseAPI
434
703
  };