tdk-api-wrapper 1.0.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/.github/workflows/publish.yml +41 -0
- package/LICENSE +21 -0
- package/README.md +69 -0
- package/dist/chunk-MGSXCUAX.mjs +325 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +422 -0
- package/dist/cli.mjs +80 -0
- package/dist/index.d.mts +187 -0
- package/dist/index.d.ts +187 -0
- package/dist/index.js +361 -0
- package/dist/index.mjs +6 -0
- package/package.json +36 -0
- package/src/cli.ts +81 -0
- package/src/index.ts +2 -0
- package/src/tdk.ts +370 -0
- package/src/types.ts +90 -0
- package/tsconfig.json +11 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
interface Author {
|
|
2
|
+
yazar_id: string;
|
|
3
|
+
tam_adi: string;
|
|
4
|
+
kisa_adi: string;
|
|
5
|
+
ekno: string;
|
|
6
|
+
}
|
|
7
|
+
interface Example {
|
|
8
|
+
ornek_id: string;
|
|
9
|
+
anlam_id: string;
|
|
10
|
+
ornek_sira: string;
|
|
11
|
+
ornek: string;
|
|
12
|
+
kac: string;
|
|
13
|
+
yazar_id: string;
|
|
14
|
+
yazar_vd: string;
|
|
15
|
+
yazar?: Author[];
|
|
16
|
+
}
|
|
17
|
+
interface Feature {
|
|
18
|
+
ozellik_id: string;
|
|
19
|
+
tur: string;
|
|
20
|
+
tam_adi: string;
|
|
21
|
+
kisa_adi: string;
|
|
22
|
+
ekno: string;
|
|
23
|
+
}
|
|
24
|
+
interface Meaning {
|
|
25
|
+
anlam_id: string;
|
|
26
|
+
madde_id: string;
|
|
27
|
+
anlam_sira: string;
|
|
28
|
+
fiil: string;
|
|
29
|
+
tipkes: string;
|
|
30
|
+
anlam: string;
|
|
31
|
+
anlam_html: string | null;
|
|
32
|
+
gos: string;
|
|
33
|
+
gos_kelime: string;
|
|
34
|
+
gos_kultur: string;
|
|
35
|
+
orneklerListe?: Example[];
|
|
36
|
+
ozelliklerListe?: Feature[];
|
|
37
|
+
}
|
|
38
|
+
interface Proverb {
|
|
39
|
+
madde_id: string;
|
|
40
|
+
madde: string;
|
|
41
|
+
on_taki: string | null;
|
|
42
|
+
}
|
|
43
|
+
interface WordInfo {
|
|
44
|
+
madde_id: string;
|
|
45
|
+
kac: string;
|
|
46
|
+
kelime_no: string;
|
|
47
|
+
cesit: string;
|
|
48
|
+
anlam_gor: string;
|
|
49
|
+
on_taki: string | null;
|
|
50
|
+
on_taki_html: string | null;
|
|
51
|
+
madde: string;
|
|
52
|
+
madde_html: string | null;
|
|
53
|
+
cesit_say: string;
|
|
54
|
+
anlam_say: string;
|
|
55
|
+
taki: string;
|
|
56
|
+
cogul_mu: string;
|
|
57
|
+
ozel_mi: string;
|
|
58
|
+
egik_mi: string;
|
|
59
|
+
lisan_kodu: string;
|
|
60
|
+
lisan: string;
|
|
61
|
+
telaffuz_html: string | null;
|
|
62
|
+
telaffuz: string;
|
|
63
|
+
birlesikler: string | null;
|
|
64
|
+
font: string | null;
|
|
65
|
+
madde_duz: string;
|
|
66
|
+
gosterim_tarihi: string | null;
|
|
67
|
+
anlamlarListe?: Meaning[];
|
|
68
|
+
atasozu?: Proverb[];
|
|
69
|
+
}
|
|
70
|
+
interface DailyContent {
|
|
71
|
+
kelime: {
|
|
72
|
+
madde: string;
|
|
73
|
+
anlam: string;
|
|
74
|
+
}[];
|
|
75
|
+
atasoz: {
|
|
76
|
+
madde: string;
|
|
77
|
+
anlam: string;
|
|
78
|
+
}[];
|
|
79
|
+
kural: {
|
|
80
|
+
adi: string;
|
|
81
|
+
url: string;
|
|
82
|
+
}[];
|
|
83
|
+
syyd: {
|
|
84
|
+
id: string;
|
|
85
|
+
yanliskelime: string;
|
|
86
|
+
dogrukelime: string;
|
|
87
|
+
}[];
|
|
88
|
+
karistirma: {
|
|
89
|
+
id: string;
|
|
90
|
+
yanlis: string;
|
|
91
|
+
dogru: string;
|
|
92
|
+
}[];
|
|
93
|
+
}
|
|
94
|
+
interface SpellCheckResult {
|
|
95
|
+
isCorrect: boolean;
|
|
96
|
+
word: string;
|
|
97
|
+
suggestion?: string;
|
|
98
|
+
}
|
|
99
|
+
type TDKResponse = WordInfo[] | {
|
|
100
|
+
error: string;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* TDK (Türk Dil Kurumu) API Wrapper
|
|
105
|
+
*/
|
|
106
|
+
declare class TDK {
|
|
107
|
+
private static readonly BASE_URL;
|
|
108
|
+
private static isCacheEnabled;
|
|
109
|
+
private static wordCache;
|
|
110
|
+
private static dailyContentCache;
|
|
111
|
+
private static autocompleteCache;
|
|
112
|
+
/**
|
|
113
|
+
* Enables or disables in-memory caching for API requests.
|
|
114
|
+
*/
|
|
115
|
+
static enableCache(status?: boolean): void;
|
|
116
|
+
/**
|
|
117
|
+
* Clears the internal cache.
|
|
118
|
+
*/
|
|
119
|
+
static clearCache(): void;
|
|
120
|
+
private static delay;
|
|
121
|
+
/**
|
|
122
|
+
* Fetches detailed information for a given word from the TDK Dictionary.
|
|
123
|
+
*/
|
|
124
|
+
static getWord(word: string): Promise<WordInfo[]>;
|
|
125
|
+
/**
|
|
126
|
+
* Helper method to get only the meanings (definitions) of a word as a string array.
|
|
127
|
+
*/
|
|
128
|
+
static getMeanings(word: string): Promise<string[]>;
|
|
129
|
+
/**
|
|
130
|
+
* Returns suggestions (autocomplete) for a given prefix.
|
|
131
|
+
*/
|
|
132
|
+
static getSuggestions(prefix: string): Promise<string[]>;
|
|
133
|
+
/**
|
|
134
|
+
* Returns a list of proverbs and idioms containing the word.
|
|
135
|
+
*/
|
|
136
|
+
static getProverbs(word: string): Promise<string[]>;
|
|
137
|
+
/**
|
|
138
|
+
* Returns the etymological origin of the word if it's a foreign word.
|
|
139
|
+
*/
|
|
140
|
+
static getOrigin(word: string): Promise<string | null>;
|
|
141
|
+
/**
|
|
142
|
+
* Returns literature examples containing the word.
|
|
143
|
+
*/
|
|
144
|
+
static getExamples(word: string): Promise<{
|
|
145
|
+
sentence: string;
|
|
146
|
+
author: string | null;
|
|
147
|
+
}[]>;
|
|
148
|
+
/**
|
|
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.
|
|
151
|
+
*/
|
|
152
|
+
static getAudioUrl(word: string): Promise<string | null>;
|
|
153
|
+
/**
|
|
154
|
+
* Downloads the audio pronunciation to the specified path.
|
|
155
|
+
*/
|
|
156
|
+
static downloadAudio(word: string, destPath?: string): Promise<string | null>;
|
|
157
|
+
/**
|
|
158
|
+
* Checks spelling and returns suggestions if wrong.
|
|
159
|
+
*/
|
|
160
|
+
static checkSpelling(word: string): Promise<SpellCheckResult>;
|
|
161
|
+
/**
|
|
162
|
+
* Fetches daily content (word of the day, proverbs, rules, etc).
|
|
163
|
+
*/
|
|
164
|
+
static getDailyContent(): Promise<DailyContent | null>;
|
|
165
|
+
/**
|
|
166
|
+
* Returns compound words that contain this word.
|
|
167
|
+
*/
|
|
168
|
+
static getCompoundWords(word: string): Promise<string[]>;
|
|
169
|
+
/**
|
|
170
|
+
* Returns the part of speech (isim, sıfat, zarf vb.).
|
|
171
|
+
*/
|
|
172
|
+
static getPartOfSpeech(word: string): Promise<string[]>;
|
|
173
|
+
/**
|
|
174
|
+
* Fetches multiple words concurrently with a small delay to avoid rate limiting.
|
|
175
|
+
*/
|
|
176
|
+
static getWordsBatch(words: string[]): Promise<WordInfo[][]>;
|
|
177
|
+
/**
|
|
178
|
+
* Syllabicates a Turkish word based on general grammar rules.
|
|
179
|
+
*/
|
|
180
|
+
static syllabicate(word: string): string[];
|
|
181
|
+
/**
|
|
182
|
+
* Checks if a word follows Turkish Major Vowel Harmony (Büyük Ünlü Uyumu).
|
|
183
|
+
*/
|
|
184
|
+
static checkVowelHarmony(word: string): boolean;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export { type Author, type DailyContent, type Example, type Feature, type Meaning, type Proverb, type SpellCheckResult, TDK, type TDKResponse, type WordInfo };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
|
+
TDK: () => TDK
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(src_exports);
|
|
36
|
+
|
|
37
|
+
// src/tdk.ts
|
|
38
|
+
var fs = __toESM(require("fs"));
|
|
39
|
+
var path = __toESM(require("path"));
|
|
40
|
+
var os = __toESM(require("os"));
|
|
41
|
+
var TDK = class {
|
|
42
|
+
static BASE_URL = "https://sozluk.gov.tr";
|
|
43
|
+
// Cache Mechanism
|
|
44
|
+
static isCacheEnabled = false;
|
|
45
|
+
static wordCache = /* @__PURE__ */ new Map();
|
|
46
|
+
static dailyContentCache = null;
|
|
47
|
+
static autocompleteCache = [];
|
|
48
|
+
/**
|
|
49
|
+
* Enables or disables in-memory caching for API requests.
|
|
50
|
+
*/
|
|
51
|
+
static enableCache(status = true) {
|
|
52
|
+
this.isCacheEnabled = status;
|
|
53
|
+
if (!status) {
|
|
54
|
+
this.clearCache();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Clears the internal cache.
|
|
59
|
+
*/
|
|
60
|
+
static clearCache() {
|
|
61
|
+
this.wordCache.clear();
|
|
62
|
+
this.dailyContentCache = null;
|
|
63
|
+
this.autocompleteCache = [];
|
|
64
|
+
}
|
|
65
|
+
static delay(ms) {
|
|
66
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Fetches detailed information for a given word from the TDK Dictionary.
|
|
70
|
+
*/
|
|
71
|
+
static async getWord(word) {
|
|
72
|
+
if (!word || word.trim() === "") {
|
|
73
|
+
throw new Error("Word parameter cannot be empty.");
|
|
74
|
+
}
|
|
75
|
+
const cleanWord = word.trim().toLowerCase();
|
|
76
|
+
if (this.isCacheEnabled && this.wordCache.has(cleanWord)) {
|
|
77
|
+
return this.wordCache.get(cleanWord);
|
|
78
|
+
}
|
|
79
|
+
const url = `${this.BASE_URL}/gts?ara=${encodeURIComponent(cleanWord)}`;
|
|
80
|
+
try {
|
|
81
|
+
const response = await fetch(url, {
|
|
82
|
+
headers: { "User-Agent": "TDK-API-Nodejs-Wrapper/1.0" }
|
|
83
|
+
});
|
|
84
|
+
if (!response.ok)
|
|
85
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
86
|
+
const data = await response.json();
|
|
87
|
+
if (!Array.isArray(data) && data && "error" in data) {
|
|
88
|
+
if (this.isCacheEnabled)
|
|
89
|
+
this.wordCache.set(cleanWord, []);
|
|
90
|
+
return [];
|
|
91
|
+
}
|
|
92
|
+
const results = data;
|
|
93
|
+
if (this.isCacheEnabled) {
|
|
94
|
+
this.wordCache.set(cleanWord, results);
|
|
95
|
+
}
|
|
96
|
+
return results;
|
|
97
|
+
} catch (error) {
|
|
98
|
+
if (error instanceof Error)
|
|
99
|
+
throw new Error(`Failed to fetch word from TDK: ${error.message}`);
|
|
100
|
+
throw new Error("Failed to fetch word from TDK: Unknown error");
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Helper method to get only the meanings (definitions) of a word as a string array.
|
|
105
|
+
*/
|
|
106
|
+
static async getMeanings(word) {
|
|
107
|
+
const results = await this.getWord(word);
|
|
108
|
+
if (results.length === 0)
|
|
109
|
+
return [];
|
|
110
|
+
const meanings = [];
|
|
111
|
+
for (const result of results) {
|
|
112
|
+
if (result.anlamlarListe) {
|
|
113
|
+
for (const anlam of result.anlamlarListe) {
|
|
114
|
+
if (anlam.anlam)
|
|
115
|
+
meanings.push(anlam.anlam);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return meanings;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Returns suggestions (autocomplete) for a given prefix.
|
|
123
|
+
*/
|
|
124
|
+
static async getSuggestions(prefix) {
|
|
125
|
+
if (this.autocompleteCache.length === 0) {
|
|
126
|
+
try {
|
|
127
|
+
const response = await fetch(`${this.BASE_URL}/autocomplete.json`, {
|
|
128
|
+
headers: { "User-Agent": "TDK-API-Nodejs-Wrapper/1.0" }
|
|
129
|
+
});
|
|
130
|
+
if (response.ok) {
|
|
131
|
+
const data = await response.json();
|
|
132
|
+
this.autocompleteCache = data.map((item) => item.madde);
|
|
133
|
+
}
|
|
134
|
+
} catch (e) {
|
|
135
|
+
return [];
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const cleanPrefix = prefix.toLowerCase();
|
|
139
|
+
return this.autocompleteCache.filter((w) => w.toLowerCase().startsWith(cleanPrefix)).slice(0, 10);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Returns a list of proverbs and idioms containing the word.
|
|
143
|
+
*/
|
|
144
|
+
static async getProverbs(word) {
|
|
145
|
+
const results = await this.getWord(word);
|
|
146
|
+
if (results.length === 0)
|
|
147
|
+
return [];
|
|
148
|
+
const proverbs = [];
|
|
149
|
+
for (const result of results) {
|
|
150
|
+
if (result.atasozu) {
|
|
151
|
+
for (const atasoz of result.atasozu) {
|
|
152
|
+
if (atasoz.madde)
|
|
153
|
+
proverbs.push(atasoz.madde);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return proverbs;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Returns the etymological origin of the word if it's a foreign word.
|
|
161
|
+
*/
|
|
162
|
+
static async getOrigin(word) {
|
|
163
|
+
const results = await this.getWord(word);
|
|
164
|
+
if (results.length > 0 && results[0].lisan) {
|
|
165
|
+
return results[0].lisan;
|
|
166
|
+
}
|
|
167
|
+
return "T\xFCrk\xE7e";
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Returns literature examples containing the word.
|
|
171
|
+
*/
|
|
172
|
+
static async getExamples(word) {
|
|
173
|
+
const results = await this.getWord(word);
|
|
174
|
+
const examples = [];
|
|
175
|
+
for (const result of results) {
|
|
176
|
+
if (result.anlamlarListe) {
|
|
177
|
+
for (const anlam of result.anlamlarListe) {
|
|
178
|
+
if (anlam.orneklerListe) {
|
|
179
|
+
for (const ornek of anlam.orneklerListe) {
|
|
180
|
+
const author = ornek.yazar && ornek.yazar.length > 0 ? ornek.yazar[0].tam_adi : null;
|
|
181
|
+
examples.push({ sentence: ornek.ornek, author });
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return examples;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Returns the direct URL of the audio pronunciation if available.
|
|
191
|
+
* Note: TDK audio URL usually uses the exact audio id. Sometimes it requires MD5, but we provide a common pattern.
|
|
192
|
+
*/
|
|
193
|
+
static async getAudioUrl(word) {
|
|
194
|
+
const results = await this.getWord(word);
|
|
195
|
+
if (results.length > 0) {
|
|
196
|
+
return `https://sozluk.gov.tr/ses/${encodeURIComponent(word)}.wav`;
|
|
197
|
+
}
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Downloads the audio pronunciation to the specified path.
|
|
202
|
+
*/
|
|
203
|
+
static async downloadAudio(word, destPath) {
|
|
204
|
+
const url = await this.getAudioUrl(word);
|
|
205
|
+
if (!url)
|
|
206
|
+
return null;
|
|
207
|
+
const finalPath = destPath || path.join(os.tmpdir(), `${word}.wav`);
|
|
208
|
+
try {
|
|
209
|
+
const res = await fetch(url);
|
|
210
|
+
if (!res.ok)
|
|
211
|
+
return null;
|
|
212
|
+
const buffer = await res.arrayBuffer();
|
|
213
|
+
fs.writeFileSync(finalPath, Buffer.from(buffer));
|
|
214
|
+
return finalPath;
|
|
215
|
+
} catch {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Checks spelling and returns suggestions if wrong.
|
|
221
|
+
*/
|
|
222
|
+
static async checkSpelling(word) {
|
|
223
|
+
const results = await this.getWord(word);
|
|
224
|
+
if (results.length > 0) {
|
|
225
|
+
return { isCorrect: true, word };
|
|
226
|
+
}
|
|
227
|
+
const daily = await this.getDailyContent();
|
|
228
|
+
if (daily) {
|
|
229
|
+
const syydMatch = daily.syyd.find((s) => s.yanliskelime.toLowerCase() === word.toLowerCase());
|
|
230
|
+
if (syydMatch) {
|
|
231
|
+
return { isCorrect: false, word, suggestion: syydMatch.dogrukelime };
|
|
232
|
+
}
|
|
233
|
+
const mixMatch = daily.karistirma.find((s) => s.yanlis.toLowerCase() === word.toLowerCase());
|
|
234
|
+
if (mixMatch) {
|
|
235
|
+
return { isCorrect: false, word, suggestion: mixMatch.dogru };
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return { isCorrect: false, word };
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Fetches daily content (word of the day, proverbs, rules, etc).
|
|
242
|
+
*/
|
|
243
|
+
static async getDailyContent() {
|
|
244
|
+
if (this.isCacheEnabled && this.dailyContentCache)
|
|
245
|
+
return this.dailyContentCache;
|
|
246
|
+
try {
|
|
247
|
+
const response = await fetch(`${this.BASE_URL}/icerik`, {
|
|
248
|
+
headers: { "User-Agent": "TDK-API-Nodejs-Wrapper/1.0" }
|
|
249
|
+
});
|
|
250
|
+
if (response.ok) {
|
|
251
|
+
const data = await response.json();
|
|
252
|
+
if (this.isCacheEnabled)
|
|
253
|
+
this.dailyContentCache = data;
|
|
254
|
+
return data;
|
|
255
|
+
}
|
|
256
|
+
} catch {
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Returns compound words that contain this word.
|
|
263
|
+
*/
|
|
264
|
+
static async getCompoundWords(word) {
|
|
265
|
+
const results = await this.getWord(word);
|
|
266
|
+
if (results.length === 0)
|
|
267
|
+
return [];
|
|
268
|
+
const compound = [];
|
|
269
|
+
for (const result of results) {
|
|
270
|
+
if (result.birlesikler) {
|
|
271
|
+
const words = result.birlesikler.split(",").map((w) => w.trim());
|
|
272
|
+
compound.push(...words);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return [...new Set(compound)];
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Returns the part of speech (isim, sıfat, zarf vb.).
|
|
279
|
+
*/
|
|
280
|
+
static async getPartOfSpeech(word) {
|
|
281
|
+
const results = await this.getWord(word);
|
|
282
|
+
const pos = /* @__PURE__ */ new Set();
|
|
283
|
+
for (const result of results) {
|
|
284
|
+
if (result.anlamlarListe) {
|
|
285
|
+
for (const anlam of result.anlamlarListe) {
|
|
286
|
+
if (anlam.ozelliklerListe) {
|
|
287
|
+
for (const ozellik of anlam.ozelliklerListe) {
|
|
288
|
+
pos.add(ozellik.tam_adi);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
if (pos.size === 0 && results.length > 0) {
|
|
295
|
+
pos.add("isim");
|
|
296
|
+
}
|
|
297
|
+
return Array.from(pos);
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Fetches multiple words concurrently with a small delay to avoid rate limiting.
|
|
301
|
+
*/
|
|
302
|
+
static async getWordsBatch(words) {
|
|
303
|
+
const results = [];
|
|
304
|
+
for (const word of words) {
|
|
305
|
+
try {
|
|
306
|
+
const res = await this.getWord(word);
|
|
307
|
+
results.push(res);
|
|
308
|
+
} catch {
|
|
309
|
+
results.push([]);
|
|
310
|
+
}
|
|
311
|
+
await this.delay(200);
|
|
312
|
+
}
|
|
313
|
+
return results;
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Syllabicates a Turkish word based on general grammar rules.
|
|
317
|
+
*/
|
|
318
|
+
static syllabicate(word) {
|
|
319
|
+
const vowels = /[aeıioöuüAEIİOÖUÜ]/;
|
|
320
|
+
const result = [];
|
|
321
|
+
let currentSyllable = "";
|
|
322
|
+
for (let i = word.length - 1; i >= 0; i--) {
|
|
323
|
+
currentSyllable = word[i] + currentSyllable;
|
|
324
|
+
if (vowels.test(word[i])) {
|
|
325
|
+
if (i - 1 >= 0 && !vowels.test(word[i - 1])) {
|
|
326
|
+
if (i - 2 >= 0 && vowels.test(word[i - 2])) {
|
|
327
|
+
currentSyllable = word[i - 1] + currentSyllable;
|
|
328
|
+
i--;
|
|
329
|
+
} else if (i - 2 >= 0 && !vowels.test(word[i - 2])) {
|
|
330
|
+
currentSyllable = word[i - 1] + currentSyllable;
|
|
331
|
+
i--;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
result.unshift(currentSyllable);
|
|
335
|
+
currentSyllable = "";
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
if (currentSyllable) {
|
|
339
|
+
if (result.length > 0) {
|
|
340
|
+
result[0] = currentSyllable + result[0];
|
|
341
|
+
} else {
|
|
342
|
+
result.push(currentSyllable);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
return result;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Checks if a word follows Turkish Major Vowel Harmony (Büyük Ünlü Uyumu).
|
|
349
|
+
*/
|
|
350
|
+
static checkVowelHarmony(word) {
|
|
351
|
+
const backVowels = /[aıou]/i;
|
|
352
|
+
const frontVowels = /[eiöü]/i;
|
|
353
|
+
const hasBack = backVowels.test(word);
|
|
354
|
+
const hasFront = frontVowels.test(word);
|
|
355
|
+
return !(hasBack && hasFront);
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
359
|
+
0 && (module.exports = {
|
|
360
|
+
TDK
|
|
361
|
+
});
|
package/dist/index.mjs
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tdk-api-wrapper",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "TDK (Türk Dil Kurumu) unofficial live data API wrapper for Node.js",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"tdk": "dist/cli.js"
|
|
10
|
+
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.mjs",
|
|
15
|
+
"require": "./dist/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsup src/index.ts src/cli.ts --format cjs,esm --dts --clean --shims"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"tdk",
|
|
23
|
+
"sozluk",
|
|
24
|
+
"api",
|
|
25
|
+
"turkish",
|
|
26
|
+
"dictionary",
|
|
27
|
+
"turkce"
|
|
28
|
+
],
|
|
29
|
+
"author": "",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/node": "^22.0.0",
|
|
33
|
+
"tsup": "^8.0.2",
|
|
34
|
+
"typescript": "^5.4.5"
|
|
35
|
+
}
|
|
36
|
+
}
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { TDK } from "./tdk";
|
|
3
|
+
|
|
4
|
+
const args = process.argv.slice(2);
|
|
5
|
+
const command = args[0];
|
|
6
|
+
const word = args[1];
|
|
7
|
+
|
|
8
|
+
async function run() {
|
|
9
|
+
if (!command) {
|
|
10
|
+
console.log("Kullanım: tdk <komut> <kelime>");
|
|
11
|
+
console.log("Komutlar: ara, anlam, koken, ornek, hece, uyum, yazim");
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
TDK.enableCache(false);
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
switch (command) {
|
|
19
|
+
case "ara":
|
|
20
|
+
case "anlam":
|
|
21
|
+
if (!word) throw new Error("Kelime belirtmelisiniz.");
|
|
22
|
+
const meanings = await TDK.getMeanings(word);
|
|
23
|
+
if (meanings.length === 0) {
|
|
24
|
+
console.log("Sonuç bulunamadı.");
|
|
25
|
+
} else {
|
|
26
|
+
meanings.forEach((m, i) => console.log(`${i + 1}. ${m}`));
|
|
27
|
+
}
|
|
28
|
+
break;
|
|
29
|
+
|
|
30
|
+
case "koken":
|
|
31
|
+
if (!word) throw new Error("Kelime belirtmelisiniz.");
|
|
32
|
+
const origin = await TDK.getOrigin(word);
|
|
33
|
+
console.log(`Köken: ${origin}`);
|
|
34
|
+
break;
|
|
35
|
+
|
|
36
|
+
case "ornek":
|
|
37
|
+
if (!word) throw new Error("Kelime belirtmelisiniz.");
|
|
38
|
+
const examples = await TDK.getExamples(word);
|
|
39
|
+
if (examples.length === 0) {
|
|
40
|
+
console.log("Örnek bulunamadı.");
|
|
41
|
+
} else {
|
|
42
|
+
examples.forEach((ex, i) => {
|
|
43
|
+
const yazar = ex.author ? ` (${ex.author})` : "";
|
|
44
|
+
console.log(`${i + 1}. ${ex.sentence}${yazar}`);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
break;
|
|
48
|
+
|
|
49
|
+
case "hece":
|
|
50
|
+
if (!word) throw new Error("Kelime belirtmelisiniz.");
|
|
51
|
+
const syllables = TDK.syllabicate(word);
|
|
52
|
+
console.log(`Heceler: ${syllables.join("-")}`);
|
|
53
|
+
break;
|
|
54
|
+
|
|
55
|
+
case "uyum":
|
|
56
|
+
if (!word) throw new Error("Kelime belirtmelisiniz.");
|
|
57
|
+
const isHarmony = TDK.checkVowelHarmony(word);
|
|
58
|
+
console.log(`Büyük Ünlü Uyumu: ${isHarmony ? "Uyar" : "Uymaz"}`);
|
|
59
|
+
break;
|
|
60
|
+
|
|
61
|
+
case "yazim":
|
|
62
|
+
if (!word) throw new Error("Kelime belirtmelisiniz.");
|
|
63
|
+
const spellResult = await TDK.checkSpelling(word);
|
|
64
|
+
if (spellResult.isCorrect) {
|
|
65
|
+
console.log("Doğru yazım.");
|
|
66
|
+
} else {
|
|
67
|
+
console.log(`Yanlış yazım.${spellResult.suggestion ? " Doğrusu: " + spellResult.suggestion : ""}`);
|
|
68
|
+
}
|
|
69
|
+
break;
|
|
70
|
+
|
|
71
|
+
default:
|
|
72
|
+
console.log("Bilinmeyen komut.");
|
|
73
|
+
}
|
|
74
|
+
} catch (error) {
|
|
75
|
+
if (error instanceof Error) {
|
|
76
|
+
console.log(`Hata: ${error.message}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
run();
|
package/src/index.ts
ADDED