tdk-api-wrapper 1.0.1 → 1.2.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/dist/index.d.ts CHANGED
@@ -96,6 +96,36 @@ interface SpellCheckResult {
96
96
  word: string;
97
97
  suggestion?: string;
98
98
  }
99
+ interface WordOfTheDay {
100
+ word: string;
101
+ meanings: string[];
102
+ }
103
+ interface DailyPick {
104
+ type: "kelime" | "atasoz";
105
+ madde: string;
106
+ anlam: string;
107
+ }
108
+ interface TDKRule {
109
+ adi: string;
110
+ url: string;
111
+ }
112
+ interface WordComparisonSide {
113
+ word: string;
114
+ meaningCount: number;
115
+ origin: string | null;
116
+ syllables: string[];
117
+ harmony: boolean;
118
+ }
119
+ interface WordComparison {
120
+ a: WordComparisonSide;
121
+ b: WordComparisonSide;
122
+ }
123
+ interface WordAnalysis {
124
+ word: string;
125
+ found: boolean;
126
+ meaning: string | null;
127
+ origin: string | null;
128
+ }
99
129
  type TDKResponse = WordInfo[] | {
100
130
  error: string;
101
131
  };
@@ -105,6 +135,7 @@ type TDKResponse = WordInfo[] | {
105
135
  */
106
136
  declare class TDK {
107
137
  private static readonly BASE_URL;
138
+ private static readonly AUDIO_API_HOST;
108
139
  private static isCacheEnabled;
109
140
  private static wordCache;
110
141
  private static dailyContentCache;
@@ -127,7 +158,22 @@ declare class TDK {
127
158
  */
128
159
  static getMeanings(word: string): Promise<string[]>;
129
160
  /**
130
- * Returns suggestions (autocomplete) for a given prefix.
161
+ * `sozluk.gov.tr`'s dedicated `/autocomplete.json` (and `/data/autocomplete.json`)
162
+ * routes no longer serve JSON — they fall through to the SPA's `index.html`.
163
+ * The full ~81k-word headword list the site's own autocomplete UI uses is
164
+ * instead bundled directly into its main JS asset as a
165
+ * `JSON.parse(\`[{"madde":"..."}]\`)` literal, so this fetches the home
166
+ * page to find that asset's current hashed filename, downloads it (a few
167
+ * MB, only once per process), and extracts the literal out of it. Fragile
168
+ * scraping of an implementation detail — if TDK's build stops embedding
169
+ * this, this fails closed to `[]` rather than throwing.
170
+ */
171
+ private static fetchAutocompleteData;
172
+ /**
173
+ * Returns autocomplete suggestions for a given prefix, searched over TDK's
174
+ * full headword list (see `fetchAutocompleteData`). The list is fetched
175
+ * and cached once per process regardless of `enableCache()` — the same
176
+ * caching behavior as before — and only cleared by `clearCache()`.
131
177
  */
132
178
  static getSuggestions(prefix: string): Promise<string[]>;
133
179
  /**
@@ -135,9 +181,21 @@ declare class TDK {
135
181
  */
136
182
  static getProverbs(word: string): Promise<string[]>;
137
183
  /**
138
- * Returns the etymological origin of the word if it's a foreign word.
184
+ * Returns the etymological origin of the word, or "Türkçe" if TDK doesn't
185
+ * record a foreign origin for it. Returns `null` only when the word itself
186
+ * isn't found in the dictionary at all.
139
187
  */
140
188
  static getOrigin(word: string): Promise<string | null>;
189
+ /**
190
+ * Returns whether the word has a recorded foreign etymological origin.
191
+ * Returns `null` (instead of a boolean) when the word isn't found at all.
192
+ */
193
+ static isForeignWord(word: string): Promise<boolean | null>;
194
+ /**
195
+ * Groups a list of words by their etymological origin. Words not found in
196
+ * the dictionary are grouped under "Bilinmiyor". Throttled like getWordsBatch.
197
+ */
198
+ static groupByOrigin(words: string[]): Promise<Record<string, string[]>>;
141
199
  /**
142
200
  * Returns literature examples containing the word.
143
201
  */
@@ -146,8 +204,34 @@ declare class TDK {
146
204
  author: string | null;
147
205
  }[]>;
148
206
  /**
149
- * Returns the direct URL of the audio pronunciation if available.
150
- * Note: TDK audio URL usually uses the exact audio id. Sometimes it requires MD5, but we provide a common pattern.
207
+ * Calls the `api.sozluk.gov.tr/gts-yeni` endpoint the official web UI uses
208
+ * internally (richer than the public `/gts`: includes `seskod`,
209
+ * `anlamEsAnlam`/`anlamKarsitAnlam`, etc). That endpoint 403s unless the
210
+ * request looks like it came from a browser tab on sozluk.gov.tr: it needs
211
+ * an `Origin`/`Referer` pair matching that site AND a browser-like
212
+ * `User-Agent` (our usual `TDK-API-Nodejs-Wrapper/…` UA gets rejected).
213
+ * `fetch` (undici) also strips a manually-set `Origin` header as a
214
+ * forbidden header name, so this uses `node:https` directly instead.
215
+ * This is inherently fragile scraping of an undocumented endpoint — if
216
+ * TDK tightens this check further, this should fail closed to `null`
217
+ * rather than throw.
218
+ */
219
+ private static fetchGtsYeni;
220
+ private static fetchSeskod;
221
+ /**
222
+ * Returns synonyms ("eş anlamlı kelimeler") recorded for the word, pooled
223
+ * across all of its meanings. Uses the same undocumented `gts-yeni`
224
+ * endpoint as `getAudioUrl` — returns `[]` if the lookup fails.
225
+ */
226
+ static getSynonyms(word: string): Promise<string[]>;
227
+ /**
228
+ * Returns antonyms ("zıt anlamlı kelimeler") recorded for the word, pooled
229
+ * across all of its meanings. Uses the same undocumented `gts-yeni`
230
+ * endpoint as `getAudioUrl` — returns `[]` if the lookup fails.
231
+ */
232
+ static getAntonyms(word: string): Promise<string[]>;
233
+ /**
234
+ * Returns the direct URL of the audio pronunciation, if TDK has one recorded for this word.
151
235
  */
152
236
  static getAudioUrl(word: string): Promise<string | null>;
153
237
  /**
@@ -162,14 +246,70 @@ declare class TDK {
162
246
  * Fetches daily content (word of the day, proverbs, rules, etc).
163
247
  */
164
248
  static getDailyContent(): Promise<DailyContent | null>;
249
+ /**
250
+ * Returns today's word of the day along with all of its listed meanings.
251
+ */
252
+ static getWordOfTheDay(): Promise<WordOfTheDay | null>;
253
+ /**
254
+ * Picks a random entry (word or proverb) from today's daily content.
255
+ * Note: this samples from today's `getDailyContent()` picks, not the full dictionary.
256
+ */
257
+ static getRandomWord(): Promise<DailyPick | null>;
258
+ /**
259
+ * Returns the spelling-rule page(s) ("yazım kuralları") linked from TDK's
260
+ * `/icerik` daily-content feed, e.g. `{ adi: "Kısaltmalar", url: "https://..." }`.
261
+ * Note: like `getRandomWord()`, this is NOT a fixed catalog — `/icerik`
262
+ * appears to hand back a single randomly-rotated rule per request, so two
263
+ * calls a second apart can return entirely different rules.
264
+ */
265
+ static getKurallar(): Promise<TDKRule[]>;
266
+ /**
267
+ * Fetches the full plain-text content of a named spelling rule (matched
268
+ * case-insensitively, substring match) from `tdk.gov.tr`. Since `/icerik`
269
+ * hands back a single randomly-rotated rule per request (out of a pool of
270
+ * roughly twenty) rather than a fixed catalog, a single `getKurallar()`
271
+ * draw would rarely match a given name — this re-draws (bounded, with a
272
+ * short delay) until it finds a match or gives up. Returns `null` if no
273
+ * match turns up within the attempt budget or the matched page can't be
274
+ * parsed.
275
+ */
276
+ static getRule(name: string): Promise<string | null>;
277
+ /**
278
+ * `tdk.gov.tr` rule pages are WordPress/Avada-themed. The actual article
279
+ * text lives in `<div ... itemprop="text">...</div>` right before a
280
+ * `<footer class="entry...">` (share buttons, author box, structured-data
281
+ * spans) — cutting there avoids that trailing cruft.
282
+ */
283
+ private static fetchRuleText;
284
+ private static htmlToPlainText;
165
285
  /**
166
286
  * Returns compound words that contain this word.
167
287
  */
168
288
  static getCompoundWords(word: string): Promise<string[]>;
169
289
  /**
170
290
  * Returns the part of speech (isim, sıfat, zarf vb.).
291
+ * TDK's `ozelliklerListe` mixes grammatical categories (`tur: "3"`, e.g.
292
+ * sıfat/zarf/isim) with usage-register tags (`tur: "4"`, e.g. mecaz/argo)
293
+ * in the same list — only `tur === "3"` entries are actual parts of speech.
171
294
  */
172
295
  static getPartOfSpeech(word: string): Promise<string[]>;
296
+ /**
297
+ * Compares two words side by side: meaning count, etymological origin,
298
+ * syllables and vowel-harmony compliance.
299
+ */
300
+ static compareWords(a: string, b: string): Promise<WordComparison>;
301
+ private static readonly STOPWORDS;
302
+ private static firstMeaning;
303
+ /**
304
+ * Analyzes every distinct word in a text (Turkish stopwords filtered out),
305
+ * returning each word's first meaning and etymological origin if found.
306
+ * Looks each word up individually (throttled), so scales with text length.
307
+ */
308
+ static analyzeText(text: string): Promise<WordAnalysis[]>;
309
+ /**
310
+ * Classic edit-distance between two strings.
311
+ */
312
+ private static levenshtein;
173
313
  /**
174
314
  * Fetches multiple words concurrently with a small delay to avoid rate limiting.
175
315
  */
@@ -180,8 +320,36 @@ declare class TDK {
180
320
  static syllabicate(word: string): string[];
181
321
  /**
182
322
  * Checks if a word follows Turkish Major Vowel Harmony (Büyük Ünlü Uyumu).
323
+ * Normalizes case via the Turkish locale first: a plain case-insensitive
324
+ * regex would fold ASCII "I" to "i", misreading the back vowel "I"
325
+ * (dotless) as the front vowel "i" (dotted).
183
326
  */
184
327
  static checkVowelHarmony(word: string): boolean;
185
328
  }
186
329
 
187
- export { type Author, type DailyContent, type Example, type Feature, type Meaning, type Proverb, type SpellCheckResult, TDK, type TDKResponse, type WordInfo };
330
+ /**
331
+ * Base class for all errors thrown by this library.
332
+ */
333
+ declare class TDKError extends Error {
334
+ constructor(message: string);
335
+ }
336
+ /**
337
+ * Thrown when a caller-supplied argument is invalid (e.g. an empty word).
338
+ */
339
+ declare class TDKValidationError extends TDKError {
340
+ constructor(message: string);
341
+ }
342
+ /**
343
+ * Thrown when a request to sozluk.gov.tr fails at the network/HTTP level
344
+ * (connection failure, non-OK HTTP status, unparsable response, etc).
345
+ */
346
+ declare class TDKNetworkError extends TDKError {
347
+ readonly status?: number;
348
+ readonly cause?: unknown;
349
+ constructor(message: string, options?: {
350
+ status?: number;
351
+ cause?: unknown;
352
+ });
353
+ }
354
+
355
+ export { type Author, type DailyContent, type DailyPick, type Example, type Feature, type Meaning, type Proverb, type SpellCheckResult, TDK, TDKError, TDKNetworkError, type TDKResponse, type TDKRule, TDKValidationError, type WordAnalysis, type WordComparison, type WordComparisonSide, type WordInfo, type WordOfTheDay };