@better-i18n/mcp-server 0.1.5 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +13 -9
  2. package/dist/base-tool.d.ts +43 -0
  3. package/dist/base-tool.d.ts.map +1 -0
  4. package/dist/base-tool.js +67 -0
  5. package/dist/base-tool.js.map +1 -0
  6. package/dist/helpers.d.ts +30 -0
  7. package/dist/helpers.d.ts.map +1 -0
  8. package/dist/helpers.js +32 -0
  9. package/dist/helpers.js.map +1 -0
  10. package/dist/index.js +12 -51
  11. package/dist/index.js.map +1 -1
  12. package/dist/tools/bulkCreateKeys.d.ts +0 -1
  13. package/dist/tools/bulkCreateKeys.d.ts.map +1 -1
  14. package/dist/tools/bulkCreateKeys.js +28 -79
  15. package/dist/tools/bulkCreateKeys.js.map +1 -1
  16. package/dist/tools/bulkUpdateTranslations.d.ts +0 -1
  17. package/dist/tools/bulkUpdateTranslations.d.ts.map +1 -1
  18. package/dist/tools/bulkUpdateTranslations.js +27 -78
  19. package/dist/tools/bulkUpdateTranslations.js.map +1 -1
  20. package/dist/tools/createTranslationKey.d.ts +0 -1
  21. package/dist/tools/createTranslationKey.d.ts.map +1 -1
  22. package/dist/tools/createTranslationKey.js +25 -76
  23. package/dist/tools/createTranslationKey.js.map +1 -1
  24. package/dist/tools/getProjectInfo.d.ts +0 -1
  25. package/dist/tools/getProjectInfo.d.ts.map +1 -1
  26. package/dist/tools/getProjectInfo.js +11 -62
  27. package/dist/tools/getProjectInfo.js.map +1 -1
  28. package/dist/tools/listKeys.d.ts +0 -1
  29. package/dist/tools/listKeys.d.ts.map +1 -1
  30. package/dist/tools/listKeys.js +17 -67
  31. package/dist/tools/listKeys.js.map +1 -1
  32. package/dist/tools/updateTranslation.d.ts +0 -1
  33. package/dist/tools/updateTranslation.d.ts.map +1 -1
  34. package/dist/tools/updateTranslation.js +26 -77
  35. package/dist/tools/updateTranslation.js.map +1 -1
  36. package/dist/types/index.d.ts +1 -8
  37. package/dist/types/index.d.ts.map +1 -1
  38. package/package.json +1 -1
  39. package/dist/context.d.ts +0 -23
  40. package/dist/context.d.ts.map +0 -1
  41. package/dist/context.js +0 -154
  42. package/dist/context.js.map +0 -1
@@ -2,11 +2,10 @@
2
2
  * updateTranslation MCP Tool
3
3
  *
4
4
  * Updates or creates a translation for a specific language.
5
- * Uses the MCP-specific API that works with org/project slugs.
6
5
  */
7
- import { z } from 'zod';
8
- const inputSchema = z.object({
9
- projectSlug: z.string().optional(),
6
+ import { z } from "zod";
7
+ import { executeTool, projectInputProperty, projectSchema, success, } from "../base-tool.js";
8
+ const inputSchema = projectSchema.extend({
10
9
  key: z.string().min(1),
11
10
  languageCode: z.string().min(2).max(10),
12
11
  value: z.string(),
@@ -15,17 +14,14 @@ const inputSchema = z.object({
15
14
  export const updateTranslation = {
16
15
  definition: {
17
16
  name: "updateTranslation",
18
- description: "Update or create a SINGLE translation for a specific language. IMPORTANT: If you need to update 2 or more translations, use bulkUpdateTranslations instead - it's much more efficient. Only use this tool when updating exactly ONE translation. If the translation doesn't exist, it will be created. If namespace is provided, the key should NOT include the namespace prefix (e.g., namespace: 'nav', key: 'home' NOT 'nav.home').",
17
+ description: "Update or create a SINGLE translation for a specific language. IMPORTANT: If you need to update 2 or more translations, use bulkUpdateTranslations instead.",
19
18
  inputSchema: {
20
19
  type: "object",
21
20
  properties: {
22
- projectSlug: {
23
- type: "string",
24
- description: "Project slug (optional if i18n.config.ts exists)",
25
- },
21
+ ...projectInputProperty,
26
22
  key: {
27
23
  type: "string",
28
- description: "Translation key WITHOUT namespace prefix when namespace is provided (e.g., 'home' when namespace is 'nav', NOT 'nav.home'). Only include full path if namespace is not provided.",
24
+ description: "Translation key WITHOUT namespace prefix when namespace is provided.",
29
25
  },
30
26
  languageCode: {
31
27
  type: "string",
@@ -37,76 +33,29 @@ export const updateTranslation = {
37
33
  },
38
34
  namespace: {
39
35
  type: "string",
40
- description: "Namespace for the key (e.g., 'nav', 'home', 'cta'). When provided, the key should NOT include this namespace prefix. Defaults to 'default' if not provided.",
36
+ description: "Namespace for the key. Defaults to 'default'.",
41
37
  },
42
38
  },
43
- required: ["key", "languageCode", "value"],
39
+ required: ["project", "key", "languageCode", "value"],
44
40
  },
45
41
  },
46
- async execute(client, args, context) {
47
- const input = inputSchema.parse(args);
48
- // Parse projectSlug - supports both "org/project" format and standalone "project"
49
- let orgSlug;
50
- let projectSlug;
51
- if (input.projectSlug?.includes("/")) {
52
- // AI sent "org/project" format - parse it
53
- const parts = input.projectSlug.split("/");
54
- orgSlug = parts[0];
55
- projectSlug = parts[1];
56
- }
57
- else {
58
- // Fall back to auto-detected context or explicit projectSlug
59
- projectSlug = input.projectSlug || context.projectContext?.projectSlug;
60
- orgSlug = context.projectContext?.workspaceId;
61
- }
62
- if (!projectSlug || !orgSlug) {
63
- return {
64
- content: [
65
- {
66
- type: "text",
67
- text: "Error: Project not specified. Use format 'org/project' (e.g., 'aliosman-co/personal')",
68
- },
69
- ],
70
- isError: true,
71
- };
72
- }
73
- try {
74
- // Use MCP-specific endpoint with slug-based lookup
75
- await client.mcp.updateTranslation.mutate({
76
- orgSlug,
77
- projectSlug,
78
- key: input.key,
79
- namespace: input.namespace || "default",
80
- languageCode: input.languageCode,
81
- value: input.value,
82
- });
83
- return {
84
- content: [
85
- {
86
- type: "text",
87
- text: JSON.stringify({
88
- success: true,
89
- key: input.key,
90
- namespace: input.namespace || "default",
91
- languageCode: input.languageCode,
92
- value: input.value,
93
- project: `${orgSlug}/${projectSlug}`,
94
- }, null, 2),
95
- },
96
- ],
97
- };
98
- }
99
- catch (error) {
100
- return {
101
- content: [
102
- {
103
- type: "text",
104
- text: `Error updating translation: ${error instanceof Error ? error.message : String(error)}`,
105
- },
106
- ],
107
- isError: true,
108
- };
109
- }
110
- },
42
+ execute: (client, args) => executeTool(args, inputSchema, async (input, { workspaceId, projectSlug }) => {
43
+ await client.mcp.updateTranslation.mutate({
44
+ orgSlug: workspaceId,
45
+ projectSlug,
46
+ key: input.key,
47
+ namespace: input.namespace || "default",
48
+ languageCode: input.languageCode,
49
+ value: input.value,
50
+ });
51
+ return success({
52
+ success: true,
53
+ key: input.key,
54
+ namespace: input.namespace || "default",
55
+ languageCode: input.languageCode,
56
+ value: input.value,
57
+ project: input.project,
58
+ });
59
+ }),
111
60
  };
112
61
  //# sourceMappingURL=updateTranslation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"updateTranslation.js","sourceRoot":"","sources":["../../src/tools/updateTranslation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"updateTranslation.js","sourceRoot":"","sources":["../../src/tools/updateTranslation.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,aAAa,EACb,OAAO,GACR,MAAM,iBAAiB,CAAC;AAGzB,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,CAAC;IACvC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACtB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;IACvC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACjC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAS;IACrC,UAAU,EAAE;QACV,IAAI,EAAE,mBAAmB;QACzB,WAAW,EACT,6JAA6J;QAC/J,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,GAAG,oBAAoB;gBACvB,GAAG,EAAE;oBACH,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,sEAAsE;iBACpF;gBACD,YAAY,EAAE;oBACZ,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,8CAA8C;iBAC5D;gBACD,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,kBAAkB;iBAChC;gBACD,SAAS,EAAE;oBACT,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,+CAA+C;iBAC7D;aACF;YACD,QAAQ,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,CAAC;SACtD;KACF;IAED,OAAO,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CACxB,WAAW,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,EAAE,EAAE;QAC3E,MAAM,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,MAAM,CAAC;YACxC,OAAO,EAAE,WAAW;YACpB,WAAW;YACX,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,SAAS;YACvC,YAAY,EAAE,KAAK,CAAC,YAAY;YAChC,KAAK,EAAE,KAAK,CAAC,KAAK;SACnB,CAAC,CAAC;QAEH,OAAO,OAAO,CAAC;YACb,OAAO,EAAE,IAAI;YACb,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,SAAS;YACvC,YAAY,EAAE,KAAK,CAAC,YAAY;YAChC,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAC,CAAC;IACL,CAAC,CAAC;CACL,CAAC"}
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * Shared types for MCP server
3
3
  */
4
- import type { ProjectContext } from "../context.js";
5
4
  /**
6
5
  * MCP Tool definition
7
6
  */
@@ -33,12 +32,6 @@ export interface ToolResult {
33
32
  */
34
33
  export interface Tool {
35
34
  definition: ToolDefinition;
36
- execute: (client: any, args: unknown, context: ToolContext) => Promise<ToolResult>;
37
- }
38
- /**
39
- * Context passed to tool execution
40
- */
41
- export interface ToolContext {
42
- projectContext: ProjectContext | null;
35
+ execute: (client: any, args: unknown) => Promise<ToolResult>;
43
36
  }
44
37
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAChC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,UAAU,CAAC;QACpC,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC,CAAC;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,IAAI;IACnB,UAAU,EAAE,cAAc,CAAC;IAC3B,OAAO,EAAE,CACP,MAAM,EAAE,GAAG,EACX,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,WAAW,KACjB,OAAO,CAAC,UAAU,CAAC,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,cAAc,EAAE,cAAc,GAAG,IAAI,CAAC;CACvC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAChC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,UAAU,CAAC;QACpC,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC,CAAC;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,IAAI;IACnB,UAAU,EAAE,cAAc,CAAC;IAC3B,OAAO,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;CAC9D"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-i18n/mcp-server",
3
- "version": "0.1.5",
3
+ "version": "0.2.0",
4
4
  "description": "MCP server for Better i18n translation management - AI-powered translation workflow for Cursor, Claude, and other AI assistants",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/dist/context.d.ts DELETED
@@ -1,23 +0,0 @@
1
- /**
2
- * Project context detection
3
- *
4
- * Automatically detects Better i18n project configuration by searching for
5
- * createI18n usage from @better-i18n/next or @better-i18n/core in the workspace.
6
- */
7
- export interface ProjectContext {
8
- workspaceId: string;
9
- projectSlug: string;
10
- defaultLocale: string;
11
- cdnBaseUrl?: string;
12
- }
13
- /**
14
- * Find and parse createI18n configuration in workspace
15
- *
16
- * Searches for files importing createI18n from @better-i18n packages
17
- * and extracts the configuration.
18
- *
19
- * @param startDir - Starting directory (defaults to process.cwd())
20
- * @returns Project context or null if not found
21
- */
22
- export declare function detectProjectContext(startDir?: string): Promise<ProjectContext | null>;
23
- //# sourceMappingURL=context.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,GAAE,MAAsB,GAC/B,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CA0BhC"}
package/dist/context.js DELETED
@@ -1,154 +0,0 @@
1
- /**
2
- * Project context detection
3
- *
4
- * Automatically detects Better i18n project configuration by searching for
5
- * createI18n usage from @better-i18n/next or @better-i18n/core in the workspace.
6
- */
7
- import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
8
- import { dirname, join } from "node:path";
9
- /**
10
- * Find and parse createI18n configuration in workspace
11
- *
12
- * Searches for files importing createI18n from @better-i18n packages
13
- * and extracts the configuration.
14
- *
15
- * @param startDir - Starting directory (defaults to process.cwd())
16
- * @returns Project context or null if not found
17
- */
18
- export async function detectProjectContext(startDir = process.cwd()) {
19
- try {
20
- // Find workspace root
21
- const workspaceRoot = findWorkspaceRoot(startDir);
22
- console.error(`[better-i18n] Searching for createI18n in ${workspaceRoot}...`);
23
- // Search for files with createI18n import
24
- const configFile = findCreateI18nFile(workspaceRoot);
25
- if (configFile) {
26
- console.error(`[better-i18n] Found createI18n in ${configFile}`);
27
- const config = parseI18nConfig(configFile);
28
- if (config.workspaceId && config.projectSlug) {
29
- console.error(`[better-i18n] Detected project: ${config.workspaceId}/${config.projectSlug}`);
30
- return config;
31
- }
32
- }
33
- }
34
- catch (error) {
35
- console.error("[better-i18n] Error detecting project context:", error);
36
- }
37
- return null;
38
- }
39
- /**
40
- * Find workspace root by looking for .git or package.json with workspaces
41
- */
42
- function findWorkspaceRoot(startDir) {
43
- let currentDir = startDir;
44
- const maxDepth = 10;
45
- let depth = 0;
46
- while (depth < maxDepth) {
47
- // Check for .git directory
48
- if (existsSync(join(currentDir, ".git"))) {
49
- return currentDir;
50
- }
51
- // Check for workspace root (package.json with workspaces)
52
- const pkgPath = join(currentDir, "package.json");
53
- if (existsSync(pkgPath)) {
54
- try {
55
- const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
56
- if (pkg.workspaces) {
57
- return currentDir;
58
- }
59
- }
60
- catch {
61
- // Ignore parse errors
62
- }
63
- }
64
- const parentDir = dirname(currentDir);
65
- if (parentDir === currentDir)
66
- break;
67
- currentDir = parentDir;
68
- depth++;
69
- }
70
- return startDir;
71
- }
72
- /**
73
- * Search for files containing createI18n import from @better-i18n packages
74
- */
75
- function findCreateI18nFile(workspaceRoot) {
76
- const files = [];
77
- // Recursively search for TypeScript/JavaScript files
78
- function searchDir(dir, depth = 0) {
79
- if (depth > 5)
80
- return; // Limit recursion depth
81
- try {
82
- const entries = readdirSync(dir);
83
- for (const entry of entries) {
84
- // Skip common directories
85
- if (["node_modules", ".git", "dist", "build", ".next"].includes(entry)) {
86
- continue;
87
- }
88
- const fullPath = join(dir, entry);
89
- const stat = statSync(fullPath);
90
- if (stat.isDirectory()) {
91
- searchDir(fullPath, depth + 1);
92
- }
93
- else if (/\.(ts|tsx|js|jsx)$/.test(entry)) {
94
- files.push(fullPath);
95
- }
96
- }
97
- }
98
- catch {
99
- // Ignore permission errors
100
- }
101
- }
102
- searchDir(workspaceRoot);
103
- // Search through found files for createI18n import
104
- for (const file of files) {
105
- try {
106
- const content = readFileSync(file, "utf-8");
107
- // Check for createI18n import from @better-i18n packages
108
- if (/import\s+.*createI18n.*from\s+['"]@better-i18n\/(next|core)['"]/.test(content) &&
109
- /createI18n\s*\(/.test(content)) {
110
- return file;
111
- }
112
- }
113
- catch {
114
- // Ignore read errors
115
- }
116
- }
117
- return null;
118
- }
119
- /**
120
- * Parse file to extract createI18n configuration
121
- *
122
- * Supports both old format (workspaceId + projectSlug) and new format (project: "org/slug")
123
- */
124
- function parseI18nConfig(filePath) {
125
- const content = readFileSync(filePath, "utf-8");
126
- // Try new format first: project: "org/slug"
127
- const projectMatch = content.match(/project:\s*['"]([^'"]+\/[^'"]+)['"]/);
128
- if (projectMatch) {
129
- const [workspaceId, projectSlug] = projectMatch[1].split("/");
130
- const localeMatch = content.match(/defaultLocale:\s*['"]([^'"]+)['"]/);
131
- const cdnMatch = content.match(/cdnBaseUrl:\s*['"]([^'"]+)['"]/);
132
- return {
133
- workspaceId,
134
- projectSlug,
135
- defaultLocale: localeMatch?.[1] || "en",
136
- cdnBaseUrl: cdnMatch?.[1],
137
- };
138
- }
139
- // Fall back to old format: workspaceId + projectSlug (for backward compatibility)
140
- const workspaceMatch = content.match(/workspaceId:\s*['"]([^'"]+)['"]/);
141
- const projectSlugMatch = content.match(/projectSlug:\s*['"]([^'"]+)['"]/);
142
- const localeMatch = content.match(/defaultLocale:\s*['"]([^'"]+)['"]/);
143
- const cdnMatch = content.match(/cdnBaseUrl:\s*['"]([^'"]+)['"]/);
144
- if (!workspaceMatch || !projectSlugMatch) {
145
- throw new Error(`Invalid createI18n config in ${filePath}: missing project or workspaceId/projectSlug`);
146
- }
147
- return {
148
- workspaceId: workspaceMatch[1],
149
- projectSlug: projectSlugMatch[1],
150
- defaultLocale: localeMatch?.[1] || "en",
151
- cdnBaseUrl: cdnMatch?.[1],
152
- };
153
- }
154
- //# sourceMappingURL=context.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}