@dialexjs/mcp 0.9.1 → 0.9.2
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.mts.map +1 -1
- package/dist/index.mjs +440 -427
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/server.ts","../src/index.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/server.ts","../src/index.ts"],"mappings":";;wBAcgB,sBAAsB;EAAW;IAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBCCrD,aAAa,2BAA2B"}
|
package/dist/index.mjs
CHANGED
|
@@ -3,12 +3,12 @@ import fs from "node:fs";
|
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
5
|
import path from "node:path";
|
|
6
|
-
import { TODO_PREFIX, analyzeProject, copyLeaf, generateDictionaries, getString, hasPath, isStale, listLeaves, listLocales, loadDictionaryFile, loadStaticProject, readLock, readStaticConfig, saveDictionaryFile, scanReferences, setString } from "@dialexjs/cli/api";
|
|
7
6
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
8
7
|
import { CallToolRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
8
|
+
import { TODO_PREFIX, analyzeProject, copyLeaf, generateDictionaries, getString, hasPath, isStale, listLeaves, listLocales, loadDictionaryFile, loadStaticProject, readLock, readStaticConfig, saveDictionaryFile, scanReferences, setString } from "@dialexjs/cli/api";
|
|
9
9
|
import { z } from "zod";
|
|
10
10
|
//#region package.json
|
|
11
|
-
var version = "0.9.
|
|
11
|
+
var version = "0.9.2";
|
|
12
12
|
const DOC_TOPICS = {
|
|
13
13
|
guide: `# Dialex Internationalization Guide
|
|
14
14
|
|
|
@@ -83,449 +83,462 @@ All locales for a given key must declare the exact same variable placeholders.
|
|
|
83
83
|
`
|
|
84
84
|
};
|
|
85
85
|
//#endregion
|
|
86
|
-
//#region src/
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
86
|
+
//#region src/resources.ts
|
|
87
|
+
/** The documentation topics offered as `dialex://docs/<topic>` resources. */
|
|
88
|
+
function listDocResources() {
|
|
89
|
+
return { resources: Object.keys(DOC_TOPICS).map((topic) => ({
|
|
90
|
+
uri: `dialex://docs/${topic}`,
|
|
91
|
+
name: `Dialex Documentation: ${topic}`,
|
|
92
|
+
mimeType: "text/markdown",
|
|
93
|
+
description: `Reference documentation for Dialex ${topic}`
|
|
94
|
+
})) };
|
|
95
|
+
}
|
|
96
|
+
/** The content of one `dialex://docs/<topic>` resource. */
|
|
97
|
+
function readDocResource(uri) {
|
|
98
|
+
const match = /^dialex:\/\/docs\/([a-zA-Z0-9_-]+)$/.exec(uri);
|
|
99
|
+
if (!match) throw new Error(`Invalid resource URI: ${uri}`);
|
|
100
|
+
const topic = match[1];
|
|
101
|
+
const content = DOC_TOPICS[topic];
|
|
102
|
+
if (!content) throw new Error(`Documentation topic not found: ${topic}`);
|
|
103
|
+
return { contents: [{
|
|
104
|
+
uri,
|
|
105
|
+
mimeType: "text/markdown",
|
|
106
|
+
text: content
|
|
107
|
+
}] };
|
|
108
|
+
}
|
|
109
|
+
//#endregion
|
|
110
|
+
//#region src/tools/index.ts
|
|
111
|
+
/** Every tool, in the order clients see them. */
|
|
112
|
+
const TOOLS = [
|
|
113
|
+
{
|
|
114
|
+
name: "dialex_config",
|
|
115
|
+
description: "Read static Dialex configuration (locales, defaultLocale, include pattern) from dialex.config.ts or i18n.config.ts without executing project code.",
|
|
116
|
+
inputSchema: {
|
|
117
|
+
type: "object",
|
|
118
|
+
properties: { config: {
|
|
119
|
+
type: "string",
|
|
120
|
+
description: "Optional custom path to config file relative to project root."
|
|
121
|
+
} }
|
|
122
|
+
},
|
|
123
|
+
async handler(root, args) {
|
|
124
|
+
const parsed = z.object({ config: z.string().optional() }).parse(args);
|
|
125
|
+
const staticConf = readStaticConfig(root, parsed.config);
|
|
126
|
+
return { content: [{
|
|
127
|
+
type: "text",
|
|
128
|
+
text: JSON.stringify(staticConf, null, 2)
|
|
129
|
+
}] };
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
name: "dialex_list_dictionaries",
|
|
134
|
+
description: "List all discovered content dictionaries, their files, and supported locales.",
|
|
135
|
+
inputSchema: {
|
|
136
|
+
type: "object",
|
|
137
|
+
properties: { config: {
|
|
138
|
+
type: "string",
|
|
139
|
+
description: "Optional custom path to config file relative to project root."
|
|
140
|
+
} }
|
|
141
|
+
},
|
|
142
|
+
async handler(root, args) {
|
|
143
|
+
const parsed = z.object({ config: z.string().optional() }).parse(args);
|
|
144
|
+
const project = await loadStaticProject(root, parsed.config);
|
|
145
|
+
const dicts = project.dictionaries.map((d) => ({
|
|
146
|
+
name: d.name,
|
|
147
|
+
file: d.rel,
|
|
148
|
+
locales: listLocales(d.df),
|
|
149
|
+
complete: d.df.complete
|
|
150
|
+
}));
|
|
151
|
+
return { content: [{
|
|
152
|
+
type: "text",
|
|
153
|
+
text: JSON.stringify({
|
|
154
|
+
dictionaries: dicts,
|
|
155
|
+
unsupported: project.unsupported,
|
|
156
|
+
notes: project.notes
|
|
157
|
+
}, null, 2)
|
|
158
|
+
}] };
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
name: "dialex_get_dictionary",
|
|
163
|
+
description: "Get leaf keys and values for a specific dictionary or all dictionaries, optionally filtered by locale.",
|
|
164
|
+
inputSchema: {
|
|
165
|
+
type: "object",
|
|
166
|
+
properties: {
|
|
167
|
+
name: {
|
|
168
|
+
type: "string",
|
|
169
|
+
description: "Dictionary name (e.g. 'home' or 'auth'). If omitted, returns all dictionaries."
|
|
170
|
+
},
|
|
171
|
+
locale: {
|
|
172
|
+
type: "string",
|
|
173
|
+
description: "Locale to retrieve (e.g. 'en' or 'tr'). If omitted, returns all locales."
|
|
174
|
+
},
|
|
175
|
+
config: {
|
|
176
|
+
type: "string",
|
|
177
|
+
description: "Optional custom path to config file."
|
|
139
178
|
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
description: "Optional custom path to config file."
|
|
158
|
-
}
|
|
159
|
-
}
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
async handler(root, args) {
|
|
182
|
+
const parsed = z.object({
|
|
183
|
+
name: z.string().optional(),
|
|
184
|
+
locale: z.string().optional(),
|
|
185
|
+
config: z.string().optional()
|
|
186
|
+
}).parse(args);
|
|
187
|
+
const project = await loadStaticProject(root, parsed.config);
|
|
188
|
+
const result = {};
|
|
189
|
+
for (const d of project.dictionaries) {
|
|
190
|
+
if (parsed.name && d.name !== parsed.name) continue;
|
|
191
|
+
result[d.name] = {};
|
|
192
|
+
const locales = listLocales(d.df);
|
|
193
|
+
for (const loc of locales) {
|
|
194
|
+
if (parsed.locale && loc !== parsed.locale) continue;
|
|
195
|
+
result[d.name][loc] = listLeaves(d.df, loc);
|
|
160
196
|
}
|
|
161
|
-
}
|
|
162
|
-
{
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
197
|
+
}
|
|
198
|
+
return { content: [{
|
|
199
|
+
type: "text",
|
|
200
|
+
text: JSON.stringify(result, null, 2)
|
|
201
|
+
}] };
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
name: "dialex_check",
|
|
206
|
+
description: "Analyze project statically to verify dictionary key parity, ICU arguments, and source code references without executing project code.",
|
|
207
|
+
inputSchema: {
|
|
208
|
+
type: "object",
|
|
209
|
+
properties: {
|
|
210
|
+
src: {
|
|
211
|
+
type: "array",
|
|
212
|
+
items: { type: "string" },
|
|
213
|
+
description: "Optional source file globs to scan for dictionary references."
|
|
214
|
+
},
|
|
215
|
+
config: {
|
|
216
|
+
type: "string",
|
|
217
|
+
description: "Optional custom path to config file."
|
|
178
218
|
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
async handler(root, args) {
|
|
222
|
+
const parsed = z.object({
|
|
223
|
+
src: z.array(z.string()).optional(),
|
|
224
|
+
config: z.string().optional()
|
|
225
|
+
}).parse(args);
|
|
226
|
+
const staticConf = readStaticConfig(root, parsed.config);
|
|
227
|
+
const analysis = await analyzeProject({
|
|
228
|
+
root,
|
|
229
|
+
config: staticConf.config,
|
|
230
|
+
src: parsed.src,
|
|
231
|
+
runtime: false
|
|
232
|
+
});
|
|
233
|
+
return { content: [{
|
|
234
|
+
type: "text",
|
|
235
|
+
text: JSON.stringify({
|
|
236
|
+
issues: analysis.issues.map((i) => ({
|
|
237
|
+
...i,
|
|
238
|
+
file: path.relative(root, i.file)
|
|
239
|
+
})),
|
|
240
|
+
totalIssues: analysis.issues.filter((i) => i.level === "error").length,
|
|
241
|
+
totalWarnings: analysis.issues.filter((i) => i.level === "warning").length,
|
|
242
|
+
filesScanned: analysis.sourceFilesScanned
|
|
243
|
+
}, null, 2)
|
|
244
|
+
}] };
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
name: "dialex_find_usages",
|
|
249
|
+
description: "Scan source files for dictionary usages (e.g. getDictionary('home') or t('home.title')).",
|
|
250
|
+
inputSchema: {
|
|
251
|
+
type: "object",
|
|
252
|
+
properties: { file: {
|
|
253
|
+
type: "string",
|
|
254
|
+
description: "Relative or absolute file path to scan for references."
|
|
255
|
+
} },
|
|
256
|
+
required: ["file"]
|
|
257
|
+
},
|
|
258
|
+
async handler(root, args) {
|
|
259
|
+
const parsed = z.object({ file: z.string() }).parse(args);
|
|
260
|
+
const filePath = path.isAbsolute(parsed.file) ? parsed.file : path.resolve(root, parsed.file);
|
|
261
|
+
const fs = await import("node:fs");
|
|
262
|
+
if (!fs.existsSync(filePath)) throw new Error(`File not found: ${parsed.file}`);
|
|
263
|
+
const text = fs.readFileSync(filePath, "utf-8");
|
|
264
|
+
const refs = scanReferences(text);
|
|
265
|
+
return { content: [{
|
|
266
|
+
type: "text",
|
|
267
|
+
text: JSON.stringify({
|
|
268
|
+
file: path.relative(root, filePath),
|
|
269
|
+
references: refs
|
|
270
|
+
}, null, 2)
|
|
271
|
+
}] };
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
name: "dialex_missing",
|
|
276
|
+
description: "List missing keys, keys marked with [TODO] placeholders, and stale translations (the source text changed after they were translated, per dialex.lock.json) across locales.",
|
|
277
|
+
inputSchema: {
|
|
278
|
+
type: "object",
|
|
279
|
+
properties: {
|
|
280
|
+
locale: {
|
|
281
|
+
type: "string",
|
|
282
|
+
description: "Filter missing keys to a specific target locale."
|
|
283
|
+
},
|
|
284
|
+
config: {
|
|
285
|
+
type: "string",
|
|
286
|
+
description: "Optional custom path to config file."
|
|
190
287
|
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
async handler(root, args) {
|
|
291
|
+
const parsed = z.object({
|
|
292
|
+
locale: z.string().optional(),
|
|
293
|
+
config: z.string().optional()
|
|
294
|
+
}).parse(args);
|
|
295
|
+
const project = await loadStaticProject(root, parsed.config);
|
|
296
|
+
const defaultLocale = project.config.defaultLocale || "en";
|
|
297
|
+
const missingItems = [];
|
|
298
|
+
const configuredLocales = new Set(project.config.locales || []);
|
|
299
|
+
const lock = readLock(root);
|
|
300
|
+
for (const d of project.dictionaries) {
|
|
301
|
+
const localesInDict = new Set(listLocales(d.df));
|
|
302
|
+
const allLocales = /* @__PURE__ */ new Set([...localesInDict, ...configuredLocales]);
|
|
303
|
+
const defaultLeaves = listLeaves(d.df, defaultLocale);
|
|
304
|
+
const defaultMap = new Map(defaultLeaves.map((l) => [l.path.join("."), l.value]));
|
|
305
|
+
for (const loc of allLocales) {
|
|
306
|
+
if (loc === defaultLocale) continue;
|
|
307
|
+
if (parsed.locale && loc !== parsed.locale) continue;
|
|
308
|
+
const leaves = listLeaves(d.df, loc);
|
|
309
|
+
const leafMap = new Map(leaves.map((l) => [l.path.join("."), l]));
|
|
310
|
+
for (const defLeaf of defaultLeaves) {
|
|
311
|
+
const pathKey = defLeaf.path.join(".");
|
|
312
|
+
const curr = leafMap.get(pathKey);
|
|
313
|
+
if (!curr) missingItems.push({
|
|
314
|
+
dictionary: d.name,
|
|
315
|
+
file: d.rel,
|
|
316
|
+
locale: loc,
|
|
317
|
+
path: defLeaf.path,
|
|
318
|
+
key: `${d.name}.${pathKey}`,
|
|
319
|
+
status: "missing",
|
|
320
|
+
defaultValue: defLeaf.value
|
|
321
|
+
});
|
|
322
|
+
else if (curr.kind === "string" && curr.value?.startsWith(TODO_PREFIX)) missingItems.push({
|
|
323
|
+
dictionary: d.name,
|
|
324
|
+
file: d.rel,
|
|
325
|
+
locale: loc,
|
|
326
|
+
path: defLeaf.path,
|
|
327
|
+
key: `${d.name}.${pathKey}`,
|
|
328
|
+
status: "todo",
|
|
329
|
+
currentValue: curr.value,
|
|
330
|
+
defaultValue: defaultMap.get(pathKey)
|
|
331
|
+
});
|
|
206
332
|
}
|
|
207
333
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
},
|
|
232
|
-
overwrite: {
|
|
233
|
-
type: "boolean",
|
|
234
|
-
description: "Must be set to true to overwrite an existing translated value that is not marked [TODO]. Defaults to false."
|
|
334
|
+
if (lock?.sourceLocale) {
|
|
335
|
+
const sourceLeaves = new Map(listLeaves(d.df, lock.sourceLocale).map((l) => [l.path.join("."), l]));
|
|
336
|
+
for (const loc of allLocales) {
|
|
337
|
+
if (loc === lock.sourceLocale) continue;
|
|
338
|
+
if (parsed.locale && loc !== parsed.locale) continue;
|
|
339
|
+
for (const leaf of listLeaves(d.df, loc)) {
|
|
340
|
+
if (leaf.kind !== "string" || leaf.value === void 0) continue;
|
|
341
|
+
if (leaf.value.startsWith(TODO_PREFIX)) continue;
|
|
342
|
+
const pathKey = leaf.path.join(".");
|
|
343
|
+
const source = sourceLeaves.get(pathKey);
|
|
344
|
+
if (source?.kind !== "string" || source.value === void 0) continue;
|
|
345
|
+
const key = `${d.name}.${pathKey}`;
|
|
346
|
+
if (!isStale(lock, loc, key, source.value)) continue;
|
|
347
|
+
missingItems.push({
|
|
348
|
+
dictionary: d.name,
|
|
349
|
+
file: d.rel,
|
|
350
|
+
locale: loc,
|
|
351
|
+
path: leaf.path,
|
|
352
|
+
key,
|
|
353
|
+
status: "stale",
|
|
354
|
+
currentValue: leaf.value,
|
|
355
|
+
defaultValue: source.value
|
|
356
|
+
});
|
|
235
357
|
}
|
|
236
|
-
}
|
|
237
|
-
required: [
|
|
238
|
-
"file",
|
|
239
|
-
"locale",
|
|
240
|
-
"path",
|
|
241
|
-
"value"
|
|
242
|
-
]
|
|
358
|
+
}
|
|
243
359
|
}
|
|
244
|
-
}
|
|
245
|
-
{
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
360
|
+
}
|
|
361
|
+
return { content: [{
|
|
362
|
+
type: "text",
|
|
363
|
+
text: JSON.stringify({
|
|
364
|
+
missingCount: missingItems.length,
|
|
365
|
+
items: missingItems
|
|
366
|
+
}, null, 2)
|
|
367
|
+
}] };
|
|
368
|
+
}
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
name: "dialex_set_key",
|
|
372
|
+
description: "Safely set or update a translation string in a dictionary file using AST manipulation without executing project code or destroying comments/formatting. Refuses to overwrite non-[TODO] values unless overwrite is explicitly true.",
|
|
373
|
+
inputSchema: {
|
|
374
|
+
type: "object",
|
|
375
|
+
properties: {
|
|
376
|
+
file: {
|
|
377
|
+
type: "string",
|
|
378
|
+
description: "Dictionary file path (e.g. 'src/home.content.ts' or absolute path)."
|
|
379
|
+
},
|
|
380
|
+
locale: {
|
|
381
|
+
type: "string",
|
|
382
|
+
description: "Locale to update (e.g. 'tr')."
|
|
383
|
+
},
|
|
384
|
+
path: {
|
|
385
|
+
type: "array",
|
|
386
|
+
items: { type: "string" },
|
|
387
|
+
description: "Key path segments (e.g. ['nav', 'about'] or ['title'])."
|
|
388
|
+
},
|
|
389
|
+
value: {
|
|
390
|
+
type: "string",
|
|
391
|
+
description: "The translated string value to set."
|
|
392
|
+
},
|
|
393
|
+
overwrite: {
|
|
394
|
+
type: "boolean",
|
|
395
|
+
description: "Must be set to true to overwrite an existing translated value that is not marked [TODO]. Defaults to false."
|
|
254
396
|
}
|
|
255
397
|
},
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
398
|
+
required: [
|
|
399
|
+
"file",
|
|
400
|
+
"locale",
|
|
401
|
+
"path",
|
|
402
|
+
"value"
|
|
403
|
+
]
|
|
404
|
+
},
|
|
405
|
+
async handler(root, args) {
|
|
406
|
+
const parsed = z.object({
|
|
407
|
+
file: z.string(),
|
|
408
|
+
locale: z.string(),
|
|
409
|
+
path: z.array(z.string()),
|
|
410
|
+
value: z.string(),
|
|
411
|
+
overwrite: z.boolean().optional()
|
|
412
|
+
}).parse(args);
|
|
413
|
+
const filePath = path.isAbsolute(parsed.file) ? parsed.file : path.resolve(root, parsed.file);
|
|
414
|
+
const df = await loadDictionaryFile(filePath);
|
|
415
|
+
if (!df) throw new Error(`Cannot load dictionary file at ${parsed.file} (unsupported shape or syntax error)`);
|
|
416
|
+
const existingVal = getString(df, parsed.locale, parsed.path);
|
|
417
|
+
const isTodo = existingVal?.startsWith(TODO_PREFIX);
|
|
418
|
+
if (existingVal !== void 0 && !isTodo && !parsed.overwrite) throw new Error(`Key "${parsed.path.join(".")}" in locale "${parsed.locale}" already has a translated value (${JSON.stringify(existingVal)}). Set overwrite: true to overwrite.`);
|
|
419
|
+
const res = setString(df, parsed.locale, parsed.path, parsed.value);
|
|
420
|
+
if (res === "skipped") throw new Error(`Cannot set string at "${parsed.path.join(".")}" in "${parsed.locale}": target is a function or non-string node.`);
|
|
421
|
+
await saveDictionaryFile(df);
|
|
422
|
+
return { content: [{
|
|
423
|
+
type: "text",
|
|
424
|
+
text: JSON.stringify({
|
|
425
|
+
success: true,
|
|
426
|
+
action: res,
|
|
427
|
+
file: path.relative(root, filePath),
|
|
428
|
+
locale: parsed.locale,
|
|
429
|
+
path: parsed.path,
|
|
430
|
+
value: parsed.value
|
|
431
|
+
}, null, 2)
|
|
432
|
+
}] };
|
|
433
|
+
}
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
name: "dialex_add_missing",
|
|
437
|
+
description: "Automatically insert missing keys across all locales as [TODO] placeholders copied from default locale values (AST safe edits).",
|
|
438
|
+
inputSchema: {
|
|
439
|
+
type: "object",
|
|
440
|
+
properties: { config: {
|
|
441
|
+
type: "string",
|
|
442
|
+
description: "Optional custom path to config file."
|
|
443
|
+
} }
|
|
444
|
+
},
|
|
445
|
+
async handler(root, args) {
|
|
446
|
+
const parsed = z.object({ config: z.string().optional() }).parse(args);
|
|
447
|
+
const project = await loadStaticProject(root, parsed.config);
|
|
448
|
+
const defaultLocale = project.config.defaultLocale || "en";
|
|
449
|
+
const configuredLocales = project.config.locales || [];
|
|
450
|
+
let totalFixed = 0;
|
|
451
|
+
for (const d of project.dictionaries) {
|
|
452
|
+
if (!d.df.complete) continue;
|
|
453
|
+
const present = listLocales(d.df);
|
|
454
|
+
const targets = Array.from(/* @__PURE__ */ new Set([...present, ...configuredLocales]));
|
|
455
|
+
const sourceOrder = [defaultLocale, ...present.filter((l) => l !== defaultLocale)].filter((l) => present.includes(l));
|
|
456
|
+
const allPaths = /* @__PURE__ */ new Map();
|
|
457
|
+
for (const locale of present) for (const leaf of listLeaves(d.df, locale)) allPaths.set(leaf.path.join("\0"), leaf.path);
|
|
458
|
+
let changed = false;
|
|
459
|
+
for (const target of targets) for (const leafPath of allPaths.values()) {
|
|
460
|
+
if (hasPath(d.df, target, leafPath)) continue;
|
|
461
|
+
const source = sourceOrder.find((l) => l !== target && hasPath(d.df, l, leafPath));
|
|
462
|
+
if (source && copyLeaf(d.df, source, target, leafPath, (v) => `${TODO_PREFIX}${v}`)) {
|
|
463
|
+
totalFixed++;
|
|
464
|
+
changed = true;
|
|
270
465
|
}
|
|
271
466
|
}
|
|
467
|
+
if (changed) await saveDictionaryFile(d.df);
|
|
272
468
|
}
|
|
273
|
-
|
|
469
|
+
return { content: [{
|
|
470
|
+
type: "text",
|
|
471
|
+
text: JSON.stringify({
|
|
472
|
+
success: true,
|
|
473
|
+
fixed: totalFixed
|
|
474
|
+
}, null, 2)
|
|
475
|
+
}] };
|
|
476
|
+
}
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
name: "dialex_generate",
|
|
480
|
+
description: "Run code generation to build standalone dictionary registry and TypeScript declarations.",
|
|
481
|
+
inputSchema: {
|
|
482
|
+
type: "object",
|
|
483
|
+
properties: {
|
|
484
|
+
output: {
|
|
485
|
+
type: "string",
|
|
486
|
+
description: "Optional custom output path for dialex.generated.ts."
|
|
487
|
+
},
|
|
488
|
+
config: {
|
|
489
|
+
type: "string",
|
|
490
|
+
description: "Optional custom path to config file."
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
},
|
|
494
|
+
async handler(root, args) {
|
|
495
|
+
const parsed = z.object({
|
|
496
|
+
output: z.string().optional(),
|
|
497
|
+
config: z.string().optional()
|
|
498
|
+
}).parse(args);
|
|
499
|
+
const res = generateDictionaries(root, {
|
|
500
|
+
output: parsed.output,
|
|
501
|
+
config: parsed.config
|
|
502
|
+
});
|
|
503
|
+
return { content: [{
|
|
504
|
+
type: "text",
|
|
505
|
+
text: JSON.stringify({
|
|
506
|
+
success: true,
|
|
507
|
+
files: res.files.map((f) => path.relative(root, f)),
|
|
508
|
+
outputPath: path.relative(root, res.outputPath),
|
|
509
|
+
dtsPath: path.relative(root, res.dtsPath)
|
|
510
|
+
}, null, 2)
|
|
511
|
+
}] };
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
];
|
|
515
|
+
//#endregion
|
|
516
|
+
//#region src/server.ts
|
|
517
|
+
function createDialexMcpServer(options = {}) {
|
|
518
|
+
const getRoot = () => path.resolve(options.root || process.cwd());
|
|
519
|
+
const server = new Server({
|
|
520
|
+
name: "dialex",
|
|
521
|
+
version
|
|
522
|
+
}, { capabilities: {
|
|
523
|
+
tools: {},
|
|
524
|
+
resources: {}
|
|
525
|
+
} });
|
|
526
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => listDocResources());
|
|
527
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => readDocResource(request.params.uri));
|
|
528
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
529
|
+
return { tools: TOOLS.map(({ name, description, inputSchema }) => ({
|
|
530
|
+
name,
|
|
531
|
+
description,
|
|
532
|
+
inputSchema
|
|
533
|
+
})) };
|
|
274
534
|
});
|
|
275
535
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
276
536
|
const root = getRoot();
|
|
277
537
|
const { name, arguments: args = {} } = request.params;
|
|
278
538
|
try {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
const staticConf = readStaticConfig(root, parsed.config);
|
|
283
|
-
return { content: [{
|
|
284
|
-
type: "text",
|
|
285
|
-
text: JSON.stringify(staticConf, null, 2)
|
|
286
|
-
}] };
|
|
287
|
-
}
|
|
288
|
-
case "dialex_list_dictionaries": {
|
|
289
|
-
const parsed = z.object({ config: z.string().optional() }).parse(args);
|
|
290
|
-
const project = await loadStaticProject(root, parsed.config);
|
|
291
|
-
const dicts = project.dictionaries.map((d) => ({
|
|
292
|
-
name: d.name,
|
|
293
|
-
file: d.rel,
|
|
294
|
-
locales: listLocales(d.df),
|
|
295
|
-
complete: d.df.complete
|
|
296
|
-
}));
|
|
297
|
-
return { content: [{
|
|
298
|
-
type: "text",
|
|
299
|
-
text: JSON.stringify({
|
|
300
|
-
dictionaries: dicts,
|
|
301
|
-
unsupported: project.unsupported,
|
|
302
|
-
notes: project.notes
|
|
303
|
-
}, null, 2)
|
|
304
|
-
}] };
|
|
305
|
-
}
|
|
306
|
-
case "dialex_get_dictionary": {
|
|
307
|
-
const parsed = z.object({
|
|
308
|
-
name: z.string().optional(),
|
|
309
|
-
locale: z.string().optional(),
|
|
310
|
-
config: z.string().optional()
|
|
311
|
-
}).parse(args);
|
|
312
|
-
const project = await loadStaticProject(root, parsed.config);
|
|
313
|
-
const result = {};
|
|
314
|
-
for (const d of project.dictionaries) {
|
|
315
|
-
if (parsed.name && d.name !== parsed.name) continue;
|
|
316
|
-
result[d.name] = {};
|
|
317
|
-
const locales = listLocales(d.df);
|
|
318
|
-
for (const loc of locales) {
|
|
319
|
-
if (parsed.locale && loc !== parsed.locale) continue;
|
|
320
|
-
result[d.name][loc] = listLeaves(d.df, loc);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
return { content: [{
|
|
324
|
-
type: "text",
|
|
325
|
-
text: JSON.stringify(result, null, 2)
|
|
326
|
-
}] };
|
|
327
|
-
}
|
|
328
|
-
case "dialex_check": {
|
|
329
|
-
const parsed = z.object({
|
|
330
|
-
src: z.array(z.string()).optional(),
|
|
331
|
-
config: z.string().optional()
|
|
332
|
-
}).parse(args);
|
|
333
|
-
const staticConf = readStaticConfig(root, parsed.config);
|
|
334
|
-
const analysis = await analyzeProject({
|
|
335
|
-
root,
|
|
336
|
-
config: staticConf.config,
|
|
337
|
-
src: parsed.src,
|
|
338
|
-
runtime: false
|
|
339
|
-
});
|
|
340
|
-
return { content: [{
|
|
341
|
-
type: "text",
|
|
342
|
-
text: JSON.stringify({
|
|
343
|
-
issues: analysis.issues.map((i) => ({
|
|
344
|
-
...i,
|
|
345
|
-
file: path.relative(root, i.file)
|
|
346
|
-
})),
|
|
347
|
-
totalIssues: analysis.issues.filter((i) => i.level === "error").length,
|
|
348
|
-
totalWarnings: analysis.issues.filter((i) => i.level === "warning").length,
|
|
349
|
-
filesScanned: analysis.sourceFilesScanned
|
|
350
|
-
}, null, 2)
|
|
351
|
-
}] };
|
|
352
|
-
}
|
|
353
|
-
case "dialex_find_usages": {
|
|
354
|
-
const parsed = z.object({ file: z.string() }).parse(args);
|
|
355
|
-
const filePath = path.isAbsolute(parsed.file) ? parsed.file : path.resolve(root, parsed.file);
|
|
356
|
-
const fs = await import("node:fs");
|
|
357
|
-
if (!fs.existsSync(filePath)) throw new Error(`File not found: ${parsed.file}`);
|
|
358
|
-
const text = fs.readFileSync(filePath, "utf-8");
|
|
359
|
-
const refs = scanReferences(text);
|
|
360
|
-
return { content: [{
|
|
361
|
-
type: "text",
|
|
362
|
-
text: JSON.stringify({
|
|
363
|
-
file: path.relative(root, filePath),
|
|
364
|
-
references: refs
|
|
365
|
-
}, null, 2)
|
|
366
|
-
}] };
|
|
367
|
-
}
|
|
368
|
-
case "dialex_missing": {
|
|
369
|
-
const parsed = z.object({
|
|
370
|
-
locale: z.string().optional(),
|
|
371
|
-
config: z.string().optional()
|
|
372
|
-
}).parse(args);
|
|
373
|
-
const project = await loadStaticProject(root, parsed.config);
|
|
374
|
-
const defaultLocale = project.config.defaultLocale || "en";
|
|
375
|
-
const missingItems = [];
|
|
376
|
-
const configuredLocales = new Set(project.config.locales || []);
|
|
377
|
-
const lock = readLock(root);
|
|
378
|
-
for (const d of project.dictionaries) {
|
|
379
|
-
const localesInDict = new Set(listLocales(d.df));
|
|
380
|
-
const allLocales = /* @__PURE__ */ new Set([...localesInDict, ...configuredLocales]);
|
|
381
|
-
const defaultLeaves = listLeaves(d.df, defaultLocale);
|
|
382
|
-
const defaultMap = new Map(defaultLeaves.map((l) => [l.path.join("."), l.value]));
|
|
383
|
-
for (const loc of allLocales) {
|
|
384
|
-
if (loc === defaultLocale) continue;
|
|
385
|
-
if (parsed.locale && loc !== parsed.locale) continue;
|
|
386
|
-
const leaves = listLeaves(d.df, loc);
|
|
387
|
-
const leafMap = new Map(leaves.map((l) => [l.path.join("."), l]));
|
|
388
|
-
for (const defLeaf of defaultLeaves) {
|
|
389
|
-
const pathKey = defLeaf.path.join(".");
|
|
390
|
-
const curr = leafMap.get(pathKey);
|
|
391
|
-
if (!curr) missingItems.push({
|
|
392
|
-
dictionary: d.name,
|
|
393
|
-
file: d.rel,
|
|
394
|
-
locale: loc,
|
|
395
|
-
path: defLeaf.path,
|
|
396
|
-
key: `${d.name}.${pathKey}`,
|
|
397
|
-
status: "missing",
|
|
398
|
-
defaultValue: defLeaf.value
|
|
399
|
-
});
|
|
400
|
-
else if (curr.kind === "string" && curr.value?.startsWith(TODO_PREFIX)) missingItems.push({
|
|
401
|
-
dictionary: d.name,
|
|
402
|
-
file: d.rel,
|
|
403
|
-
locale: loc,
|
|
404
|
-
path: defLeaf.path,
|
|
405
|
-
key: `${d.name}.${pathKey}`,
|
|
406
|
-
status: "todo",
|
|
407
|
-
currentValue: curr.value,
|
|
408
|
-
defaultValue: defaultMap.get(pathKey)
|
|
409
|
-
});
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
if (lock?.sourceLocale) {
|
|
413
|
-
const sourceLeaves = new Map(listLeaves(d.df, lock.sourceLocale).map((l) => [l.path.join("."), l]));
|
|
414
|
-
for (const loc of allLocales) {
|
|
415
|
-
if (loc === lock.sourceLocale) continue;
|
|
416
|
-
if (parsed.locale && loc !== parsed.locale) continue;
|
|
417
|
-
for (const leaf of listLeaves(d.df, loc)) {
|
|
418
|
-
if (leaf.kind !== "string" || leaf.value === void 0) continue;
|
|
419
|
-
if (leaf.value.startsWith(TODO_PREFIX)) continue;
|
|
420
|
-
const pathKey = leaf.path.join(".");
|
|
421
|
-
const source = sourceLeaves.get(pathKey);
|
|
422
|
-
if (source?.kind !== "string" || source.value === void 0) continue;
|
|
423
|
-
const key = `${d.name}.${pathKey}`;
|
|
424
|
-
if (!isStale(lock, loc, key, source.value)) continue;
|
|
425
|
-
missingItems.push({
|
|
426
|
-
dictionary: d.name,
|
|
427
|
-
file: d.rel,
|
|
428
|
-
locale: loc,
|
|
429
|
-
path: leaf.path,
|
|
430
|
-
key,
|
|
431
|
-
status: "stale",
|
|
432
|
-
currentValue: leaf.value,
|
|
433
|
-
defaultValue: source.value
|
|
434
|
-
});
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
return { content: [{
|
|
440
|
-
type: "text",
|
|
441
|
-
text: JSON.stringify({
|
|
442
|
-
missingCount: missingItems.length,
|
|
443
|
-
items: missingItems
|
|
444
|
-
}, null, 2)
|
|
445
|
-
}] };
|
|
446
|
-
}
|
|
447
|
-
case "dialex_set_key": {
|
|
448
|
-
const parsed = z.object({
|
|
449
|
-
file: z.string(),
|
|
450
|
-
locale: z.string(),
|
|
451
|
-
path: z.array(z.string()),
|
|
452
|
-
value: z.string(),
|
|
453
|
-
overwrite: z.boolean().optional()
|
|
454
|
-
}).parse(args);
|
|
455
|
-
const filePath = path.isAbsolute(parsed.file) ? parsed.file : path.resolve(root, parsed.file);
|
|
456
|
-
const df = await loadDictionaryFile(filePath);
|
|
457
|
-
if (!df) throw new Error(`Cannot load dictionary file at ${parsed.file} (unsupported shape or syntax error)`);
|
|
458
|
-
const existingVal = getString(df, parsed.locale, parsed.path);
|
|
459
|
-
const isTodo = existingVal?.startsWith(TODO_PREFIX);
|
|
460
|
-
if (existingVal !== void 0 && !isTodo && !parsed.overwrite) throw new Error(`Key "${parsed.path.join(".")}" in locale "${parsed.locale}" already has a translated value (${JSON.stringify(existingVal)}). Set overwrite: true to overwrite.`);
|
|
461
|
-
const res = setString(df, parsed.locale, parsed.path, parsed.value);
|
|
462
|
-
if (res === "skipped") throw new Error(`Cannot set string at "${parsed.path.join(".")}" in "${parsed.locale}": target is a function or non-string node.`);
|
|
463
|
-
await saveDictionaryFile(df);
|
|
464
|
-
return { content: [{
|
|
465
|
-
type: "text",
|
|
466
|
-
text: JSON.stringify({
|
|
467
|
-
success: true,
|
|
468
|
-
action: res,
|
|
469
|
-
file: path.relative(root, filePath),
|
|
470
|
-
locale: parsed.locale,
|
|
471
|
-
path: parsed.path,
|
|
472
|
-
value: parsed.value
|
|
473
|
-
}, null, 2)
|
|
474
|
-
}] };
|
|
475
|
-
}
|
|
476
|
-
case "dialex_add_missing": {
|
|
477
|
-
const parsed = z.object({ config: z.string().optional() }).parse(args);
|
|
478
|
-
const project = await loadStaticProject(root, parsed.config);
|
|
479
|
-
const defaultLocale = project.config.defaultLocale || "en";
|
|
480
|
-
const configuredLocales = project.config.locales || [];
|
|
481
|
-
let totalFixed = 0;
|
|
482
|
-
for (const d of project.dictionaries) {
|
|
483
|
-
if (!d.df.complete) continue;
|
|
484
|
-
const present = listLocales(d.df);
|
|
485
|
-
const targets = Array.from(/* @__PURE__ */ new Set([...present, ...configuredLocales]));
|
|
486
|
-
const sourceOrder = [defaultLocale, ...present.filter((l) => l !== defaultLocale)].filter((l) => present.includes(l));
|
|
487
|
-
const allPaths = /* @__PURE__ */ new Map();
|
|
488
|
-
for (const locale of present) for (const leaf of listLeaves(d.df, locale)) allPaths.set(leaf.path.join("\0"), leaf.path);
|
|
489
|
-
let changed = false;
|
|
490
|
-
for (const target of targets) for (const leafPath of allPaths.values()) {
|
|
491
|
-
if (hasPath(d.df, target, leafPath)) continue;
|
|
492
|
-
const source = sourceOrder.find((l) => l !== target && hasPath(d.df, l, leafPath));
|
|
493
|
-
if (source && copyLeaf(d.df, source, target, leafPath, (v) => `${TODO_PREFIX}${v}`)) {
|
|
494
|
-
totalFixed++;
|
|
495
|
-
changed = true;
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
if (changed) await saveDictionaryFile(d.df);
|
|
499
|
-
}
|
|
500
|
-
return { content: [{
|
|
501
|
-
type: "text",
|
|
502
|
-
text: JSON.stringify({
|
|
503
|
-
success: true,
|
|
504
|
-
fixed: totalFixed
|
|
505
|
-
}, null, 2)
|
|
506
|
-
}] };
|
|
507
|
-
}
|
|
508
|
-
case "dialex_generate": {
|
|
509
|
-
const parsed = z.object({
|
|
510
|
-
output: z.string().optional(),
|
|
511
|
-
config: z.string().optional()
|
|
512
|
-
}).parse(args);
|
|
513
|
-
const res = generateDictionaries(root, {
|
|
514
|
-
output: parsed.output,
|
|
515
|
-
config: parsed.config
|
|
516
|
-
});
|
|
517
|
-
return { content: [{
|
|
518
|
-
type: "text",
|
|
519
|
-
text: JSON.stringify({
|
|
520
|
-
success: true,
|
|
521
|
-
files: res.files.map((f) => path.relative(root, f)),
|
|
522
|
-
outputPath: path.relative(root, res.outputPath),
|
|
523
|
-
dtsPath: path.relative(root, res.dtsPath)
|
|
524
|
-
}, null, 2)
|
|
525
|
-
}] };
|
|
526
|
-
}
|
|
527
|
-
default: throw new Error(`Unknown tool: ${name}`);
|
|
528
|
-
}
|
|
539
|
+
const tool = TOOLS.find((candidate) => candidate.name === name);
|
|
540
|
+
if (!tool) throw new Error(`Unknown tool: ${name}`);
|
|
541
|
+
return await tool.handler(root, args);
|
|
529
542
|
} catch (err) {
|
|
530
543
|
return {
|
|
531
544
|
isError: true,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["pkg.version"],"sources":["../package.json","../src/docs.ts","../src/server.ts","../src/index.ts"],"sourcesContent":["","export const DIALEX_GUIDE_DOC = `# Dialex Internationalization Guide\n\nDialex is a high-performance, type-safe internationalization toolchain for JavaScript and TypeScript.\n\n## Key Features\n- **Zero Runtime Overhead**: Dictionaries are statically compiled.\n- **Strict Parity**: Compile-time checking verifies that every key in your default locale exists in all configured locales.\n- **ICU MessageFormat**: Native plural and select format support ({count, plural, one {# item} other {# items}}).\n- **Universal Framework Support**: Native integrations for React, Next.js, Express, Fastify, Hono, Koa, NestJS, SvelteKit, Astro, Vue, and Nuxt.\n\n## Content Dictionaries (\\`*.content.ts\\`)\nDefined with \\`defineDictionary\\`:\n\\`\\`\\`ts\nimport { defineDictionary } from \"dialexjs\";\n\nexport default defineDictionary(\"home\", {\n en: {\n title: \"Welcome\",\n greeting: (name: string) => \\`Hello, \\${name}!\\`,\n items: \"{count, plural, one {# item} other {# items}}\",\n },\n tr: {\n title: \"Hoş Geldiniz\",\n greeting: (name: string) => \\`Merhaba, \\${name}!\\`,\n items: \"{count, plural, other {# öğe}}\",\n },\n});\n\\`\\`\\`\n\n## CLI & Tooling\n- \\`dialex check\\`: Parity checker. Use \\`--fix\\` to insert \\`[TODO]\\` stubs. Use \\`--json\\` for structured output.\n- \\`dialex generate\\`: Generates \\`dialex.generated.ts\\` and \\`dialex-env.d.ts\\`.\n- \\`dialex export\\` / \\`dialex import\\`: JSON, CSV, XLIFF interchange.\n- \\`dialex translate\\`: Fill missing keys with AI providers (Claude, OpenAI, Gemini, DeepL).\n`;\n\nexport const DIALEX_TRANSLATE_DOC = `# Dialex Translation Workflow\n\n## Missing Keys & Workflow\n1. Run \\`dialex check --json\\` to detect missing keys or parity discrepancies.\n2. Run \\`dialex check --fix\\` (or \\`dialex_add_missing\\` via MCP) to automatically insert \\`[TODO]\\` stubs for missing keys.\n3. Replace \\`[TODO]\\` entries with real translations using \\`dialex_set_key\\` via MCP or \\`dialex translate\\` via CLI.\n4. Verify with \\`dialex check\\` that all keys are translated and ICU placeholders match.\n`;\n\nexport const DIALEX_ICU_DOC = `# Dialex ICU MessageFormat Reference\n\n## Plurals\n\\`\\`\\`icu\n{count, plural,\n =0 {No notifications}\n one {# notification}\n other {# notifications}\n}\n\\`\\`\\`\n\n## Select\n\\`\\`\\`icu\n{gender, select,\n male {He updated his profile}\n female {She updated her profile}\n other {They updated their profile}\n}\n\\`\\`\\`\n\nAll locales for a given key must declare the exact same variable placeholders.\n`;\n\nexport const DIALEX_ADAPTERS_DOC = `# Dialex Adapters Reference\n\n- **React**: \\`useDictionary(\"name\")\\`, \\`useT()\\` with \\`DialexProvider\\`.\n- **Next.js App Router**: \\`getDictionary(\"name\", locale)\\` in Server Components.\n- **Express / Hono / Fastify**: Middleware injecting \\`getDictionary\\` or context variable into requests.\n`;\n\nexport const DOC_TOPICS: Record<string, string> = {\n guide: DIALEX_GUIDE_DOC,\n translate: DIALEX_TRANSLATE_DOC,\n icu: DIALEX_ICU_DOC,\n adapters: DIALEX_ADAPTERS_DOC,\n};\n","import path from \"node:path\";\n\nimport {\n analyzeProject,\n readStaticConfig,\n loadStaticProject,\n loadDictionaryFile,\n saveDictionaryFile,\n listLeaves,\n getString,\n setString,\n copyLeaf,\n scanReferences,\n generateDictionaries,\n TODO_PREFIX,\n hasPath,\n isStale,\n listLocales,\n readLock,\n} from \"@dialexjs/cli/api\";\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n ListResourcesRequestSchema,\n ReadResourceRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { z } from \"zod\";\n\nimport pkg from \"../package.json\" with { type: \"json\" };\nimport { DOC_TOPICS } from \"./docs.js\";\n\nexport function createDialexMcpServer(options: { root?: string } = {}) {\n const getRoot = () => path.resolve(options.root || process.cwd());\n\n const server = new Server(\n {\n name: \"dialex\",\n version: pkg.version,\n },\n {\n capabilities: {\n tools: {},\n resources: {},\n },\n },\n );\n\n server.setRequestHandler(ListResourcesRequestSchema, async () => {\n return {\n resources: Object.keys(DOC_TOPICS).map((topic) => ({\n uri: `dialex://docs/${topic}`,\n name: `Dialex Documentation: ${topic}`,\n mimeType: \"text/markdown\",\n description: `Reference documentation for Dialex ${topic}`,\n })),\n };\n });\n\n server.setRequestHandler(ReadResourceRequestSchema, async (request) => {\n const uri = request.params.uri;\n const match = /^dialex:\\/\\/docs\\/([a-zA-Z0-9_-]+)$/.exec(uri);\n if (!match) {\n throw new Error(`Invalid resource URI: ${uri}`);\n }\n const topic = match[1];\n const content = DOC_TOPICS[topic];\n if (!content) {\n throw new Error(`Documentation topic not found: ${topic}`);\n }\n return {\n contents: [\n {\n uri,\n mimeType: \"text/markdown\",\n text: content,\n },\n ],\n };\n });\n\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n return {\n tools: [\n {\n name: \"dialex_config\",\n description:\n \"Read static Dialex configuration (locales, defaultLocale, include pattern) from dialex.config.ts or i18n.config.ts without executing project code.\",\n inputSchema: {\n type: \"object\",\n properties: {\n config: {\n type: \"string\",\n description: \"Optional custom path to config file relative to project root.\",\n },\n },\n },\n },\n {\n name: \"dialex_list_dictionaries\",\n description:\n \"List all discovered content dictionaries, their files, and supported locales.\",\n inputSchema: {\n type: \"object\",\n properties: {\n config: {\n type: \"string\",\n description: \"Optional custom path to config file relative to project root.\",\n },\n },\n },\n },\n {\n name: \"dialex_get_dictionary\",\n description:\n \"Get leaf keys and values for a specific dictionary or all dictionaries, optionally filtered by locale.\",\n inputSchema: {\n type: \"object\",\n properties: {\n name: {\n type: \"string\",\n description:\n \"Dictionary name (e.g. 'home' or 'auth'). If omitted, returns all dictionaries.\",\n },\n locale: {\n type: \"string\",\n description:\n \"Locale to retrieve (e.g. 'en' or 'tr'). If omitted, returns all locales.\",\n },\n config: {\n type: \"string\",\n description: \"Optional custom path to config file.\",\n },\n },\n },\n },\n {\n name: \"dialex_check\",\n description:\n \"Analyze project statically to verify dictionary key parity, ICU arguments, and source code references without executing project code.\",\n inputSchema: {\n type: \"object\",\n properties: {\n src: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Optional source file globs to scan for dictionary references.\",\n },\n config: {\n type: \"string\",\n description: \"Optional custom path to config file.\",\n },\n },\n },\n },\n {\n name: \"dialex_find_usages\",\n description:\n \"Scan source files for dictionary usages (e.g. getDictionary('home') or t('home.title')).\",\n inputSchema: {\n type: \"object\",\n properties: {\n file: {\n type: \"string\",\n description: \"Relative or absolute file path to scan for references.\",\n },\n },\n required: [\"file\"],\n },\n },\n {\n name: \"dialex_missing\",\n description:\n \"List missing keys, keys marked with [TODO] placeholders, and stale translations (the source text changed after they were translated, per dialex.lock.json) across locales.\",\n inputSchema: {\n type: \"object\",\n properties: {\n locale: {\n type: \"string\",\n description: \"Filter missing keys to a specific target locale.\",\n },\n config: {\n type: \"string\",\n description: \"Optional custom path to config file.\",\n },\n },\n },\n },\n {\n name: \"dialex_set_key\",\n description:\n \"Safely set or update a translation string in a dictionary file using AST manipulation without executing project code or destroying comments/formatting. Refuses to overwrite non-[TODO] values unless overwrite is explicitly true.\",\n inputSchema: {\n type: \"object\",\n properties: {\n file: {\n type: \"string\",\n description: \"Dictionary file path (e.g. 'src/home.content.ts' or absolute path).\",\n },\n locale: {\n type: \"string\",\n description: \"Locale to update (e.g. 'tr').\",\n },\n path: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Key path segments (e.g. ['nav', 'about'] or ['title']).\",\n },\n value: {\n type: \"string\",\n description: \"The translated string value to set.\",\n },\n overwrite: {\n type: \"boolean\",\n description:\n \"Must be set to true to overwrite an existing translated value that is not marked [TODO]. Defaults to false.\",\n },\n },\n required: [\"file\", \"locale\", \"path\", \"value\"],\n },\n },\n {\n name: \"dialex_add_missing\",\n description:\n \"Automatically insert missing keys across all locales as [TODO] placeholders copied from default locale values (AST safe edits).\",\n inputSchema: {\n type: \"object\",\n properties: {\n config: {\n type: \"string\",\n description: \"Optional custom path to config file.\",\n },\n },\n },\n },\n {\n name: \"dialex_generate\",\n description:\n \"Run code generation to build standalone dictionary registry and TypeScript declarations.\",\n inputSchema: {\n type: \"object\",\n properties: {\n output: {\n type: \"string\",\n description: \"Optional custom output path for dialex.generated.ts.\",\n },\n config: {\n type: \"string\",\n description: \"Optional custom path to config file.\",\n },\n },\n },\n },\n ],\n };\n });\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const root = getRoot();\n const { name, arguments: args = {} } = request.params;\n\n try {\n switch (name) {\n case \"dialex_config\": {\n const schema = z.object({ config: z.string().optional() });\n const parsed = schema.parse(args);\n const staticConf = readStaticConfig(root, parsed.config);\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(staticConf, null, 2),\n },\n ],\n };\n }\n\n case \"dialex_list_dictionaries\": {\n const schema = z.object({ config: z.string().optional() });\n const parsed = schema.parse(args);\n const project = await loadStaticProject(root, parsed.config);\n const dicts = project.dictionaries.map((d) => ({\n name: d.name,\n file: d.rel,\n locales: listLocales(d.df),\n complete: d.df.complete,\n }));\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n dictionaries: dicts,\n unsupported: project.unsupported,\n notes: project.notes,\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n case \"dialex_get_dictionary\": {\n const schema = z.object({\n name: z.string().optional(),\n locale: z.string().optional(),\n config: z.string().optional(),\n });\n const parsed = schema.parse(args);\n const project = await loadStaticProject(root, parsed.config);\n\n const result: Record<\n string,\n Record<string, Array<{ path: string[]; kind: string; value?: string }>>\n > = {};\n\n for (const d of project.dictionaries) {\n if (parsed.name && d.name !== parsed.name) continue;\n result[d.name] = {};\n const locales = listLocales(d.df);\n for (const loc of locales) {\n if (parsed.locale && loc !== parsed.locale) continue;\n result[d.name][loc] = listLeaves(d.df, loc);\n }\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n }\n\n case \"dialex_check\": {\n const schema = z.object({\n src: z.array(z.string()).optional(),\n config: z.string().optional(),\n });\n const parsed = schema.parse(args);\n const staticConf = readStaticConfig(root, parsed.config);\n const analysis = await analyzeProject({\n root,\n config: staticConf.config,\n src: parsed.src,\n runtime: false,\n });\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n issues: analysis.issues.map((i) => ({\n ...i,\n file: path.relative(root, i.file),\n })),\n totalIssues: analysis.issues.filter((i) => i.level === \"error\").length,\n totalWarnings: analysis.issues.filter((i) => i.level === \"warning\").length,\n filesScanned: analysis.sourceFilesScanned,\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n case \"dialex_find_usages\": {\n const schema = z.object({ file: z.string() });\n const parsed = schema.parse(args);\n const filePath = path.isAbsolute(parsed.file)\n ? parsed.file\n : path.resolve(root, parsed.file);\n const fs = await import(\"node:fs\");\n if (!fs.existsSync(filePath)) {\n throw new Error(`File not found: ${parsed.file}`);\n }\n const text = fs.readFileSync(filePath, \"utf-8\");\n const refs = scanReferences(text);\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n { file: path.relative(root, filePath), references: refs },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n case \"dialex_missing\": {\n const schema = z.object({\n locale: z.string().optional(),\n config: z.string().optional(),\n });\n const parsed = schema.parse(args);\n const project = await loadStaticProject(root, parsed.config);\n const defaultLocale = project.config.defaultLocale || \"en\";\n\n const missingItems: Array<{\n dictionary: string;\n file: string;\n locale: string;\n path: string[];\n key: string;\n status: \"missing\" | \"todo\" | \"stale\";\n currentValue?: string;\n defaultValue?: string;\n }> = [];\n\n const configuredLocales = new Set(project.config.locales || []);\n const lock = readLock(root);\n\n for (const d of project.dictionaries) {\n const localesInDict = new Set(listLocales(d.df));\n const allLocales = new Set([...localesInDict, ...configuredLocales]);\n const defaultLeaves = listLeaves(d.df, defaultLocale);\n const defaultMap = new Map(defaultLeaves.map((l) => [l.path.join(\".\"), l.value]));\n\n for (const loc of allLocales) {\n if (loc === defaultLocale) continue;\n if (parsed.locale && loc !== parsed.locale) continue;\n\n const leaves = listLeaves(d.df, loc);\n const leafMap = new Map(leaves.map((l) => [l.path.join(\".\"), l]));\n\n for (const defLeaf of defaultLeaves) {\n const pathKey = defLeaf.path.join(\".\");\n const curr = leafMap.get(pathKey);\n if (!curr) {\n missingItems.push({\n dictionary: d.name,\n file: d.rel,\n locale: loc,\n path: defLeaf.path,\n key: `${d.name}.${pathKey}`,\n status: \"missing\",\n defaultValue: defLeaf.value,\n });\n } else if (curr.kind === \"string\" && curr.value?.startsWith(TODO_PREFIX)) {\n missingItems.push({\n dictionary: d.name,\n file: d.rel,\n locale: loc,\n path: defLeaf.path,\n key: `${d.name}.${pathKey}`,\n status: \"todo\",\n currentValue: curr.value,\n defaultValue: defaultMap.get(pathKey),\n });\n }\n }\n }\n\n // Translations whose source text changed since they were translated\n if (lock?.sourceLocale) {\n const sourceLeaves = new Map(\n listLeaves(d.df, lock.sourceLocale).map((l) => [l.path.join(\".\"), l]),\n );\n for (const loc of allLocales) {\n if (loc === lock.sourceLocale) continue;\n if (parsed.locale && loc !== parsed.locale) continue;\n for (const leaf of listLeaves(d.df, loc)) {\n if (leaf.kind !== \"string\" || leaf.value === undefined) continue;\n if (leaf.value.startsWith(TODO_PREFIX)) continue;\n const pathKey = leaf.path.join(\".\");\n const source = sourceLeaves.get(pathKey);\n if (source?.kind !== \"string\" || source.value === undefined) continue;\n const key = `${d.name}.${pathKey}`;\n if (!isStale(lock, loc, key, source.value)) continue;\n missingItems.push({\n dictionary: d.name,\n file: d.rel,\n locale: loc,\n path: leaf.path,\n key,\n status: \"stale\",\n currentValue: leaf.value,\n defaultValue: source.value,\n });\n }\n }\n }\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n { missingCount: missingItems.length, items: missingItems },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n case \"dialex_set_key\": {\n const schema = z.object({\n file: z.string(),\n locale: z.string(),\n path: z.array(z.string()),\n value: z.string(),\n overwrite: z.boolean().optional(),\n });\n const parsed = schema.parse(args);\n const filePath = path.isAbsolute(parsed.file)\n ? parsed.file\n : path.resolve(root, parsed.file);\n\n const df = await loadDictionaryFile(filePath);\n if (!df) {\n throw new Error(\n `Cannot load dictionary file at ${parsed.file} (unsupported shape or syntax error)`,\n );\n }\n\n const existingVal = getString(df, parsed.locale, parsed.path);\n const isTodo = existingVal?.startsWith(TODO_PREFIX);\n\n if (existingVal !== undefined && !isTodo && !parsed.overwrite) {\n throw new Error(\n `Key \"${parsed.path.join(\".\")}\" in locale \"${parsed.locale}\" already has a translated value (${JSON.stringify(existingVal)}). Set overwrite: true to overwrite.`,\n );\n }\n\n const res = setString(df, parsed.locale, parsed.path, parsed.value);\n if (res === \"skipped\") {\n throw new Error(\n `Cannot set string at \"${parsed.path.join(\".\")}\" in \"${parsed.locale}\": target is a function or non-string node.`,\n );\n }\n\n await saveDictionaryFile(df);\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n success: true,\n action: res,\n file: path.relative(root, filePath),\n locale: parsed.locale,\n path: parsed.path,\n value: parsed.value,\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n case \"dialex_add_missing\": {\n const schema = z.object({ config: z.string().optional() });\n const parsed = schema.parse(args);\n const project = await loadStaticProject(root, parsed.config);\n const defaultLocale = project.config.defaultLocale || \"en\";\n const configuredLocales = project.config.locales || [];\n\n let totalFixed = 0;\n\n for (const d of project.dictionaries) {\n if (!d.df.complete) continue;\n const present = listLocales(d.df);\n const targets = Array.from(new Set([...present, ...configuredLocales]));\n const sourceOrder = [\n defaultLocale,\n ...present.filter((l) => l !== defaultLocale),\n ].filter((l) => present.includes(l));\n\n const allPaths = new Map<string, string[]>();\n for (const locale of present) {\n for (const leaf of listLeaves(d.df, locale))\n allPaths.set(leaf.path.join(\"\\u0000\"), leaf.path);\n }\n\n let changed = false;\n for (const target of targets) {\n for (const leafPath of allPaths.values()) {\n if (hasPath(d.df, target, leafPath)) continue;\n const source = sourceOrder.find((l) => l !== target && hasPath(d.df, l, leafPath));\n if (\n source &&\n copyLeaf(d.df, source, target, leafPath, (v) => `${TODO_PREFIX}${v}`)\n ) {\n totalFixed++;\n changed = true;\n }\n }\n }\n\n if (changed) {\n await saveDictionaryFile(d.df);\n }\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: true, fixed: totalFixed }, null, 2),\n },\n ],\n };\n }\n\n case \"dialex_generate\": {\n const schema = z.object({\n output: z.string().optional(),\n config: z.string().optional(),\n });\n const parsed = schema.parse(args);\n const res = generateDictionaries(root, { output: parsed.output, config: parsed.config });\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n success: true,\n files: res.files.map((f) => path.relative(root, f)),\n outputPath: path.relative(root, res.outputPath),\n dtsPath: path.relative(root, res.dtsPath),\n },\n null,\n 2,\n ),\n },\n ],\n };\n }\n\n default:\n throw new Error(`Unknown tool: ${name}`);\n }\n } catch (err: any) {\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: `Error executing ${name}: ${err.message || String(err)}`,\n },\n ],\n };\n }\n });\n\n return server;\n}\n","#!/usr/bin/env node\n\nimport fs from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\n\nimport { createDialexMcpServer } from \"./server.js\";\n\nexport { createDialexMcpServer } from \"./server.js\";\n\n/**\n * True when this module is the script node was started with. `npx` and package managers start\n * bins through a symlink, so `argv[1]` must be resolved before comparing it with the module path.\n */\nexport function isEntrypoint(argv1: string | undefined, moduleUrl: string): boolean {\n if (!argv1) return false;\n try {\n return fs.realpathSync(argv1) === fs.realpathSync(fileURLToPath(moduleUrl));\n } catch {\n return false;\n }\n}\n\nasync function main() {\n const args = process.argv.slice(2);\n let root = process.cwd();\n\n for (let i = 0; i < args.length; i++) {\n if (args[i] === \"--root\" && args[i + 1]) {\n root = args[i + 1];\n i++;\n } else if (args[i].startsWith(\"--root=\")) {\n root = args[i].slice(\"--root=\".length);\n }\n }\n\n const server = createDialexMcpServer({ root });\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\nif (isEntrypoint(process.argv[1], import.meta.url)) {\n main().catch((err) => {\n console.error(\"Dialex MCP Server Error:\", err);\n process.exit(1);\n });\n}\n"],"mappings":";;;;;;;;;;;AC2EA,MAAa,aAAqC;CAChD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CACP,WAAW;;;;;;;;CACX,KAAK;;;;;;;;;;;;;;;;;;;;;;CACL,UAAU;;;;;;AACZ;;;AChDA,SAAgB,sBAAsB,UAA6B,CAAC,GAAG;CACrE,MAAM,gBAAgB,KAAK,QAAQ,QAAQ,QAAQ,QAAQ,IAAI,CAAC;CAEhE,MAAM,SAAS,IAAI,OACjB;EACE,MAAM;EACGA;CACX,GACA,EACE,cAAc;EACZ,OAAO,CAAC;EACR,WAAW,CAAC;CACd,EACF,CACF;CAEA,OAAO,kBAAkB,4BAA4B,YAAY;EAC/D,OAAO,EACL,WAAW,OAAO,KAAK,UAAU,CAAC,CAAC,KAAK,WAAW;GACjD,KAAK,iBAAiB;GACtB,MAAM,yBAAyB;GAC/B,UAAU;GACV,aAAa,sCAAsC;EACrD,EAAE,EACJ;CACF,CAAC;CAED,OAAO,kBAAkB,2BAA2B,OAAO,YAAY;EACrE,MAAM,MAAM,QAAQ,OAAO;EAC3B,MAAM,QAAQ,sCAAsC,KAAK,GAAG;EAC5D,IAAI,CAAC,OACH,MAAM,IAAI,MAAM,yBAAyB,KAAK;EAEhD,MAAM,QAAQ,MAAM;EACpB,MAAM,UAAU,WAAW;EAC3B,IAAI,CAAC,SACH,MAAM,IAAI,MAAM,kCAAkC,OAAO;EAE3D,OAAO,EACL,UAAU,CACR;GACE;GACA,UAAU;GACV,MAAM;EACR,CACF,EACF;CACF,CAAC;CAED,OAAO,kBAAkB,wBAAwB,YAAY;EAC3D,OAAO,EACL,OAAO;GACL;IACE,MAAM;IACN,aACE;IACF,aAAa;KACX,MAAM;KACN,YAAY,EACV,QAAQ;MACN,MAAM;MACN,aAAa;KACf,EACF;IACF;GACF;GACA;IACE,MAAM;IACN,aACE;IACF,aAAa;KACX,MAAM;KACN,YAAY,EACV,QAAQ;MACN,MAAM;MACN,aAAa;KACf,EACF;IACF;GACF;GACA;IACE,MAAM;IACN,aACE;IACF,aAAa;KACX,MAAM;KACN,YAAY;MACV,MAAM;OACJ,MAAM;OACN,aACE;MACJ;MACA,QAAQ;OACN,MAAM;OACN,aACE;MACJ;MACA,QAAQ;OACN,MAAM;OACN,aAAa;MACf;KACF;IACF;GACF;GACA;IACE,MAAM;IACN,aACE;IACF,aAAa;KACX,MAAM;KACN,YAAY;MACV,KAAK;OACH,MAAM;OACN,OAAO,EAAE,MAAM,SAAS;OACxB,aAAa;MACf;MACA,QAAQ;OACN,MAAM;OACN,aAAa;MACf;KACF;IACF;GACF;GACA;IACE,MAAM;IACN,aACE;IACF,aAAa;KACX,MAAM;KACN,YAAY,EACV,MAAM;MACJ,MAAM;MACN,aAAa;KACf,EACF;KACA,UAAU,CAAC,MAAM;IACnB;GACF;GACA;IACE,MAAM;IACN,aACE;IACF,aAAa;KACX,MAAM;KACN,YAAY;MACV,QAAQ;OACN,MAAM;OACN,aAAa;MACf;MACA,QAAQ;OACN,MAAM;OACN,aAAa;MACf;KACF;IACF;GACF;GACA;IACE,MAAM;IACN,aACE;IACF,aAAa;KACX,MAAM;KACN,YAAY;MACV,MAAM;OACJ,MAAM;OACN,aAAa;MACf;MACA,QAAQ;OACN,MAAM;OACN,aAAa;MACf;MACA,MAAM;OACJ,MAAM;OACN,OAAO,EAAE,MAAM,SAAS;OACxB,aAAa;MACf;MACA,OAAO;OACL,MAAM;OACN,aAAa;MACf;MACA,WAAW;OACT,MAAM;OACN,aACE;MACJ;KACF;KACA,UAAU;MAAC;MAAQ;MAAU;MAAQ;KAAO;IAC9C;GACF;GACA;IACE,MAAM;IACN,aACE;IACF,aAAa;KACX,MAAM;KACN,YAAY,EACV,QAAQ;MACN,MAAM;MACN,aAAa;KACf,EACF;IACF;GACF;GACA;IACE,MAAM;IACN,aACE;IACF,aAAa;KACX,MAAM;KACN,YAAY;MACV,QAAQ;OACN,MAAM;OACN,aAAa;MACf;MACA,QAAQ;OACN,MAAM;OACN,aAAa;MACf;KACF;IACF;GACF;EACF,EACF;CACF,CAAC;CAED,OAAO,kBAAkB,uBAAuB,OAAO,YAAY;EACjE,MAAM,OAAO,QAAQ;EACrB,MAAM,EAAE,MAAM,WAAW,OAAO,CAAC,MAAM,QAAQ;EAE/C,IAAI;GACF,QAAQ,MAAR;IACE,KAAK,iBA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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["pkg.version"],"sources":["../package.json","../src/docs.ts","../src/resources.ts","../src/tools/add-missing.ts","../src/tools/check.ts","../src/tools/config.ts","../src/tools/find-usages.ts","../src/tools/generate.ts","../src/tools/get-dictionary.ts","../src/tools/list-dictionaries.ts","../src/tools/missing.ts","../src/tools/set-key.ts","../src/tools/index.ts","../src/server.ts","../src/index.ts"],"sourcesContent":["","export const DIALEX_GUIDE_DOC = `# Dialex Internationalization Guide\n\nDialex is a high-performance, type-safe internationalization toolchain for JavaScript and TypeScript.\n\n## Key Features\n- **Zero Runtime Overhead**: Dictionaries are statically compiled.\n- **Strict Parity**: Compile-time checking verifies that every key in your default locale exists in all configured locales.\n- **ICU MessageFormat**: Native plural and select format support ({count, plural, one {# item} other {# items}}).\n- **Universal Framework Support**: Native integrations for React, Next.js, Express, Fastify, Hono, Koa, NestJS, SvelteKit, Astro, Vue, and Nuxt.\n\n## Content Dictionaries (\\`*.content.ts\\`)\nDefined with \\`defineDictionary\\`:\n\\`\\`\\`ts\nimport { defineDictionary } from \"dialexjs\";\n\nexport default defineDictionary(\"home\", {\n en: {\n title: \"Welcome\",\n greeting: (name: string) => \\`Hello, \\${name}!\\`,\n items: \"{count, plural, one {# item} other {# items}}\",\n },\n tr: {\n title: \"Hoş Geldiniz\",\n greeting: (name: string) => \\`Merhaba, \\${name}!\\`,\n items: \"{count, plural, other {# öğe}}\",\n },\n});\n\\`\\`\\`\n\n## CLI & Tooling\n- \\`dialex check\\`: Parity checker. Use \\`--fix\\` to insert \\`[TODO]\\` stubs. Use \\`--json\\` for structured output.\n- \\`dialex generate\\`: Generates \\`dialex.generated.ts\\` and \\`dialex-env.d.ts\\`.\n- \\`dialex export\\` / \\`dialex import\\`: JSON, CSV, XLIFF interchange.\n- \\`dialex translate\\`: Fill missing keys with AI providers (Claude, OpenAI, Gemini, DeepL).\n`;\n\nexport const DIALEX_TRANSLATE_DOC = `# Dialex Translation Workflow\n\n## Missing Keys & Workflow\n1. Run \\`dialex check --json\\` to detect missing keys or parity discrepancies.\n2. Run \\`dialex check --fix\\` (or \\`dialex_add_missing\\` via MCP) to automatically insert \\`[TODO]\\` stubs for missing keys.\n3. Replace \\`[TODO]\\` entries with real translations using \\`dialex_set_key\\` via MCP or \\`dialex translate\\` via CLI.\n4. Verify with \\`dialex check\\` that all keys are translated and ICU placeholders match.\n`;\n\nexport const DIALEX_ICU_DOC = `# Dialex ICU MessageFormat Reference\n\n## Plurals\n\\`\\`\\`icu\n{count, plural,\n =0 {No notifications}\n one {# notification}\n other {# notifications}\n}\n\\`\\`\\`\n\n## Select\n\\`\\`\\`icu\n{gender, select,\n male {He updated his profile}\n female {She updated her profile}\n other {They updated their profile}\n}\n\\`\\`\\`\n\nAll locales for a given key must declare the exact same variable placeholders.\n`;\n\nexport const DIALEX_ADAPTERS_DOC = `# Dialex Adapters Reference\n\n- **React**: \\`useDictionary(\"name\")\\`, \\`useT()\\` with \\`DialexProvider\\`.\n- **Next.js App Router**: \\`getDictionary(\"name\", locale)\\` in Server Components.\n- **Express / Hono / Fastify**: Middleware injecting \\`getDictionary\\` or context variable into requests.\n`;\n\nexport const DOC_TOPICS: Record<string, string> = {\n guide: DIALEX_GUIDE_DOC,\n translate: DIALEX_TRANSLATE_DOC,\n icu: DIALEX_ICU_DOC,\n adapters: DIALEX_ADAPTERS_DOC,\n};\n","import { DOC_TOPICS } from \"./docs.js\";\n\n/** The documentation topics offered as `dialex://docs/<topic>` resources. */\nexport function listDocResources() {\n return {\n resources: Object.keys(DOC_TOPICS).map((topic) => ({\n uri: `dialex://docs/${topic}`,\n name: `Dialex Documentation: ${topic}`,\n mimeType: \"text/markdown\",\n description: `Reference documentation for Dialex ${topic}`,\n })),\n };\n}\n\n/** The content of one `dialex://docs/<topic>` resource. */\nexport function readDocResource(uri: string) {\n const match = /^dialex:\\/\\/docs\\/([a-zA-Z0-9_-]+)$/.exec(uri);\n if (!match) {\n throw new Error(`Invalid resource URI: ${uri}`);\n }\n const topic = match[1];\n const content = DOC_TOPICS[topic];\n if (!content) {\n throw new Error(`Documentation topic not found: ${topic}`);\n }\n return {\n contents: [\n {\n uri,\n mimeType: \"text/markdown\",\n text: content,\n },\n ],\n };\n}\n","import {\n TODO_PREFIX,\n copyLeaf,\n hasPath,\n listLeaves,\n listLocales,\n loadStaticProject,\n saveDictionaryFile,\n} from \"@dialexjs/cli/api\";\nimport { z } from \"zod\";\n\nimport type { McpTool } from \"./types.js\";\n\nexport const addMissing: McpTool = {\n name: \"dialex_add_missing\",\n description:\n \"Automatically insert missing keys across all locales as [TODO] placeholders copied from default locale values (AST safe edits).\",\n inputSchema: {\n type: \"object\",\n properties: {\n config: {\n type: \"string\",\n description: \"Optional custom path to config file.\",\n },\n },\n },\n\n async handler(root, args) {\n const schema = z.object({ config: z.string().optional() });\n const parsed = schema.parse(args);\n const project = await loadStaticProject(root, parsed.config);\n const defaultLocale = project.config.defaultLocale || \"en\";\n const configuredLocales = project.config.locales || [];\n\n let totalFixed = 0;\n\n for (const d of project.dictionaries) {\n if (!d.df.complete) continue;\n const present = listLocales(d.df);\n const targets = Array.from(new Set([...present, ...configuredLocales]));\n const sourceOrder = [defaultLocale, ...present.filter((l) => l !== defaultLocale)].filter(\n (l) => present.includes(l),\n );\n\n const allPaths = new Map<string, string[]>();\n for (const locale of present) {\n for (const leaf of listLeaves(d.df, locale))\n allPaths.set(leaf.path.join(\"\\u0000\"), leaf.path);\n }\n\n let changed = false;\n for (const target of targets) {\n for (const leafPath of allPaths.values()) {\n if (hasPath(d.df, target, leafPath)) continue;\n const source = sourceOrder.find((l) => l !== target && hasPath(d.df, l, leafPath));\n if (source && copyLeaf(d.df, source, target, leafPath, (v) => `${TODO_PREFIX}${v}`)) {\n totalFixed++;\n changed = true;\n }\n }\n }\n\n if (changed) {\n await saveDictionaryFile(d.df);\n }\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: true, fixed: totalFixed }, null, 2),\n },\n ],\n };\n },\n};\n","import path from \"node:path\";\n\nimport { analyzeProject, readStaticConfig } from \"@dialexjs/cli/api\";\nimport { z } from \"zod\";\n\nimport type { McpTool } from \"./types.js\";\n\nexport const check: McpTool = {\n name: \"dialex_check\",\n description:\n \"Analyze project statically to verify dictionary key parity, ICU arguments, and source code references without executing project code.\",\n inputSchema: {\n type: \"object\",\n properties: {\n src: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Optional source file globs to scan for dictionary references.\",\n },\n config: {\n type: \"string\",\n description: \"Optional custom path to config file.\",\n },\n },\n },\n\n async handler(root, args) {\n const schema = z.object({\n src: z.array(z.string()).optional(),\n config: z.string().optional(),\n });\n const parsed = schema.parse(args);\n const staticConf = readStaticConfig(root, parsed.config);\n const analysis = await analyzeProject({\n root,\n config: staticConf.config,\n src: parsed.src,\n runtime: false,\n });\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n issues: analysis.issues.map((i) => ({\n ...i,\n file: path.relative(root, i.file),\n })),\n totalIssues: analysis.issues.filter((i) => i.level === \"error\").length,\n totalWarnings: analysis.issues.filter((i) => i.level === \"warning\").length,\n filesScanned: analysis.sourceFilesScanned,\n },\n null,\n 2,\n ),\n },\n ],\n };\n },\n};\n","import { readStaticConfig } from \"@dialexjs/cli/api\";\nimport { z } from \"zod\";\n\nimport type { McpTool } from \"./types.js\";\n\nexport const dialexConfig: McpTool = {\n name: \"dialex_config\",\n description:\n \"Read static Dialex configuration (locales, defaultLocale, include pattern) from dialex.config.ts or i18n.config.ts without executing project code.\",\n inputSchema: {\n type: \"object\",\n properties: {\n config: {\n type: \"string\",\n description: \"Optional custom path to config file relative to project root.\",\n },\n },\n },\n\n async handler(root, args) {\n const schema = z.object({ config: z.string().optional() });\n const parsed = schema.parse(args);\n const staticConf = readStaticConfig(root, parsed.config);\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(staticConf, null, 2),\n },\n ],\n };\n },\n};\n","import path from \"node:path\";\n\nimport { scanReferences } from \"@dialexjs/cli/api\";\nimport { z } from \"zod\";\n\nimport type { McpTool } from \"./types.js\";\n\nexport const findUsages: McpTool = {\n name: \"dialex_find_usages\",\n description:\n \"Scan source files for dictionary usages (e.g. getDictionary('home') or t('home.title')).\",\n inputSchema: {\n type: \"object\",\n properties: {\n file: {\n type: \"string\",\n description: \"Relative or absolute file path to scan for references.\",\n },\n },\n required: [\"file\"],\n },\n\n async handler(root, args) {\n const schema = z.object({ file: z.string() });\n const parsed = schema.parse(args);\n const filePath = path.isAbsolute(parsed.file) ? parsed.file : path.resolve(root, parsed.file);\n const fs = await import(\"node:fs\");\n if (!fs.existsSync(filePath)) {\n throw new Error(`File not found: ${parsed.file}`);\n }\n const text = fs.readFileSync(filePath, \"utf-8\");\n const refs = scanReferences(text);\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ file: path.relative(root, filePath), references: refs }, null, 2),\n },\n ],\n };\n },\n};\n","import path from \"node:path\";\n\nimport { generateDictionaries } from \"@dialexjs/cli/api\";\nimport { z } from \"zod\";\n\nimport type { McpTool } from \"./types.js\";\n\nexport const generate: McpTool = {\n name: \"dialex_generate\",\n description:\n \"Run code generation to build standalone dictionary registry and TypeScript declarations.\",\n inputSchema: {\n type: \"object\",\n properties: {\n output: {\n type: \"string\",\n description: \"Optional custom output path for dialex.generated.ts.\",\n },\n config: {\n type: \"string\",\n description: \"Optional custom path to config file.\",\n },\n },\n },\n\n async handler(root, args) {\n const schema = z.object({\n output: z.string().optional(),\n config: z.string().optional(),\n });\n const parsed = schema.parse(args);\n const res = generateDictionaries(root, { output: parsed.output, config: parsed.config });\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n success: true,\n files: res.files.map((f) => path.relative(root, f)),\n outputPath: path.relative(root, res.outputPath),\n dtsPath: path.relative(root, res.dtsPath),\n },\n null,\n 2,\n ),\n },\n ],\n };\n },\n};\n","import { listLeaves, listLocales, loadStaticProject } from \"@dialexjs/cli/api\";\nimport { z } from \"zod\";\n\nimport type { McpTool } from \"./types.js\";\n\nexport const getDictionary: McpTool = {\n name: \"dialex_get_dictionary\",\n description:\n \"Get leaf keys and values for a specific dictionary or all dictionaries, optionally filtered by locale.\",\n inputSchema: {\n type: \"object\",\n properties: {\n name: {\n type: \"string\",\n description:\n \"Dictionary name (e.g. 'home' or 'auth'). If omitted, returns all dictionaries.\",\n },\n locale: {\n type: \"string\",\n description: \"Locale to retrieve (e.g. 'en' or 'tr'). If omitted, returns all locales.\",\n },\n config: {\n type: \"string\",\n description: \"Optional custom path to config file.\",\n },\n },\n },\n\n async handler(root, args) {\n const schema = z.object({\n name: z.string().optional(),\n locale: z.string().optional(),\n config: z.string().optional(),\n });\n const parsed = schema.parse(args);\n const project = await loadStaticProject(root, parsed.config);\n\n const result: Record<\n string,\n Record<string, Array<{ path: string[]; kind: string; value?: string }>>\n > = {};\n\n for (const d of project.dictionaries) {\n if (parsed.name && d.name !== parsed.name) continue;\n result[d.name] = {};\n const locales = listLocales(d.df);\n for (const loc of locales) {\n if (parsed.locale && loc !== parsed.locale) continue;\n result[d.name][loc] = listLeaves(d.df, loc);\n }\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n },\n};\n","import { listLocales, loadStaticProject } from \"@dialexjs/cli/api\";\nimport { z } from \"zod\";\n\nimport type { McpTool } from \"./types.js\";\n\nexport const listDictionaries: McpTool = {\n name: \"dialex_list_dictionaries\",\n description: \"List all discovered content dictionaries, their files, and supported locales.\",\n inputSchema: {\n type: \"object\",\n properties: {\n config: {\n type: \"string\",\n description: \"Optional custom path to config file relative to project root.\",\n },\n },\n },\n\n async handler(root, args) {\n const schema = z.object({ config: z.string().optional() });\n const parsed = schema.parse(args);\n const project = await loadStaticProject(root, parsed.config);\n const dicts = project.dictionaries.map((d) => ({\n name: d.name,\n file: d.rel,\n locales: listLocales(d.df),\n complete: d.df.complete,\n }));\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n dictionaries: dicts,\n unsupported: project.unsupported,\n notes: project.notes,\n },\n null,\n 2,\n ),\n },\n ],\n };\n },\n};\n","import {\n TODO_PREFIX,\n isStale,\n listLeaves,\n listLocales,\n loadStaticProject,\n readLock,\n} from \"@dialexjs/cli/api\";\nimport { z } from \"zod\";\n\nimport type { McpTool } from \"./types.js\";\n\nexport const missing: McpTool = {\n name: \"dialex_missing\",\n description:\n \"List missing keys, keys marked with [TODO] placeholders, and stale translations (the source text changed after they were translated, per dialex.lock.json) across locales.\",\n inputSchema: {\n type: \"object\",\n properties: {\n locale: {\n type: \"string\",\n description: \"Filter missing keys to a specific target locale.\",\n },\n config: {\n type: \"string\",\n description: \"Optional custom path to config file.\",\n },\n },\n },\n\n async handler(root, args) {\n const schema = z.object({\n locale: z.string().optional(),\n config: z.string().optional(),\n });\n const parsed = schema.parse(args);\n const project = await loadStaticProject(root, parsed.config);\n const defaultLocale = project.config.defaultLocale || \"en\";\n\n const missingItems: Array<{\n dictionary: string;\n file: string;\n locale: string;\n path: string[];\n key: string;\n status: \"missing\" | \"todo\" | \"stale\";\n currentValue?: string;\n defaultValue?: string;\n }> = [];\n\n const configuredLocales = new Set(project.config.locales || []);\n const lock = readLock(root);\n\n for (const d of project.dictionaries) {\n const localesInDict = new Set(listLocales(d.df));\n const allLocales = new Set([...localesInDict, ...configuredLocales]);\n const defaultLeaves = listLeaves(d.df, defaultLocale);\n const defaultMap = new Map(defaultLeaves.map((l) => [l.path.join(\".\"), l.value]));\n\n for (const loc of allLocales) {\n if (loc === defaultLocale) continue;\n if (parsed.locale && loc !== parsed.locale) continue;\n\n const leaves = listLeaves(d.df, loc);\n const leafMap = new Map(leaves.map((l) => [l.path.join(\".\"), l]));\n\n for (const defLeaf of defaultLeaves) {\n const pathKey = defLeaf.path.join(\".\");\n const curr = leafMap.get(pathKey);\n if (!curr) {\n missingItems.push({\n dictionary: d.name,\n file: d.rel,\n locale: loc,\n path: defLeaf.path,\n key: `${d.name}.${pathKey}`,\n status: \"missing\",\n defaultValue: defLeaf.value,\n });\n } else if (curr.kind === \"string\" && curr.value?.startsWith(TODO_PREFIX)) {\n missingItems.push({\n dictionary: d.name,\n file: d.rel,\n locale: loc,\n path: defLeaf.path,\n key: `${d.name}.${pathKey}`,\n status: \"todo\",\n currentValue: curr.value,\n defaultValue: defaultMap.get(pathKey),\n });\n }\n }\n }\n\n // Translations whose source text changed since they were translated\n if (lock?.sourceLocale) {\n const sourceLeaves = new Map(\n listLeaves(d.df, lock.sourceLocale).map((l) => [l.path.join(\".\"), l]),\n );\n for (const loc of allLocales) {\n if (loc === lock.sourceLocale) continue;\n if (parsed.locale && loc !== parsed.locale) continue;\n for (const leaf of listLeaves(d.df, loc)) {\n if (leaf.kind !== \"string\" || leaf.value === undefined) continue;\n if (leaf.value.startsWith(TODO_PREFIX)) continue;\n const pathKey = leaf.path.join(\".\");\n const source = sourceLeaves.get(pathKey);\n if (source?.kind !== \"string\" || source.value === undefined) continue;\n const key = `${d.name}.${pathKey}`;\n if (!isStale(lock, loc, key, source.value)) continue;\n missingItems.push({\n dictionary: d.name,\n file: d.rel,\n locale: loc,\n path: leaf.path,\n key,\n status: \"stale\",\n currentValue: leaf.value,\n defaultValue: source.value,\n });\n }\n }\n }\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ missingCount: missingItems.length, items: missingItems }, null, 2),\n },\n ],\n };\n },\n};\n","import path from \"node:path\";\n\nimport {\n TODO_PREFIX,\n getString,\n loadDictionaryFile,\n saveDictionaryFile,\n setString,\n} from \"@dialexjs/cli/api\";\nimport { z } from \"zod\";\n\nimport type { McpTool } from \"./types.js\";\n\nexport const setKey: McpTool = {\n name: \"dialex_set_key\",\n description:\n \"Safely set or update a translation string in a dictionary file using AST manipulation without executing project code or destroying comments/formatting. Refuses to overwrite non-[TODO] values unless overwrite is explicitly true.\",\n inputSchema: {\n type: \"object\",\n properties: {\n file: {\n type: \"string\",\n description: \"Dictionary file path (e.g. 'src/home.content.ts' or absolute path).\",\n },\n locale: {\n type: \"string\",\n description: \"Locale to update (e.g. 'tr').\",\n },\n path: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Key path segments (e.g. ['nav', 'about'] or ['title']).\",\n },\n value: {\n type: \"string\",\n description: \"The translated string value to set.\",\n },\n overwrite: {\n type: \"boolean\",\n description:\n \"Must be set to true to overwrite an existing translated value that is not marked [TODO]. Defaults to false.\",\n },\n },\n required: [\"file\", \"locale\", \"path\", \"value\"],\n },\n\n async handler(root, args) {\n const schema = z.object({\n file: z.string(),\n locale: z.string(),\n path: z.array(z.string()),\n value: z.string(),\n overwrite: z.boolean().optional(),\n });\n const parsed = schema.parse(args);\n const filePath = path.isAbsolute(parsed.file) ? parsed.file : path.resolve(root, parsed.file);\n\n const df = await loadDictionaryFile(filePath);\n if (!df) {\n throw new Error(\n `Cannot load dictionary file at ${parsed.file} (unsupported shape or syntax error)`,\n );\n }\n\n const existingVal = getString(df, parsed.locale, parsed.path);\n const isTodo = existingVal?.startsWith(TODO_PREFIX);\n\n if (existingVal !== undefined && !isTodo && !parsed.overwrite) {\n throw new Error(\n `Key \"${parsed.path.join(\".\")}\" in locale \"${parsed.locale}\" already has a translated value (${JSON.stringify(existingVal)}). Set overwrite: true to overwrite.`,\n );\n }\n\n const res = setString(df, parsed.locale, parsed.path, parsed.value);\n if (res === \"skipped\") {\n throw new Error(\n `Cannot set string at \"${parsed.path.join(\".\")}\" in \"${parsed.locale}\": target is a function or non-string node.`,\n );\n }\n\n await saveDictionaryFile(df);\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n success: true,\n action: res,\n file: path.relative(root, filePath),\n locale: parsed.locale,\n path: parsed.path,\n value: parsed.value,\n },\n null,\n 2,\n ),\n },\n ],\n };\n },\n};\n","import { addMissing } from \"./add-missing.js\";\nimport { check } from \"./check.js\";\nimport { dialexConfig } from \"./config.js\";\nimport { findUsages } from \"./find-usages.js\";\nimport { generate } from \"./generate.js\";\nimport { getDictionary } from \"./get-dictionary.js\";\nimport { listDictionaries } from \"./list-dictionaries.js\";\nimport { missing } from \"./missing.js\";\nimport { setKey } from \"./set-key.js\";\nimport type { McpTool } from \"./types.js\";\n\nexport type { McpTool, ToolResult } from \"./types.js\";\n\n/** Every tool, in the order clients see them. */\nexport const TOOLS: McpTool[] = [\n dialexConfig,\n listDictionaries,\n getDictionary,\n check,\n findUsages,\n missing,\n setKey,\n addMissing,\n generate,\n];\n","import path from \"node:path\";\n\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n ListResourcesRequestSchema,\n ReadResourceRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\n\nimport pkg from \"../package.json\" with { type: \"json\" };\nimport { listDocResources, readDocResource } from \"./resources.js\";\nimport { TOOLS } from \"./tools/index.js\";\n\nexport function createDialexMcpServer(options: { root?: string } = {}) {\n const getRoot = () => path.resolve(options.root || process.cwd());\n\n const server = new Server(\n {\n name: \"dialex\",\n version: pkg.version,\n },\n {\n capabilities: {\n tools: {},\n resources: {},\n },\n },\n );\n\n server.setRequestHandler(ListResourcesRequestSchema, async () => listDocResources());\n\n server.setRequestHandler(ReadResourceRequestSchema, async (request) =>\n readDocResource(request.params.uri),\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => {\n return {\n tools: TOOLS.map(({ name, description, inputSchema }) => ({\n name,\n description,\n inputSchema,\n })),\n };\n });\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const root = getRoot();\n const { name, arguments: args = {} } = request.params;\n\n try {\n const tool = TOOLS.find((candidate) => candidate.name === name);\n if (!tool) throw new Error(`Unknown tool: ${name}`);\n return await tool.handler(root, args);\n } catch (err: any) {\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: `Error executing ${name}: ${err.message || String(err)}`,\n },\n ],\n };\n }\n });\n\n return server;\n}\n","#!/usr/bin/env node\n\nimport fs from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\n\nimport { createDialexMcpServer } from \"./server.js\";\n\nexport { createDialexMcpServer } from \"./server.js\";\n\n/**\n * True when this module is the script node was started with. `npx` and package managers start\n * bins through a symlink, so `argv[1]` must be resolved before comparing it with the module path.\n */\nexport function isEntrypoint(argv1: string | undefined, moduleUrl: string): boolean {\n if (!argv1) return false;\n try {\n return fs.realpathSync(argv1) === fs.realpathSync(fileURLToPath(moduleUrl));\n } catch {\n return false;\n }\n}\n\nasync function main() {\n const args = process.argv.slice(2);\n let root = process.cwd();\n\n for (let i = 0; i < args.length; i++) {\n if (args[i] === \"--root\" && args[i + 1]) {\n root = args[i + 1];\n i++;\n } else if (args[i].startsWith(\"--root=\")) {\n root = args[i].slice(\"--root=\".length);\n }\n }\n\n const server = createDialexMcpServer({ root });\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\nif (isEntrypoint(process.argv[1], import.meta.url)) {\n main().catch((err) => {\n console.error(\"Dialex MCP Server Error:\", err);\n process.exit(1);\n });\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dialexjs/mcp",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.2",
|
|
4
4
|
"description": "Model Context Protocol (MCP) server for Dialex internationalization",
|
|
5
5
|
"homepage": "https://github.com/awaiden/dialex#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"check": "vp check"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@dialexjs/cli": "0.9.
|
|
36
|
+
"@dialexjs/cli": "0.9.2",
|
|
37
37
|
"@modelcontextprotocol/sdk": "^1.32.1",
|
|
38
38
|
"zod": "^4.6.5"
|
|
39
39
|
},
|