@gtkx/cli 1.4.0 → 1.5.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 (143) hide show
  1. package/README.md +1 -1
  2. package/dist/builder.d.ts +1 -0
  3. package/dist/builder.d.ts.map +1 -1
  4. package/dist/builder.js +2 -2
  5. package/dist/builder.js.map +1 -1
  6. package/dist/codegen/run-codegen.d.ts +2 -0
  7. package/dist/codegen/run-codegen.d.ts.map +1 -1
  8. package/dist/codegen/run-codegen.js +30 -6
  9. package/dist/codegen/run-codegen.js.map +1 -1
  10. package/dist/commands/codegen.js +1 -1
  11. package/dist/commands/codegen.js.map +1 -1
  12. package/dist/deploy/freedesktop/localize.d.ts +6 -0
  13. package/dist/deploy/freedesktop/localize.d.ts.map +1 -0
  14. package/dist/deploy/freedesktop/localize.js +107 -0
  15. package/dist/deploy/freedesktop/localize.js.map +1 -0
  16. package/dist/deploy/install-hints.d.ts.map +1 -1
  17. package/dist/deploy/install-hints.js +5 -0
  18. package/dist/deploy/install-hints.js.map +1 -1
  19. package/dist/deploy/payload/launcher.d.ts.map +1 -1
  20. package/dist/deploy/payload/launcher.js +2 -0
  21. package/dist/deploy/payload/launcher.js.map +1 -1
  22. package/dist/deploy/payload/stage.d.ts +1 -1
  23. package/dist/deploy/payload/stage.d.ts.map +1 -1
  24. package/dist/deploy/payload/stage.js +20 -11
  25. package/dist/deploy/payload/stage.js.map +1 -1
  26. package/dist/deploy/run-deploy.d.ts.map +1 -1
  27. package/dist/deploy/run-deploy.js +87 -15
  28. package/dist/deploy/run-deploy.js.map +1 -1
  29. package/dist/deploy/targets/flatpak-source.d.ts.map +1 -1
  30. package/dist/deploy/targets/flatpak-source.js +21 -10
  31. package/dist/deploy/targets/flatpak-source.js.map +1 -1
  32. package/dist/deploy/tools.d.ts +6 -1
  33. package/dist/deploy/tools.d.ts.map +1 -1
  34. package/dist/deploy/tools.js +26 -1
  35. package/dist/deploy/tools.js.map +1 -1
  36. package/dist/dev/locale-dir.d.ts +3 -0
  37. package/dist/dev/locale-dir.d.ts.map +1 -0
  38. package/dist/dev/locale-dir.js +17 -0
  39. package/dist/dev/locale-dir.js.map +1 -0
  40. package/dist/dev/runner-main.d.ts.map +1 -1
  41. package/dist/dev/runner-main.js +2 -0
  42. package/dist/dev/runner-main.js.map +1 -1
  43. package/dist/dev/runner.d.ts.map +1 -1
  44. package/dist/dev/runner.js +6 -0
  45. package/dist/dev/runner.js.map +1 -1
  46. package/dist/dev/vite-dev-server.d.ts +1 -0
  47. package/dist/dev/vite-dev-server.d.ts.map +1 -1
  48. package/dist/dev/vite-dev-server.js.map +1 -1
  49. package/dist/i18n/binding-extractor.d.ts +30 -0
  50. package/dist/i18n/binding-extractor.d.ts.map +1 -0
  51. package/dist/i18n/binding-extractor.js +1324 -0
  52. package/dist/i18n/binding-extractor.js.map +1 -0
  53. package/dist/i18n/catalog-template.d.ts +3 -0
  54. package/dist/i18n/catalog-template.d.ts.map +1 -0
  55. package/dist/i18n/catalog-template.js +18 -0
  56. package/dist/i18n/catalog-template.js.map +1 -0
  57. package/dist/i18n/catalogs.d.ts +21 -0
  58. package/dist/i18n/catalogs.d.ts.map +1 -0
  59. package/dist/i18n/catalogs.js +139 -0
  60. package/dist/i18n/catalogs.js.map +1 -0
  61. package/dist/i18n/extractor-plugin.d.ts +8 -0
  62. package/dist/i18n/extractor-plugin.d.ts.map +1 -0
  63. package/dist/i18n/extractor-plugin.js +247 -0
  64. package/dist/i18n/extractor-plugin.js.map +1 -0
  65. package/dist/i18n/metadata-templates.d.ts +11 -0
  66. package/dist/i18n/metadata-templates.d.ts.map +1 -0
  67. package/dist/i18n/metadata-templates.js +11 -0
  68. package/dist/i18n/metadata-templates.js.map +1 -0
  69. package/dist/i18n/source-messages.d.ts +23 -0
  70. package/dist/i18n/source-messages.d.ts.map +1 -0
  71. package/dist/i18n/source-messages.js +403 -0
  72. package/dist/i18n/source-messages.js.map +1 -0
  73. package/dist/i18n/types.d.ts +10 -0
  74. package/dist/i18n/types.d.ts.map +1 -0
  75. package/dist/i18n/types.js +108 -0
  76. package/dist/i18n/types.js.map +1 -0
  77. package/dist/internal/source-imports.d.ts +5 -1
  78. package/dist/internal/source-imports.d.ts.map +1 -1
  79. package/dist/internal/source-imports.js +23 -44
  80. package/dist/internal/source-imports.js.map +1 -1
  81. package/dist/mcp/client.d.ts +0 -1
  82. package/dist/mcp/client.d.ts.map +1 -1
  83. package/dist/mcp/client.js +11 -39
  84. package/dist/mcp/client.js.map +1 -1
  85. package/dist/mcp/handlers.d.ts +2 -1
  86. package/dist/mcp/handlers.d.ts.map +1 -1
  87. package/dist/mcp/handlers.js.map +1 -1
  88. package/dist/settings/render.d.ts +4 -1
  89. package/dist/settings/render.d.ts.map +1 -1
  90. package/dist/settings/render.js +11 -2
  91. package/dist/settings/render.js.map +1 -1
  92. package/dist/settings/schema.d.ts.map +1 -1
  93. package/dist/settings/schema.js +3 -1
  94. package/dist/settings/schema.js.map +1 -1
  95. package/dist/vite-plugins/asset-imports.d.ts.map +1 -1
  96. package/dist/vite-plugins/asset-imports.js +2 -12
  97. package/dist/vite-plugins/asset-imports.js.map +1 -1
  98. package/dist/vite-plugins/i18n.d.ts +5 -0
  99. package/dist/vite-plugins/i18n.d.ts.map +1 -0
  100. package/dist/vite-plugins/i18n.js +88 -0
  101. package/dist/vite-plugins/i18n.js.map +1 -0
  102. package/dist/vite-plugins/index.d.ts +1 -1
  103. package/dist/vite-plugins/index.d.ts.map +1 -1
  104. package/dist/vite-plugins/index.js +3 -1
  105. package/dist/vite-plugins/index.js.map +1 -1
  106. package/dist/vite-plugins/resources.d.ts.map +1 -1
  107. package/dist/vite-plugins/resources.js +10 -55
  108. package/dist/vite-plugins/resources.js.map +1 -1
  109. package/dist/vite-plugins/self-contained.d.ts.map +1 -1
  110. package/dist/vite-plugins/self-contained.js +128 -135
  111. package/dist/vite-plugins/self-contained.js.map +1 -1
  112. package/package.json +10 -9
  113. package/src/builder.ts +3 -2
  114. package/src/codegen/run-codegen.ts +53 -7
  115. package/src/commands/codegen.ts +1 -1
  116. package/src/deploy/freedesktop/localize.ts +144 -0
  117. package/src/deploy/install-hints.ts +5 -0
  118. package/src/deploy/payload/launcher.ts +2 -0
  119. package/src/deploy/payload/stage.ts +35 -10
  120. package/src/deploy/run-deploy.ts +128 -13
  121. package/src/deploy/targets/flatpak-source.ts +33 -10
  122. package/src/deploy/tools.ts +35 -0
  123. package/src/dev/locale-dir.ts +22 -0
  124. package/src/dev/runner-main.ts +2 -0
  125. package/src/dev/runner.ts +8 -0
  126. package/src/dev/vite-dev-server.ts +1 -0
  127. package/src/i18n/binding-extractor.ts +1969 -0
  128. package/src/i18n/catalog-template.ts +24 -0
  129. package/src/i18n/catalogs.ts +216 -0
  130. package/src/i18n/extractor-plugin.ts +413 -0
  131. package/src/i18n/metadata-templates.ts +29 -0
  132. package/src/i18n/source-messages.ts +608 -0
  133. package/src/i18n/types.ts +154 -0
  134. package/src/internal/source-imports.ts +28 -57
  135. package/src/mcp/client.ts +17 -44
  136. package/src/mcp/handlers.ts +7 -6
  137. package/src/settings/render.ts +16 -2
  138. package/src/settings/schema.ts +3 -1
  139. package/src/vite-plugins/asset-imports.ts +3 -15
  140. package/src/vite-plugins/i18n.ts +146 -0
  141. package/src/vite-plugins/index.ts +3 -0
  142. package/src/vite-plugins/resources.ts +10 -72
  143. package/src/vite-plugins/self-contained.ts +150 -169
@@ -1,7 +1,7 @@
1
- import { isRecord, sortStringsBy } from "@gtkx/utils";
1
+ import { sortStringsBy } from "@gtkx/utils";
2
2
  import { readdirSync, readFileSync } from "node:fs";
3
3
  import { extname, join } from "node:path";
4
- import { parseSync } from "vite";
4
+ import { parseSync, Visitor } from "vite";
5
5
  const SOURCE_LANGUAGES = new Map([
6
6
  [".cjs", "jsx"],
7
7
  [".cts", "ts"],
@@ -51,6 +51,11 @@ const sourceFilesIn = (dir, found) => {
51
51
  collectSourceEntry(dir, entry, found);
52
52
  }
53
53
  };
54
+ const discoverSourceFiles = (dir) => {
55
+ const files = [];
56
+ sourceFilesIn(dir, files);
57
+ return sortStringsBy(files, (path) => path);
58
+ };
54
59
  const staticImportSources = (module) => [
55
60
  ...module.staticImports.map((statement) => statement.moduleRequest.value),
56
61
  ...module.staticExports.flatMap((statement) => statement.entries
@@ -67,49 +72,24 @@ const staticRuntimeImportSources = (module) => [
67
72
  .filter((source) => source !== undefined)),
68
73
  ];
69
74
  const templateImportSource = (node) => {
70
- if (!Array.isArray(node.expressions) || node.expressions.length > 0 || !Array.isArray(node.quasis)) {
71
- return null;
72
- }
73
- const quasis = node.quasis;
74
- const first = quasis[0];
75
- if (!isRecord(first) || !isRecord(first.value)) {
76
- return null;
77
- }
78
- return typeof first.value.cooked === "string" ? first.value.cooked : null;
75
+ const [quasi] = node.quasis;
76
+ return quasi === undefined || node.expressions.length > 0 ? null : quasi.value.cooked;
79
77
  };
80
78
  const literalImportSource = (node) => {
81
- if (!isRecord(node)) {
82
- return null;
83
- }
84
- if (node.type === "Literal") {
85
- return typeof node.value === "string" ? node.value : null;
79
+ if (node.type === "TemplateLiteral") {
80
+ return templateImportSource(node);
86
81
  }
87
- return node.type === "TemplateLiteral" ? templateImportSource(node) : null;
82
+ return node.type === "Literal" && typeof node.value === "string" ? node.value : null;
88
83
  };
89
- const collectDynamicImportArray = (nodes, found) => {
90
- for (const child of nodes) {
91
- collectDynamicImportSources(child, found);
92
- }
93
- };
94
- const collectDynamicImportRecord = (node, found) => {
95
- if (node.type === "ImportExpression") {
96
- const source = literalImportSource(node.source);
97
- if (source !== null) {
98
- found.push(source);
99
- }
100
- return;
101
- }
102
- collectDynamicImportArray(Object.values(node), found);
103
- };
104
- const collectDynamicImportSources = (node, found) => {
105
- if (Array.isArray(node)) {
106
- collectDynamicImportArray(node, found);
107
- return;
108
- }
109
- if (!isRecord(node)) {
110
- return;
111
- }
112
- collectDynamicImportRecord(node, found);
84
+ const collectDynamicImportSources = (program, found) => {
85
+ new Visitor({
86
+ ImportExpression: (node) => {
87
+ const source = literalImportSource(node.source);
88
+ if (source !== null) {
89
+ found.push(source);
90
+ }
91
+ },
92
+ }).visit(program);
113
93
  };
114
94
  const parseImportsInWith = (path, staticSources) => {
115
95
  const lang = sourceLanguage(path);
@@ -135,10 +115,9 @@ const parseRuntimeImportsIn = (path) => parseImportsInWith(path, staticRuntimeIm
135
115
  const importsIn = (path) => parseImportsIn(path) ?? [];
136
116
  const importKey = (entry) => `${entry.importer}\0${entry.source}`;
137
117
  const discoverSourceImports = (dir) => {
138
- const files = [];
139
- sourceFilesIn(dir, files);
118
+ const files = discoverSourceFiles(dir);
140
119
  const imports = files.flatMap((path) => importsIn(path));
141
120
  return sortStringsBy(imports, importKey);
142
121
  };
143
- export { discoverSourceImports, parseRuntimeImportsIn };
122
+ export { discoverSourceFiles, discoverSourceImports, parseRuntimeImportsIn, sourceLanguage };
144
123
  //# sourceMappingURL=source-imports.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"source-imports.js","sourceRoot":"","sources":["../../src/internal/source-imports.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ParseResult, ParserOptions } from \"vite\";\nimport { isRecord, sortStringsBy } from \"@gtkx/utils\";\nimport { type Dirent, readdirSync, readFileSync } from \"node:fs\";\nimport { extname, join } from \"node:path\";\nimport { parseSync } from \"vite\";\n\ntype SourceImport = {\n importer: string;\n source: string;\n};\n\ntype SourceLanguage = NonNullable<ParserOptions[\"lang\"]>;\ntype ParsedModule = ParseResult[\"module\"];\n\nconst SOURCE_LANGUAGES: Map<string, SourceLanguage> = new Map([\n [\".cjs\", \"jsx\"],\n [\".cts\", \"ts\"],\n [\".js\", \"jsx\"],\n [\".jsx\", \"jsx\"],\n [\".mjs\", \"jsx\"],\n [\".mts\", \"ts\"],\n [\".ts\", \"ts\"],\n [\".tsx\", \"tsx\"],\n]);\n\nconst EXCLUDED_DIRECTORIES: Set<string> = new Set([\n \".git\",\n \".gtkx\",\n \"build\",\n \"coverage\",\n \"dist\",\n \"node_modules\",\n \"out-tsc\",\n]);\n\nconst sourceLanguage = (path: string): SourceLanguage | undefined => {\n if (path.endsWith(\".d.ts\") || path.endsWith(\".d.cts\") || path.endsWith(\".d.mts\")) {\n return undefined;\n }\n\n return SOURCE_LANGUAGES.get(extname(path).toLowerCase());\n};\n\nconst collectSourceEntry = (dir: string, entry: Dirent, found: string[]): void => {\n const path = join(dir, entry.name);\n\n if (entry.isDirectory()) {\n if (!EXCLUDED_DIRECTORIES.has(entry.name)) {\n sourceFilesIn(path, found);\n }\n\n return;\n }\n\n if (entry.isFile() && sourceLanguage(path) !== undefined) {\n found.push(path);\n }\n};\n\nconst sourceFilesIn = (dir: string, found: string[]): void => {\n let entries: Dirent[];\n\n try {\n entries = readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n collectSourceEntry(dir, entry, found);\n }\n};\n\nconst staticImportSources = (module: ParsedModule): string[] => [\n ...module.staticImports.map((statement) => statement.moduleRequest.value),\n ...module.staticExports.flatMap((statement) =>\n statement.entries\n .map((entry) => entry.moduleRequest?.value)\n .filter((source): source is string => source !== undefined),\n ),\n];\n\nconst staticRuntimeImportSources = (module: ParsedModule): string[] => [\n ...module.staticImports\n .filter((statement) => statement.entries.length === 0 || statement.entries.some((entry) => !entry.isType))\n .map((statement) => statement.moduleRequest.value),\n ...module.staticExports.flatMap((statement) =>\n statement.entries\n .filter((entry) => !entry.isType)\n .map((entry) => entry.moduleRequest?.value)\n .filter((source): source is string => source !== undefined),\n ),\n];\n\nconst templateImportSource = (node: Record<string, unknown>): string | null => {\n if (!Array.isArray(node.expressions) || node.expressions.length > 0 || !Array.isArray(node.quasis)) {\n return null;\n }\n\n const quasis: unknown[] = node.quasis;\n const first: unknown = quasis[0];\n\n if (!isRecord(first) || !isRecord(first.value)) {\n return null;\n }\n\n return typeof first.value.cooked === \"string\" ? first.value.cooked : null;\n};\n\nconst literalImportSource = (node: unknown): string | null => {\n if (!isRecord(node)) {\n return null;\n }\n\n if (node.type === \"Literal\") {\n return typeof node.value === \"string\" ? node.value : null;\n }\n\n return node.type === \"TemplateLiteral\" ? templateImportSource(node) : null;\n};\n\nconst collectDynamicImportArray = (nodes: unknown[], found: string[]): void => {\n for (const child of nodes) {\n collectDynamicImportSources(child, found);\n }\n};\n\nconst collectDynamicImportRecord = (node: Record<string, unknown>, found: string[]): void => {\n if (node.type === \"ImportExpression\") {\n const source = literalImportSource(node.source);\n\n if (source !== null) {\n found.push(source);\n }\n\n return;\n }\n\n collectDynamicImportArray(Object.values(node), found);\n};\n\nconst collectDynamicImportSources = (node: unknown, found: string[]): void => {\n if (Array.isArray(node)) {\n collectDynamicImportArray(node, found);\n\n return;\n }\n\n if (!isRecord(node)) {\n return;\n }\n\n collectDynamicImportRecord(node, found);\n};\n\nconst parseImportsInWith = (\n path: string,\n staticSources: (module: ParsedModule) => string[],\n): SourceImport[] | null => {\n const lang = sourceLanguage(path);\n\n if (lang === undefined) {\n return [];\n }\n\n let parsed: ParseResult;\n\n try {\n parsed = parseSync(path, readFileSync(path, \"utf8\"), { lang });\n } catch {\n return null;\n }\n\n if (parsed.errors.length > 0) {\n return null;\n }\n\n const sources = staticSources(parsed.module);\n collectDynamicImportSources(parsed.program, sources);\n\n return [...new Set(sources)].map((source) => ({ importer: path, source }));\n};\n\nconst parseImportsIn = (path: string): SourceImport[] | null => parseImportsInWith(path, staticImportSources);\n\nconst parseRuntimeImportsIn = (path: string): SourceImport[] | null =>\n parseImportsInWith(path, staticRuntimeImportSources);\n\nconst importsIn = (path: string): SourceImport[] => parseImportsIn(path) ?? [];\nconst importKey = (entry: SourceImport): string => `${entry.importer}\\0${entry.source}`;\n\nconst discoverSourceImports = (dir: string): SourceImport[] => {\n const files: string[] = [];\n sourceFilesIn(dir, files);\n const imports = files.flatMap((path) => importsIn(path));\n\n return sortStringsBy(imports, importKey);\n};\n\nexport { discoverSourceImports, parseRuntimeImportsIn, type SourceImport };\n"]}
1
+ {"version":3,"file":"source-imports.js","sourceRoot":"","sources":["../../src/internal/source-imports.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ESTree, ParseResult, ParserOptions } from \"vite\";\nimport { sortStringsBy } from \"@gtkx/utils\";\nimport { type Dirent, readdirSync, readFileSync } from \"node:fs\";\nimport { extname, join } from \"node:path\";\nimport { parseSync, Visitor } from \"vite\";\n\ntype SourceImport = {\n importer: string;\n source: string;\n};\n\ntype SourceLanguage = NonNullable<ParserOptions[\"lang\"]>;\ntype ParsedModule = ParseResult[\"module\"];\n\nconst SOURCE_LANGUAGES: Map<string, SourceLanguage> = new Map([\n [\".cjs\", \"jsx\"],\n [\".cts\", \"ts\"],\n [\".js\", \"jsx\"],\n [\".jsx\", \"jsx\"],\n [\".mjs\", \"jsx\"],\n [\".mts\", \"ts\"],\n [\".ts\", \"ts\"],\n [\".tsx\", \"tsx\"],\n]);\n\nconst EXCLUDED_DIRECTORIES: Set<string> = new Set([\n \".git\",\n \".gtkx\",\n \"build\",\n \"coverage\",\n \"dist\",\n \"node_modules\",\n \"out-tsc\",\n]);\n\nconst sourceLanguage = (path: string): SourceLanguage | undefined => {\n if (path.endsWith(\".d.ts\") || path.endsWith(\".d.cts\") || path.endsWith(\".d.mts\")) {\n return undefined;\n }\n\n return SOURCE_LANGUAGES.get(extname(path).toLowerCase());\n};\n\nconst collectSourceEntry = (dir: string, entry: Dirent, found: string[]): void => {\n const path = join(dir, entry.name);\n\n if (entry.isDirectory()) {\n if (!EXCLUDED_DIRECTORIES.has(entry.name)) {\n sourceFilesIn(path, found);\n }\n\n return;\n }\n\n if (entry.isFile() && sourceLanguage(path) !== undefined) {\n found.push(path);\n }\n};\n\nconst sourceFilesIn = (dir: string, found: string[]): void => {\n let entries: Dirent[];\n\n try {\n entries = readdirSync(dir, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n collectSourceEntry(dir, entry, found);\n }\n};\n\nconst discoverSourceFiles = (dir: string): string[] => {\n const files: string[] = [];\n sourceFilesIn(dir, files);\n\n return sortStringsBy(files, (path) => path);\n};\n\nconst staticImportSources = (module: ParsedModule): string[] => [\n ...module.staticImports.map((statement) => statement.moduleRequest.value),\n ...module.staticExports.flatMap((statement) =>\n statement.entries\n .map((entry) => entry.moduleRequest?.value)\n .filter((source): source is string => source !== undefined),\n ),\n];\n\nconst staticRuntimeImportSources = (module: ParsedModule): string[] => [\n ...module.staticImports\n .filter((statement) => statement.entries.length === 0 || statement.entries.some((entry) => !entry.isType))\n .map((statement) => statement.moduleRequest.value),\n ...module.staticExports.flatMap((statement) =>\n statement.entries\n .filter((entry) => !entry.isType)\n .map((entry) => entry.moduleRequest?.value)\n .filter((source): source is string => source !== undefined),\n ),\n];\n\nconst templateImportSource = (node: ESTree.TemplateLiteral): string | null => {\n const [quasi] = node.quasis;\n\n return quasi === undefined || node.expressions.length > 0 ? null : quasi.value.cooked;\n};\n\nconst literalImportSource = (node: ESTree.Expression): string | null => {\n if (node.type === \"TemplateLiteral\") {\n return templateImportSource(node);\n }\n\n return node.type === \"Literal\" && typeof node.value === \"string\" ? node.value : null;\n};\n\nconst collectDynamicImportSources = (program: ESTree.Program, found: string[]): void => {\n new Visitor({\n ImportExpression: (node) => {\n const source = literalImportSource(node.source);\n\n if (source !== null) {\n found.push(source);\n }\n },\n }).visit(program);\n};\n\nconst parseImportsInWith = (\n path: string,\n staticSources: (module: ParsedModule) => string[],\n): SourceImport[] | null => {\n const lang = sourceLanguage(path);\n\n if (lang === undefined) {\n return [];\n }\n\n let parsed: ParseResult;\n\n try {\n parsed = parseSync(path, readFileSync(path, \"utf8\"), { lang });\n } catch {\n return null;\n }\n\n if (parsed.errors.length > 0) {\n return null;\n }\n\n const sources = staticSources(parsed.module);\n collectDynamicImportSources(parsed.program, sources);\n\n return [...new Set(sources)].map((source) => ({ importer: path, source }));\n};\n\nconst parseImportsIn = (path: string): SourceImport[] | null => parseImportsInWith(path, staticImportSources);\n\nconst parseRuntimeImportsIn = (path: string): SourceImport[] | null =>\n parseImportsInWith(path, staticRuntimeImportSources);\n\nconst importsIn = (path: string): SourceImport[] => parseImportsIn(path) ?? [];\nconst importKey = (entry: SourceImport): string => `${entry.importer}\\0${entry.source}`;\n\nconst discoverSourceImports = (dir: string): SourceImport[] => {\n const files = discoverSourceFiles(dir);\n const imports = files.flatMap((path) => importsIn(path));\n\n return sortStringsBy(imports, importKey);\n};\n\nexport { discoverSourceFiles, discoverSourceImports, parseRuntimeImportsIn, type SourceImport, sourceLanguage };\n"]}
@@ -19,7 +19,6 @@ declare class McpClient {
19
19
  private attemptConnect;
20
20
  private scheduleReconnect;
21
21
  private register;
22
- private respondToRequest;
23
22
  private handleRequest;
24
23
  connect(): Promise<void>;
25
24
  disconnect(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/mcp/client.ts"],"names":[],"mappings":"AAQA,KAAK,gBAAgB,GAAG;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;CACzB,CAAC;AA2CF,cAAM,SAAS;IACX,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,UAAU,CAAmC;IACrD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,oBAAoB,CAAyC;IACrE,OAAO,CAAC,QAAQ,CAAwB;gBAE5B,OAAO,EAAE,gBAAgB;IAKrC,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,iBAAiB;YAUX,kBAAkB;IAWhC,OAAO,CAAC,cAAc;IA+BtB,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,QAAQ;YAgBF,gBAAgB;YAuBhB,aAAa;IAQrB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB9B,UAAU,IAAI,IAAI;CAwBrB;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/mcp/client.ts"],"names":[],"mappings":"AAcA,KAAK,gBAAgB,GAAG;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;CACzB,CAAC;AAsCF,cAAM,SAAS;IACX,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,UAAU,CAAmC;IACrD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,oBAAoB,CAAyC;IACrE,OAAO,CAAC,QAAQ,CAAwB;gBAE5B,OAAO,EAAE,gBAAgB;IAKrC,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,iBAAiB;YAUX,kBAAkB;IAWhC,OAAO,CAAC,cAAc;IAwBtB,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,QAAQ;IAgBhB,OAAO,CAAC,aAAa;IAYf,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB9B,UAAU,IAAI,IAAI;CAsBrB;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"}
@@ -1,16 +1,13 @@
1
1
  import * as Gio from "@gtkx/gi/gio";
2
2
  import * as Gtk from "@gtkx/gi/gtk";
3
- import { DEFAULT_SOCKET_PATH, ErrorCode, ProtocolConnection, ProtocolError } from "@gtkx/mcp/internal";
4
- import { error, errorMessage, info, normalizeError, warn } from "@gtkx/utils";
3
+ import { DEFAULT_SOCKET_PATH, isConnectionClosedError, ProtocolConnection, } from "@gtkx/mcp/internal";
4
+ import { error, errorMessage, info, normalizeError } from "@gtkx/utils";
5
5
  import * as net from "node:net";
6
6
  import { dispatch } from "./handlers.js";
7
7
  import { WidgetRegistry } from "./widget-registry.js";
8
8
  const RECONNECT_DELAY_MS = 2000;
9
9
  const REGISTER_TIMEOUT_MS = 30_000;
10
10
  const DISCONNECT_ERROR_CODES = new Set(["ENOENT", "ECONNREFUSED", "EPIPE", "ECONNRESET"]);
11
- const toResponseError = (error) => error instanceof ProtocolError
12
- ? error.toErrorObject()
13
- : { code: ErrorCode.INTERNAL_ERROR, message: errorMessage(error) };
14
11
  const connectSettler = (callbacks) => {
15
12
  let isSettled = false;
16
13
  const settle = (notify) => {
@@ -54,7 +51,7 @@ class McpClient {
54
51
  }
55
52
  handleSocketError(socketError) {
56
53
  const code = socketError.code;
57
- if (code !== undefined && DISCONNECT_ERROR_CODES.has(code)) {
54
+ if (isConnectionClosedError(socketError) || (code !== undefined && DISCONNECT_ERROR_CODES.has(code))) {
58
55
  this.scheduleReconnect();
59
56
  }
60
57
  else {
@@ -88,12 +85,7 @@ class McpClient {
88
85
  settle.fail(socketError);
89
86
  },
90
87
  });
91
- connection.on("request", (request) => {
92
- void this.handleRequest(request);
93
- });
94
- connection.on("invalid", ({ error: parseError }) => {
95
- warn(`Received invalid JSON from MCP server: ${parseError.message}`);
96
- });
88
+ connection.fallbackRequestHandler = (request) => this.handleRequest(request);
97
89
  this.socket = socket;
98
90
  this.connection = connection;
99
91
  }
@@ -116,32 +108,13 @@ class McpClient {
116
108
  projectRoot: process.cwd(),
117
109
  }, REGISTER_TIMEOUT_MS);
118
110
  }
119
- async respondToRequest(request) {
120
- const { id, method, params } = request;
121
- const connection = this.connection;
122
- if (!connection) {
123
- return;
124
- }
125
- try {
126
- const defaultApp = Gio.Application.getDefault();
127
- if (!(defaultApp instanceof Gtk.Application)) {
128
- throw new TypeError("Application not initialized");
129
- }
130
- this.registry.refresh();
131
- const result = await dispatch(method, params, { app: defaultApp, registry: this.registry });
132
- connection.write({ id, result });
133
- }
134
- catch (dispatchError) {
135
- connection.write({ id, error: toResponseError(dispatchError) });
136
- }
137
- }
138
- async handleRequest(request) {
139
- try {
140
- await this.respondToRequest(request);
141
- }
142
- catch (requestError) {
143
- error("Error handling request:", requestError);
111
+ handleRequest(request) {
112
+ const defaultApp = Gio.Application.getDefault();
113
+ if (!(defaultApp instanceof Gtk.Application)) {
114
+ throw new TypeError("Application not initialized");
144
115
  }
116
+ this.registry.refresh();
117
+ return dispatch(request.method, request.params, { app: defaultApp, registry: this.registry });
145
118
  }
146
119
  async connect() {
147
120
  return new Promise((resolve, reject) => {
@@ -168,9 +141,8 @@ class McpClient {
168
141
  clearTimeout(this.reconnectTimer);
169
142
  this.reconnectTimer = null;
170
143
  }
171
- this.connection?.rejectPending(new Error("Client disconnected"));
172
144
  if (this.socket) {
173
- this.connection?.write({ id: crypto.randomUUID(), method: "app.unregister" });
145
+ void Promise.allSettled([this.connection?.send("app.unregister")]);
174
146
  this.socket.destroy();
175
147
  this.socket = null;
176
148
  }
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/mcp/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AACpC,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,kBAAkB,EAAE,aAAa,EAAgB,MAAM,oBAAoB,CAAC;AACrH,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAiBtD,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAChC,MAAM,mBAAmB,GAAG,MAAM,CAAC;AACnC,MAAM,sBAAsB,GAAgB,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC;AAEvG,MAAM,eAAe,GAAG,CAAC,KAAc,EAAqD,EAAE,CAC1F,KAAK,YAAY,aAAa;IAC1B,CAAC,CAAC,KAAK,CAAC,aAAa,EAAE;IACvB,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,cAAc,EAAE,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;AAE3E,MAAM,cAAc,GAAG,CAAC,SAA2B,EAAkB,EAAE;IACnE,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,MAAM,MAAM,GAAG,CAAC,MAAkB,EAAQ,EAAE;QACxC,IAAI,SAAS,EAAE,CAAC;YACZ,OAAO;QACX,CAAC;QAED,SAAS,GAAG,IAAI,CAAC;QACjB,MAAM,EAAE,CAAC;IACb,CAAC,CAAC;IAEF,OAAO;QACH,OAAO,EAAE,GAAG,EAAE;YACV,MAAM,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QAC1C,CAAC;QACD,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE;YACd,MAAM,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;QAC/C,CAAC;KACJ,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,SAAS;IACH,MAAM,GAAsB,IAAI,CAAC;IACjC,UAAU,GAA8B,IAAI,CAAC;IAC7C,UAAU,CAAS;IACnB,aAAa,CAAS;IACtB,cAAc,GAA0B,IAAI,CAAC;IAC7C,YAAY,GAAG,KAAK,CAAC;IACrB,UAAU,GAAG,KAAK,CAAC;IACnB,oBAAoB,GAAoC,IAAI,CAAC;IAC7D,QAAQ,GAAG,IAAI,cAAc,EAAE,CAAC;IAExC,YAAY,OAAyB;QACjC,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,mBAAmB,CAAC;QAC5D,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAC/C,CAAC;IAEO,WAAW;QACf,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACpB,IAAI,CAAC,8BAA8B,CAAC,CAAC;YACrC,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAC9B,CAAC;QAED,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,iBAAiB,EAAE,CAAC;IAC7B,CAAC;IAEO,iBAAiB,CAAC,WAAkB;QACxC,MAAM,IAAI,GAAI,WAAqC,CAAC,IAAI,CAAC;QAEzD,IAAI,IAAI,KAAK,SAAS,IAAI,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACzD,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC7B,CAAC;aAAM,CAAC;YACJ,KAAK,CAAC,eAAe,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;QAChD,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,kBAAkB,CAAC,MAAsB;QACnD,IAAI,CAAC;YACD,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;YACtB,IAAI,CAAC,4BAA4B,CAAC,CAAC;YACnC,MAAM,CAAC,OAAO,EAAE,CAAC;QACrB,CAAC;QAAC,OAAO,aAAa,EAAE,CAAC;YACrB,KAAK,CAAC,qCAAqC,EAAE,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC;YAC1E,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC,CAAC;QAC/C,CAAC;IACL,CAAC;IAEO,cAAc,CAAC,YAA8B,EAAE;QACnD,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;QAEzC,MAAM,MAAM,GAAG,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,EAAE;YACtD,IAAI,CAAC,8BAA8B,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;YACtD,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;YACzB,KAAK,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,MAAM,UAAU,GAAG,kBAAkB,CAAC,UAAU,CAAC,MAAM,EAAE;YACrD,OAAO,EAAE,GAAG,EAAE;gBACV,IAAI,CAAC,WAAW,EAAE,CAAC;YACvB,CAAC;YACD,OAAO,EAAE,CAAC,WAAW,EAAE,EAAE;gBACrB,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;gBACpC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC7B,CAAC;SACJ,CAAC,CAAC;QAEH,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE;YACjC,KAAK,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE;YAC/C,IAAI,CAAC,0CAA0C,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC;QACzE,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IACjC,CAAC;IAEO,iBAAiB;QACrB,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACzC,OAAO;QACX,CAAC;QAED,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC,GAAG,EAAE;YAClC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;YAC3B,IAAI,CAAC,cAAc,EAAE,CAAC;QAC1B,CAAC,EAAE,kBAAkB,CAAC,CAAC;IAC3B,CAAC;IAEO,QAAQ;QACZ,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACnB,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC,CAAC;QACnE,CAAC;QAED,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CACvB,cAAc,EACd;YACI,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,WAAW,EAAE,OAAO,CAAC,GAAG,EAAE;SAC7B,EACD,mBAAmB,CACtB,CAAC;IACN,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAAC,OAAgB;QAC3C,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QACvC,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QAEnC,IAAI,CAAC,UAAU,EAAE,CAAC;YACd,OAAO;QACX,CAAC;QAED,IAAI,CAAC;YACD,MAAM,UAAU,GAAG,GAAG,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC;YAEhD,IAAI,CAAC,CAAC,UAAU,YAAY,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC3C,MAAM,IAAI,SAAS,CAAC,6BAA6B,CAAC,CAAC;YACvD,CAAC;YAED,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YACxB,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC5F,UAAU,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QACrC,CAAC;QAAC,OAAO,aAAa,EAAE,CAAC;YACrB,UAAU,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,eAAe,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;QACpE,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,aAAa,CAAC,OAAgB;QACxC,IAAI,CAAC;YACD,MAAM,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACzC,CAAC;QAAC,OAAO,YAAY,EAAE,CAAC;YACpB,KAAK,CAAC,yBAAyB,EAAE,YAAY,CAAC,CAAC;QACnD,CAAC;IACL,CAAC;IAED,KAAK,CAAC,OAAO;QACT,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACzC,IAAI,CAAC,oBAAoB,GAAG,MAAM,CAAC;YAEnC,IAAI,CAAC,cAAc,CAAC;gBAChB,SAAS,EAAE,GAAG,EAAE;oBACZ,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC;oBACjC,OAAO,EAAE,CAAC;gBACd,CAAC;gBACD,OAAO,EAAE,CAAC,YAAY,EAAE,EAAE;oBACtB,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC;oBACjC,MAAM,CAAC,YAAY,CAAC,CAAC;gBACzB,CAAC;aACJ,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC;IAED,UAAU;QACN,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QAEvB,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC5B,IAAI,CAAC,oBAAoB,CAAC,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC,CAAC;YACzF,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC;QACrC,CAAC;QAED,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAClC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC/B,CAAC;QAED,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC;QAEjE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAC;YAC9E,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACtB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACvB,CAAC;QAED,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;IAC9B,CAAC;CACJ;AAED,OAAO,EAAE,SAAS,EAAE,CAAC","sourcesContent":["import * as Gio from \"@gtkx/gi/gio\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport { DEFAULT_SOCKET_PATH, ErrorCode, ProtocolConnection, ProtocolError, type Request } from \"@gtkx/mcp/internal\";\nimport { error, errorMessage, info, normalizeError, warn } from \"@gtkx/utils\";\nimport * as net from \"node:net\";\nimport { dispatch } from \"./handlers.js\";\nimport { WidgetRegistry } from \"./widget-registry.js\";\n\ntype McpClientOptions = {\n socketPath?: string;\n applicationId: string;\n};\n\ntype ConnectCallbacks = {\n onSuccess?: (() => void) | undefined;\n onError?: ((error: Error) => void) | undefined;\n};\n\ntype ConnectSettler = {\n succeed: () => void;\n fail: (error: Error) => void;\n};\n\nconst RECONNECT_DELAY_MS = 2000;\nconst REGISTER_TIMEOUT_MS = 30_000;\nconst DISCONNECT_ERROR_CODES: Set<string> = new Set([\"ENOENT\", \"ECONNREFUSED\", \"EPIPE\", \"ECONNRESET\"]);\n\nconst toResponseError = (error: unknown): { code: number; message: string; data?: unknown } =>\n error instanceof ProtocolError\n ? error.toErrorObject()\n : { code: ErrorCode.INTERNAL_ERROR, message: errorMessage(error) };\n\nconst connectSettler = (callbacks: ConnectCallbacks): ConnectSettler => {\n let isSettled = false;\n\n const settle = (notify: () => void): void => {\n if (isSettled) {\n return;\n }\n\n isSettled = true;\n notify();\n };\n\n return {\n succeed: () => {\n settle(() => callbacks.onSuccess?.());\n },\n fail: (failure) => {\n settle(() => callbacks.onError?.(failure));\n },\n };\n};\n\nclass McpClient {\n private socket: net.Socket | null = null;\n private connection: ProtocolConnection | null = null;\n private socketPath: string;\n private applicationId: string;\n private reconnectTimer: NodeJS.Timeout | null = null;\n private hasConnected = false;\n private isStopping = false;\n private pendingConnectReject: ((error: Error) => void) | null = null;\n private registry = new WidgetRegistry();\n\n constructor(options: McpClientOptions) {\n this.socketPath = options.socketPath ?? DEFAULT_SOCKET_PATH;\n this.applicationId = options.applicationId;\n }\n\n private handleClose(): void {\n if (this.hasConnected) {\n info(\"Disconnected from MCP server\");\n this.hasConnected = false;\n }\n\n this.socket = null;\n this.connection = null;\n this.scheduleReconnect();\n }\n\n private handleSocketError(socketError: Error): void {\n const code = (socketError as NodeJS.ErrnoException).code;\n\n if (code !== undefined && DISCONNECT_ERROR_CODES.has(code)) {\n this.scheduleReconnect();\n } else {\n error(\"Socket error:\", socketError.message);\n }\n }\n\n private async registerWithServer(settle: ConnectSettler): Promise<void> {\n try {\n await this.register();\n info(\"Registered with MCP server\");\n settle.succeed();\n } catch (registerError) {\n error(\"Failed to register with MCP server:\", errorMessage(registerError));\n settle.fail(normalizeError(registerError));\n }\n }\n\n private attemptConnect(callbacks: ConnectCallbacks = {}): void {\n const settle = connectSettler(callbacks);\n\n const socket = net.createConnection(this.socketPath, () => {\n info(`Connected to MCP server at ${this.socketPath}`);\n this.hasConnected = true;\n void this.registerWithServer(settle);\n });\n\n const connection = ProtocolConnection.fromSocket(socket, {\n onClose: () => {\n this.handleClose();\n },\n onError: (socketError) => {\n this.handleSocketError(socketError);\n settle.fail(socketError);\n },\n });\n\n connection.on(\"request\", (request) => {\n void this.handleRequest(request);\n });\n\n connection.on(\"invalid\", ({ error: parseError }) => {\n warn(`Received invalid JSON from MCP server: ${parseError.message}`);\n });\n\n this.socket = socket;\n this.connection = connection;\n }\n\n private scheduleReconnect(): void {\n if (this.reconnectTimer || this.isStopping) {\n return;\n }\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.attemptConnect();\n }, RECONNECT_DELAY_MS);\n }\n\n private register(): Promise<unknown> {\n if (!this.connection) {\n return Promise.reject(new Error(\"Connection not initialized\"));\n }\n\n return this.connection.send(\n \"app.register\",\n {\n applicationId: this.applicationId,\n pid: process.pid,\n projectRoot: process.cwd(),\n },\n REGISTER_TIMEOUT_MS,\n );\n }\n\n private async respondToRequest(request: Request): Promise<void> {\n const { id, method, params } = request;\n const connection = this.connection;\n\n if (!connection) {\n return;\n }\n\n try {\n const defaultApp = Gio.Application.getDefault();\n\n if (!(defaultApp instanceof Gtk.Application)) {\n throw new TypeError(\"Application not initialized\");\n }\n\n this.registry.refresh();\n const result = await dispatch(method, params, { app: defaultApp, registry: this.registry });\n connection.write({ id, result });\n } catch (dispatchError) {\n connection.write({ id, error: toResponseError(dispatchError) });\n }\n }\n\n private async handleRequest(request: Request): Promise<void> {\n try {\n await this.respondToRequest(request);\n } catch (requestError) {\n error(\"Error handling request:\", requestError);\n }\n }\n\n async connect(): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n this.pendingConnectReject = reject;\n\n this.attemptConnect({\n onSuccess: () => {\n this.pendingConnectReject = null;\n resolve();\n },\n onError: (connectError) => {\n this.pendingConnectReject = null;\n reject(connectError);\n },\n });\n });\n }\n\n disconnect(): void {\n this.isStopping = true;\n\n if (this.pendingConnectReject) {\n this.pendingConnectReject(new Error(\"Client disconnected before connection registered\"));\n this.pendingConnectReject = null;\n }\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n this.connection?.rejectPending(new Error(\"Client disconnected\"));\n\n if (this.socket) {\n this.connection?.write({ id: crypto.randomUUID(), method: \"app.unregister\" });\n this.socket.destroy();\n this.socket = null;\n }\n\n this.connection = null;\n this.hasConnected = false;\n }\n}\n\nexport { McpClient };\n"]}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/mcp/client.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Gio from \"@gtkx/gi/gio\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport {\n DEFAULT_SOCKET_PATH,\n isConnectionClosedError,\n type JSONRPCRequest,\n ProtocolConnection,\n type Result,\n} from \"@gtkx/mcp/internal\";\nimport { error, errorMessage, info, normalizeError } from \"@gtkx/utils\";\nimport * as net from \"node:net\";\nimport { dispatch } from \"./handlers.js\";\nimport { WidgetRegistry } from \"./widget-registry.js\";\n\ntype McpClientOptions = {\n socketPath?: string;\n applicationId: string;\n};\n\ntype ConnectCallbacks = {\n onSuccess?: (() => void) | undefined;\n onError?: ((error: Error) => void) | undefined;\n};\n\ntype ConnectSettler = {\n succeed: () => void;\n fail: (error: Error) => void;\n};\n\nconst RECONNECT_DELAY_MS = 2000;\nconst REGISTER_TIMEOUT_MS = 30_000;\nconst DISCONNECT_ERROR_CODES: Set<string> = new Set([\"ENOENT\", \"ECONNREFUSED\", \"EPIPE\", \"ECONNRESET\"]);\n\nconst connectSettler = (callbacks: ConnectCallbacks): ConnectSettler => {\n let isSettled = false;\n\n const settle = (notify: () => void): void => {\n if (isSettled) {\n return;\n }\n\n isSettled = true;\n notify();\n };\n\n return {\n succeed: () => {\n settle(() => callbacks.onSuccess?.());\n },\n fail: (failure) => {\n settle(() => callbacks.onError?.(failure));\n },\n };\n};\n\nclass McpClient {\n private socket: net.Socket | null = null;\n private connection: ProtocolConnection | null = null;\n private socketPath: string;\n private applicationId: string;\n private reconnectTimer: NodeJS.Timeout | null = null;\n private hasConnected = false;\n private isStopping = false;\n private pendingConnectReject: ((error: Error) => void) | null = null;\n private registry = new WidgetRegistry();\n\n constructor(options: McpClientOptions) {\n this.socketPath = options.socketPath ?? DEFAULT_SOCKET_PATH;\n this.applicationId = options.applicationId;\n }\n\n private handleClose(): void {\n if (this.hasConnected) {\n info(\"Disconnected from MCP server\");\n this.hasConnected = false;\n }\n\n this.socket = null;\n this.connection = null;\n this.scheduleReconnect();\n }\n\n private handleSocketError(socketError: Error): void {\n const code = (socketError as NodeJS.ErrnoException).code;\n\n if (isConnectionClosedError(socketError) || (code !== undefined && DISCONNECT_ERROR_CODES.has(code))) {\n this.scheduleReconnect();\n } else {\n error(\"Socket error:\", socketError.message);\n }\n }\n\n private async registerWithServer(settle: ConnectSettler): Promise<void> {\n try {\n await this.register();\n info(\"Registered with MCP server\");\n settle.succeed();\n } catch (registerError) {\n error(\"Failed to register with MCP server:\", errorMessage(registerError));\n settle.fail(normalizeError(registerError));\n }\n }\n\n private attemptConnect(callbacks: ConnectCallbacks = {}): void {\n const settle = connectSettler(callbacks);\n\n const socket = net.createConnection(this.socketPath, () => {\n info(`Connected to MCP server at ${this.socketPath}`);\n this.hasConnected = true;\n void this.registerWithServer(settle);\n });\n\n const connection = ProtocolConnection.fromSocket(socket, {\n onClose: () => {\n this.handleClose();\n },\n onError: (socketError) => {\n this.handleSocketError(socketError);\n settle.fail(socketError);\n },\n });\n\n connection.fallbackRequestHandler = (request) => this.handleRequest(request);\n this.socket = socket;\n this.connection = connection;\n }\n\n private scheduleReconnect(): void {\n if (this.reconnectTimer || this.isStopping) {\n return;\n }\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.attemptConnect();\n }, RECONNECT_DELAY_MS);\n }\n\n private register(): Promise<unknown> {\n if (!this.connection) {\n return Promise.reject(new Error(\"Connection not initialized\"));\n }\n\n return this.connection.send(\n \"app.register\",\n {\n applicationId: this.applicationId,\n pid: process.pid,\n projectRoot: process.cwd(),\n },\n REGISTER_TIMEOUT_MS,\n );\n }\n\n private handleRequest(request: JSONRPCRequest): Promise<Result> {\n const defaultApp = Gio.Application.getDefault();\n\n if (!(defaultApp instanceof Gtk.Application)) {\n throw new TypeError(\"Application not initialized\");\n }\n\n this.registry.refresh();\n\n return dispatch(request.method, request.params, { app: defaultApp, registry: this.registry });\n }\n\n async connect(): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n this.pendingConnectReject = reject;\n\n this.attemptConnect({\n onSuccess: () => {\n this.pendingConnectReject = null;\n resolve();\n },\n onError: (connectError) => {\n this.pendingConnectReject = null;\n reject(connectError);\n },\n });\n });\n }\n\n disconnect(): void {\n this.isStopping = true;\n\n if (this.pendingConnectReject) {\n this.pendingConnectReject(new Error(\"Client disconnected before connection registered\"));\n this.pendingConnectReject = null;\n }\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n if (this.socket) {\n void Promise.allSettled([this.connection?.send(\"app.unregister\")]);\n this.socket.destroy();\n this.socket = null;\n }\n\n this.connection = null;\n this.hasConnected = false;\n }\n}\n\nexport { McpClient };\n"]}
@@ -1,9 +1,10 @@
1
1
  import * as Gtk from "@gtkx/gi/gtk";
2
+ import { type Result } from "@gtkx/mcp/internal";
2
3
  import type { WidgetRegistry } from "./widget-registry.js";
3
4
  type HandlerContext = {
4
5
  app: Gtk.Application;
5
6
  registry: WidgetRegistry;
6
7
  };
7
- declare const dispatch: (method: string, params: unknown, ctx: HandlerContext) => Promise<unknown>;
8
+ declare const dispatch: (method: string, params: unknown, ctx: HandlerContext) => Promise<Result>;
8
9
  export { dispatch };
9
10
  //# sourceMappingURL=handlers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../src/mcp/handlers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAUpC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAK3D,KAAK,cAAc,GAAG;IAClB,GAAG,EAAE,GAAG,CAAC,WAAW,CAAC;IACrB,QAAQ,EAAE,cAAc,CAAC;CAC5B,CAAC;AA6PF,QAAA,MAAM,QAAQ,GAAU,QAAQ,MAAM,EAAE,QAAQ,OAAO,EAAE,KAAK,cAAc,KAAG,OAAO,CAAC,OAAO,CAM7F,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAE,CAAC"}
1
+ {"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../src/mcp/handlers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AACpC,OAAO,EAIH,KAAK,MAAM,EAKd,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAK3D,KAAK,cAAc,GAAG;IAClB,GAAG,EAAE,GAAG,CAAC,WAAW,CAAC;IACrB,QAAQ,EAAE,cAAc,CAAC;CAC5B,CAAC;AA6PF,QAAA,MAAM,QAAQ,GAAU,QAAQ,MAAM,EAAE,QAAQ,OAAO,EAAE,KAAK,cAAc,KAAG,OAAO,CAAC,MAAM,CAM5F,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"handlers.js","sourceRoot":"","sources":["../../src/mcp/handlers.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Gtk from \"@gtkx/gi/gtk\";\nimport {\n invalidRequestError,\n methodNotFoundError,\n type ParamsSchema,\n type ServerInitiatedMethod,\n type ServerRequestParams,\n ServerRequestParamsSchemas,\n widgetNotFoundError,\n} from \"@gtkx/mcp/internal\";\nimport type { WidgetRegistry } from \"./widget-registry.js\";\nimport { serializeWidget } from \"./serialize-widget.js\";\nimport { loadTestingModule, type TestingModule } from \"./testing-loader.js\";\nimport { readWidgetProperties } from \"./widget-properties.js\";\n\ntype HandlerContext = {\n app: Gtk.Application;\n registry: WidgetRegistry;\n};\n\ntype ValidatedHandler = (ctx: HandlerContext, params: unknown) => Promise<unknown>;\ntype WidgetTarget = { testing: TestingModule; widget: Gtk.Widget };\ntype WidgetParams = { widgetId?: string | undefined };\ntype TargetedHandler<Params> = (ctx: HandlerContext, target: WidgetTarget, params: Params) => Promise<unknown>;\ntype QueryParams = ServerRequestParams<\"widget.query\">;\ntype QueryBy = QueryParams[\"by\"];\ntype QueryRunner = (testing: TestingModule, app: Gtk.Application, params: QueryParams) => Promise<Gtk.Widget[]>;\n\nconst HANDLERS: Record<ServerInitiatedMethod, ValidatedHandler> = {\n \"app.getWindows\": validated(ServerRequestParamsSchemas[\"app.getWindows\"], ({ registry }) =>\n Promise.resolve({\n windows: registry.toplevels().map((window) => ({\n id: registry.getOrCreateId(window),\n title: window.getTitle(),\n })),\n })),\n \"widget.getTree\": validated(ServerRequestParamsSchemas[\"widget.getTree\"], async ({ app, registry }, params) => {\n const testing = await loadTestingModule();\n const container = params.rootId === undefined ? app : requireWidget(registry, params.rootId);\n\n return {\n tree: testing.prettyWidget(container, {\n getId: (w) => registry.getOrCreateId(w),\n shouldHighlight: false,\n ...((params.maxDepth !== undefined) && { maxDepth: params.maxDepth }),\n }),\n };\n }),\n \"widget.query\": validated(ServerRequestParamsSchemas[\"widget.query\"], handleQuery),\n \"widget.getProps\": targeted(\n ServerRequestParamsSchemas[\"widget.getProps\"],\n ({ registry }, { testing, widget }, params) =>\n Promise.resolve({\n ...(params.properties !== undefined && {\n properties: readWidgetProperties(widget, params.properties, registry),\n }),\n ...serializeWidget(widget, (target) => registry.getOrCreateId(target), testing, params.maxDepth),\n }),\n ),\n \"widget.click\": targeted(ServerRequestParamsSchemas[\"widget.click\"], async (_ctx, { testing, widget }) => {\n await testing.userEvent.click(widget);\n\n return { success: true };\n }),\n \"widget.type\": targeted(ServerRequestParamsSchemas[\"widget.type\"], async (_ctx, { testing, widget }, params) => {\n if (params.clear) {\n await testing.userEvent.clear(widget);\n }\n\n await testing.userEvent.type(widget, params.text);\n\n return { success: true };\n }),\n \"widget.fireEvent\": targeted(\n ServerRequestParamsSchemas[\"widget.fireEvent\"],\n async (_ctx, { testing, widget }, params) => {\n const signalArgs = (params.args ?? []).map((arg) => extractSignalArg(arg));\n const isRealized = widget.getRealized();\n const isMapped = widget.getMapped();\n const isSensitive = widget.getSensitive();\n await testing.fireEvent(widget, params.signal, ...signalArgs);\n\n return {\n signal: params.signal,\n isRealized,\n isMapped,\n isSensitive,\n note: emissionNote(isRealized, isMapped),\n };\n },\n ),\n \"widget.screenshot\": validated(ServerRequestParamsSchemas[\"widget.screenshot\"], handleScreenshot),\n};\n\nconst QUERY_RUNNERS: Record<QueryBy, QueryRunner> = {\n role: runRoleQuery,\n text: runTextQuery,\n name: runNameQuery,\n labelText: runLabelTextQuery,\n};\n\nconst SEARCHED_BY: Record<QueryBy, string> = {\n role: \"the accessible role, narrowed by any options given\",\n text: \"the text the widget renders\",\n name:\n \"the widget name (gtk_widget_get_name, which reports the GType name such as \\\"GtkButton\\\" when no name \" +\n \"was set), the accessible label, and the text the widget renders\",\n labelText: \"the accessible label, the labelled-by relation, and the label whose mnemonic targets the widget\",\n};\n\nfunction validated<Params>(\n schema: ParamsSchema<Params>,\n handler: (ctx: HandlerContext, params: Params) => Promise<unknown>,\n): ValidatedHandler {\n return (ctx, params) => {\n const parsed = schema.safeParse(params ?? {});\n\n if (!parsed.success) {\n throw invalidRequestError(parsed.error.message);\n }\n\n return handler(ctx, parsed.data);\n };\n}\n\nfunction targeted<Params extends WidgetParams>(\n schema: ParamsSchema<Params>,\n handler: TargetedHandler<Params>,\n): ValidatedHandler {\n return validated(schema, async (ctx, params) =>\n handler(ctx, await widgetTarget(ctx.registry, params.widgetId), params));\n}\n\nconst widgetTarget = async (registry: WidgetRegistry, widgetId: string | undefined): Promise<WidgetTarget> => ({\n testing: await loadTestingModule(),\n widget: requireWidget(registry, widgetId),\n});\n\nconst requireWidget = (registry: WidgetRegistry, widgetId: string | undefined): Gtk.Widget => {\n if (widgetId === undefined) {\n throw widgetNotFoundError(\"undefined\");\n }\n\n const widget = registry.get(widgetId);\n\n if (!widget) {\n throw widgetNotFoundError(widgetId);\n }\n\n return widget;\n};\n\nconst extractSignalArg = (arg: unknown): unknown => {\n const isTypedArg = typeof arg === \"object\" && arg !== null && \"type\" in arg && \"value\" in arg;\n\n return isTypedArg ? (arg as { value: unknown }).value : arg;\n};\n\nconst emissionNote = (isRealized: boolean, isMapped: boolean): string => {\n if (isRealized && isMapped) {\n return (\n \"The signal was emitted. Default handlers that animate, such as a button activate, settle \" +\n \"asynchronously, so read the widget again rather than assuming the effect has landed.\"\n );\n }\n\n return (\n \"The signal was emitted on a widget that is not realized and mapped, so a default handler that \" +\n \"requires a drawn widget does nothing. Present the containing window or open the containing \" +\n \"popover first, then fire the signal again.\"\n );\n};\n\nconst resolveRole = (value: string | number): Gtk.AccessibleRole | undefined => {\n if (typeof value === \"number\") {\n return value;\n }\n\n const resolved = Gtk.AccessibleRole[value.toUpperCase() as keyof typeof Gtk.AccessibleRole];\n\n return typeof resolved === \"number\" ? resolved : undefined;\n};\n\nconst matchesOrEmpty = async (find: () => Promise<Gtk.Widget[]>): Promise<Gtk.Widget[]> => {\n try {\n return await find();\n } catch {\n return [];\n }\n};\n\nfunction runRoleQuery(testing: TestingModule, app: Gtk.Application, params: QueryParams): Promise<Gtk.Widget[]> {\n const roleValue = resolveRole(params.value);\n\n if (roleValue === undefined) {\n throw invalidRequestError(\n `Unknown accessible role \"${String(params.value)}\"; use the lowercase role shown in the ` +\n \"widget tree, e.g. \\\"button\\\", \\\"list\\\", \\\"list_item\\\", or \\\"checkbox\\\".\",\n );\n }\n\n return matchesOrEmpty(() => testing.findAllByRole(app, roleValue, params.options));\n}\n\nfunction runTextQuery(testing: TestingModule, app: Gtk.Application, params: QueryParams): Promise<Gtk.Widget[]> {\n return matchesOrEmpty(() => testing.findAllByText(app, String(params.value), params.options));\n}\n\nfunction runLabelTextQuery(testing: TestingModule, app: Gtk.Application, params: QueryParams): Promise<Gtk.Widget[]> {\n return matchesOrEmpty(() => testing.findAllByLabelText(app, String(params.value), params.options));\n}\n\nasync function runNameQuery(\n testing: TestingModule,\n app: Gtk.Application,\n params: QueryParams,\n): Promise<Gtk.Widget[]> {\n const matches = await Promise.all([\n matchesOrEmpty(() => testing.findAllByName(app, String(params.value), params.options)),\n runLabelTextQuery(testing, app, params),\n runTextQuery(testing, app, params),\n ]);\n\n return [...new Set(matches.flat())];\n}\n\nconst emptyQueryHint = (params: QueryParams): string =>\n `Nothing matched by:\"${params.by}\" value:\"${String(params.value)}\", which compared ${SEARCHED_BY[params.by]}. ` +\n \"Call gtkx_get_widget_tree to see what is mounted; by:\\\"name\\\" is the widest match, and by:\\\"role\\\" accepts \" +\n \"options.name to match the accessible name of a known role.\";\n\nasync function handleQuery({ app, registry }: HandlerContext, params: QueryParams): Promise<unknown> {\n const testing = await loadTestingModule();\n const widgets = await QUERY_RUNNERS[params.by](testing, app, params);\n const resolveId = (widget: Gtk.Widget): string => registry.getOrCreateId(widget);\n\n return {\n widgets: widgets.map((widget) => serializeWidget(widget, resolveId, testing, 0)),\n searched: SEARCHED_BY[params.by],\n ...(widgets.length === 0 && { hint: emptyQueryHint(params) }),\n };\n}\n\nconst defaultScreenshotTarget = (registry: WidgetRegistry): Gtk.Widget => {\n const [toplevel] = registry.toplevels();\n\n if (!toplevel) {\n throw new Error(\"No windows available for screenshot\");\n }\n\n return toplevel;\n};\n\nasync function handleScreenshot(\n { registry }: HandlerContext,\n params: ServerRequestParams<\"widget.screenshot\">,\n): Promise<unknown> {\n const testing = await loadTestingModule();\n const target = params.windowId ? requireWidget(registry, params.windowId) : defaultScreenshotTarget(registry);\n const result = await testing.screenshot(target, { path: params.path });\n\n if (params.path) {\n return { data: result.data, mimeType: result.mimeType, savedPath: params.path };\n }\n\n return { data: result.data, mimeType: result.mimeType };\n}\n\nconst isServerInitiatedMethod = (method: string): method is ServerInitiatedMethod =>\n Object.hasOwn(ServerRequestParamsSchemas, method);\n\nconst dispatch = async (method: string, params: unknown, ctx: HandlerContext): Promise<unknown> => {\n if (!isServerInitiatedMethod(method)) {\n throw methodNotFoundError(method);\n }\n\n return HANDLERS[method](ctx, params);\n};\n\nexport { dispatch };\n"]}
1
+ {"version":3,"file":"handlers.js","sourceRoot":"","sources":["../../src/mcp/handlers.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Gtk from \"@gtkx/gi/gtk\";\nimport {\n invalidRequestError,\n methodNotFoundError,\n type ParamsSchema,\n type Result,\n type ServerInitiatedMethod,\n type ServerRequestParams,\n ServerRequestParamsSchemas,\n widgetNotFoundError,\n} from \"@gtkx/mcp/internal\";\nimport type { WidgetRegistry } from \"./widget-registry.js\";\nimport { serializeWidget } from \"./serialize-widget.js\";\nimport { loadTestingModule, type TestingModule } from \"./testing-loader.js\";\nimport { readWidgetProperties } from \"./widget-properties.js\";\n\ntype HandlerContext = {\n app: Gtk.Application;\n registry: WidgetRegistry;\n};\n\ntype ValidatedHandler = (ctx: HandlerContext, params: unknown) => Promise<Result>;\ntype WidgetTarget = { testing: TestingModule; widget: Gtk.Widget };\ntype WidgetParams = { widgetId?: string | undefined };\ntype TargetedHandler<Params> = (ctx: HandlerContext, target: WidgetTarget, params: Params) => Promise<Result>;\ntype QueryParams = ServerRequestParams<\"widget.query\">;\ntype QueryBy = QueryParams[\"by\"];\ntype QueryRunner = (testing: TestingModule, app: Gtk.Application, params: QueryParams) => Promise<Gtk.Widget[]>;\n\nconst HANDLERS: Record<ServerInitiatedMethod, ValidatedHandler> = {\n \"app.getWindows\": validated(ServerRequestParamsSchemas[\"app.getWindows\"], ({ registry }) =>\n Promise.resolve({\n windows: registry.toplevels().map((window) => ({\n id: registry.getOrCreateId(window),\n title: window.getTitle(),\n })),\n })),\n \"widget.getTree\": validated(ServerRequestParamsSchemas[\"widget.getTree\"], async ({ app, registry }, params) => {\n const testing = await loadTestingModule();\n const container = params.rootId === undefined ? app : requireWidget(registry, params.rootId);\n\n return {\n tree: testing.prettyWidget(container, {\n getId: (w) => registry.getOrCreateId(w),\n shouldHighlight: false,\n ...((params.maxDepth !== undefined) && { maxDepth: params.maxDepth }),\n }),\n };\n }),\n \"widget.query\": validated(ServerRequestParamsSchemas[\"widget.query\"], handleQuery),\n \"widget.getProps\": targeted(\n ServerRequestParamsSchemas[\"widget.getProps\"],\n ({ registry }, { testing, widget }, params) =>\n Promise.resolve({\n ...(params.properties !== undefined && {\n properties: readWidgetProperties(widget, params.properties, registry),\n }),\n ...serializeWidget(widget, (target) => registry.getOrCreateId(target), testing, params.maxDepth),\n }),\n ),\n \"widget.click\": targeted(ServerRequestParamsSchemas[\"widget.click\"], async (_ctx, { testing, widget }) => {\n await testing.userEvent.click(widget);\n\n return { success: true };\n }),\n \"widget.type\": targeted(ServerRequestParamsSchemas[\"widget.type\"], async (_ctx, { testing, widget }, params) => {\n if (params.clear) {\n await testing.userEvent.clear(widget);\n }\n\n await testing.userEvent.type(widget, params.text);\n\n return { success: true };\n }),\n \"widget.fireEvent\": targeted(\n ServerRequestParamsSchemas[\"widget.fireEvent\"],\n async (_ctx, { testing, widget }, params) => {\n const signalArgs = (params.args ?? []).map((arg) => extractSignalArg(arg));\n const isRealized = widget.getRealized();\n const isMapped = widget.getMapped();\n const isSensitive = widget.getSensitive();\n await testing.fireEvent(widget, params.signal, ...signalArgs);\n\n return {\n signal: params.signal,\n isRealized,\n isMapped,\n isSensitive,\n note: emissionNote(isRealized, isMapped),\n };\n },\n ),\n \"widget.screenshot\": validated(ServerRequestParamsSchemas[\"widget.screenshot\"], handleScreenshot),\n};\n\nconst QUERY_RUNNERS: Record<QueryBy, QueryRunner> = {\n role: runRoleQuery,\n text: runTextQuery,\n name: runNameQuery,\n labelText: runLabelTextQuery,\n};\n\nconst SEARCHED_BY: Record<QueryBy, string> = {\n role: \"the accessible role, narrowed by any options given\",\n text: \"the text the widget renders\",\n name:\n \"the widget name (gtk_widget_get_name, which reports the GType name such as \\\"GtkButton\\\" when no name \" +\n \"was set), the accessible label, and the text the widget renders\",\n labelText: \"the accessible label, the labelled-by relation, and the label whose mnemonic targets the widget\",\n};\n\nfunction validated<Params>(\n schema: ParamsSchema<Params>,\n handler: (ctx: HandlerContext, params: Params) => Promise<Result>,\n): ValidatedHandler {\n return (ctx, params) => {\n const parsed = schema.safeParse(params ?? {});\n\n if (!parsed.success) {\n throw invalidRequestError(parsed.error.message);\n }\n\n return handler(ctx, parsed.data);\n };\n}\n\nfunction targeted<Params extends WidgetParams>(\n schema: ParamsSchema<Params>,\n handler: TargetedHandler<Params>,\n): ValidatedHandler {\n return validated(schema, async (ctx, params) =>\n handler(ctx, await widgetTarget(ctx.registry, params.widgetId), params));\n}\n\nconst widgetTarget = async (registry: WidgetRegistry, widgetId: string | undefined): Promise<WidgetTarget> => ({\n testing: await loadTestingModule(),\n widget: requireWidget(registry, widgetId),\n});\n\nconst requireWidget = (registry: WidgetRegistry, widgetId: string | undefined): Gtk.Widget => {\n if (widgetId === undefined) {\n throw widgetNotFoundError(\"undefined\");\n }\n\n const widget = registry.get(widgetId);\n\n if (!widget) {\n throw widgetNotFoundError(widgetId);\n }\n\n return widget;\n};\n\nconst extractSignalArg = (arg: unknown): unknown => {\n const isTypedArg = typeof arg === \"object\" && arg !== null && \"type\" in arg && \"value\" in arg;\n\n return isTypedArg ? (arg as { value: unknown }).value : arg;\n};\n\nconst emissionNote = (isRealized: boolean, isMapped: boolean): string => {\n if (isRealized && isMapped) {\n return (\n \"The signal was emitted. Default handlers that animate, such as a button activate, settle \" +\n \"asynchronously, so read the widget again rather than assuming the effect has landed.\"\n );\n }\n\n return (\n \"The signal was emitted on a widget that is not realized and mapped, so a default handler that \" +\n \"requires a drawn widget does nothing. Present the containing window or open the containing \" +\n \"popover first, then fire the signal again.\"\n );\n};\n\nconst resolveRole = (value: string | number): Gtk.AccessibleRole | undefined => {\n if (typeof value === \"number\") {\n return value;\n }\n\n const resolved = Gtk.AccessibleRole[value.toUpperCase() as keyof typeof Gtk.AccessibleRole];\n\n return typeof resolved === \"number\" ? resolved : undefined;\n};\n\nconst matchesOrEmpty = async (find: () => Promise<Gtk.Widget[]>): Promise<Gtk.Widget[]> => {\n try {\n return await find();\n } catch {\n return [];\n }\n};\n\nfunction runRoleQuery(testing: TestingModule, app: Gtk.Application, params: QueryParams): Promise<Gtk.Widget[]> {\n const roleValue = resolveRole(params.value);\n\n if (roleValue === undefined) {\n throw invalidRequestError(\n `Unknown accessible role \"${String(params.value)}\"; use the lowercase role shown in the ` +\n \"widget tree, e.g. \\\"button\\\", \\\"list\\\", \\\"list_item\\\", or \\\"checkbox\\\".\",\n );\n }\n\n return matchesOrEmpty(() => testing.findAllByRole(app, roleValue, params.options));\n}\n\nfunction runTextQuery(testing: TestingModule, app: Gtk.Application, params: QueryParams): Promise<Gtk.Widget[]> {\n return matchesOrEmpty(() => testing.findAllByText(app, String(params.value), params.options));\n}\n\nfunction runLabelTextQuery(testing: TestingModule, app: Gtk.Application, params: QueryParams): Promise<Gtk.Widget[]> {\n return matchesOrEmpty(() => testing.findAllByLabelText(app, String(params.value), params.options));\n}\n\nasync function runNameQuery(\n testing: TestingModule,\n app: Gtk.Application,\n params: QueryParams,\n): Promise<Gtk.Widget[]> {\n const matches = await Promise.all([\n matchesOrEmpty(() => testing.findAllByName(app, String(params.value), params.options)),\n runLabelTextQuery(testing, app, params),\n runTextQuery(testing, app, params),\n ]);\n\n return [...new Set(matches.flat())];\n}\n\nconst emptyQueryHint = (params: QueryParams): string =>\n `Nothing matched by:\"${params.by}\" value:\"${String(params.value)}\", which compared ${SEARCHED_BY[params.by]}. ` +\n \"Call gtkx_get_widget_tree to see what is mounted; by:\\\"name\\\" is the widest match, and by:\\\"role\\\" accepts \" +\n \"options.name to match the accessible name of a known role.\";\n\nasync function handleQuery({ app, registry }: HandlerContext, params: QueryParams): Promise<Result> {\n const testing = await loadTestingModule();\n const widgets = await QUERY_RUNNERS[params.by](testing, app, params);\n const resolveId = (widget: Gtk.Widget): string => registry.getOrCreateId(widget);\n\n return {\n widgets: widgets.map((widget) => serializeWidget(widget, resolveId, testing, 0)),\n searched: SEARCHED_BY[params.by],\n ...(widgets.length === 0 && { hint: emptyQueryHint(params) }),\n };\n}\n\nconst defaultScreenshotTarget = (registry: WidgetRegistry): Gtk.Widget => {\n const [toplevel] = registry.toplevels();\n\n if (!toplevel) {\n throw new Error(\"No windows available for screenshot\");\n }\n\n return toplevel;\n};\n\nasync function handleScreenshot(\n { registry }: HandlerContext,\n params: ServerRequestParams<\"widget.screenshot\">,\n): Promise<Result> {\n const testing = await loadTestingModule();\n const target = params.windowId ? requireWidget(registry, params.windowId) : defaultScreenshotTarget(registry);\n const result = await testing.screenshot(target, { path: params.path });\n\n if (params.path) {\n return { data: result.data, mimeType: result.mimeType, savedPath: params.path };\n }\n\n return { data: result.data, mimeType: result.mimeType };\n}\n\nconst isServerInitiatedMethod = (method: string): method is ServerInitiatedMethod =>\n Object.hasOwn(ServerRequestParamsSchemas, method);\n\nconst dispatch = async (method: string, params: unknown, ctx: HandlerContext): Promise<Result> => {\n if (!isServerInitiatedMethod(method)) {\n throw methodNotFoundError(method);\n }\n\n return HANDLERS[method](ctx, params);\n};\n\nexport { dispatch };\n"]}
@@ -5,7 +5,10 @@ type EnvAssetDeclarations = {
5
5
  legacy: string[];
6
6
  resources: string[];
7
7
  };
8
+ type EnvModuleOptions = {
9
+ references?: string[];
10
+ };
8
11
  declare const renderRuntimeModule: (file: ParsedSchemaFile) => string;
9
- declare const renderEnvModule: (files: ParsedSchemaFile[], assetDeclarations?: EnvAssetDeclarations) => string;
12
+ declare const renderEnvModule: (files: ParsedSchemaFile[], assetDeclarations?: EnvAssetDeclarations, options?: EnvModuleOptions) => string;
10
13
  export { renderRuntimeModule, renderEnvModule };
11
14
  //# sourceMappingURL=render.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/settings/render.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAA2B,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAO7E,KAAK,oBAAoB,GAAG;IACxB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AA6DF,QAAA,MAAM,mBAAmB,GAAI,MAAM,gBAAgB,KAAG,MA0BrD,CAAC;AA6HF,QAAA,MAAM,eAAe,GACjB,OAAO,gBAAgB,EAAE,EACzB,oBAAoB,oBAAoB,KACzC,MAcF,CAAC;AAEF,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/settings/render.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAA2B,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAO7E,KAAK,oBAAoB,GAAG;IACxB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACpB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB,CAAC;AA6DF,QAAA,MAAM,mBAAmB,GAAI,MAAM,gBAAgB,KAAG,MA0BrD,CAAC;AA6HF,QAAA,MAAM,eAAe,GACjB,OAAO,gBAAgB,EAAE,EACzB,oBAAoB,oBAAoB,EACxC,UAAS,gBAAqB,KAC/B,MAuBF,CAAC;AAEF,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,CAAC"}
@@ -155,7 +155,7 @@ const renderBlockedAssetModule = (specifier) => [
155
155
  " export default assetImportRequiresResourceOrUrlQuery;",
156
156
  "}",
157
157
  ].join("\n");
158
- const renderEnvModule = (files, assetDeclarations) => {
158
+ const renderEnvModule = (files, assetDeclarations, options = {}) => {
159
159
  const assets = assetDeclarations ?? { blocked: [], icons: [], legacy: [], resources: [] };
160
160
  const usedNames = new Set();
161
161
  const schemas = files
@@ -165,7 +165,16 @@ const renderEnvModule = (files, assetDeclarations) => {
165
165
  const icons = assets.icons.map((specifier) => renderIconModule(specifier));
166
166
  const legacy = assets.legacy.map((specifier) => renderLegacyAssetModule(specifier));
167
167
  const resources = assets.resources.map((specifier) => renderResourceModule(specifier));
168
- return `${[GTKX_ENV_MODULE_HEADER, ...blocked, ...icons, ...legacy, ...resources, ...schemas].join("\n\n")}\n`;
168
+ const references = (options.references ?? []).map((path) => `/// <reference path=${JSON.stringify(path)} />`);
169
+ return `${[
170
+ GTKX_ENV_MODULE_HEADER,
171
+ ...references,
172
+ ...blocked,
173
+ ...icons,
174
+ ...legacy,
175
+ ...resources,
176
+ ...schemas,
177
+ ].join("\n\n")}\n`;
169
178
  };
170
179
  export { renderRuntimeModule, renderEnvModule };
171
180
  //# sourceMappingURL=render.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/settings/render.ts"],"names":[],"mappings":"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","sourcesContent":["import { camelCase, sanitizeIdentifier, upperFirst } from \"@gtkx/utils\";\nimport type { ParsedKey, ParsedSchema, ParsedSchemaFile } from \"./parser.js\";\n\ntype NamedSchema = {\n schema: ParsedSchema;\n exportName: string;\n};\n\ntype EnvAssetDeclarations = {\n blocked: string[];\n icons: string[];\n legacy: string[];\n resources: string[];\n};\n\nconst GTKX_ENV_MODULE_HEADER = `/**\n * Project import declarations generated by GTKX. Regenerated by\n * \\`gtkx codegen\\`, \\`gtkx dev\\`, and \\`gtkx build\\`; do not edit.\n */`;\n\nconst ENUM_KIND = \"enum\";\nconst FLAGS_KIND = \"flags\";\nconst ID_SEPARATOR = /[._]/;\nconst NAME_SEPARATOR = \"_\";\n\nconst toJsStringLiteral = (value: string): string =>\n JSON.stringify(value).replaceAll(\"\\u{2028}\", String.raw`\\u2028`).replaceAll(\"\\u{2029}\", String.raw`\\u2029`);\n\nconst getExportName = (schemaId: string): string =>\n sanitizeIdentifier(schemaId.split(ID_SEPARATOR).map((part) => camelCase(part)).join(NAME_SEPARATOR));\n\nconst collisionError = (file: ParsedSchemaFile, taken: string, schemaId: string, name: string): Error =>\n new Error(\n `${file.fileName} declares ${taken} and ${schemaId}, which both export \\`${name}\\`. ` +\n \"Rename one of the schema ids so that every schema in the file gets an export of its own.\",\n );\n\nconst getNamedSchemas = (file: ParsedSchemaFile): NamedSchema[] => {\n const owners: Map<string, string> = new Map();\n\n return file.schemas.map((schema) => {\n const exportName = getExportName(schema.id);\n const taken = owners.get(exportName);\n\n if (taken !== undefined) {\n throw collisionError(file, taken, schema.id, exportName);\n }\n\n owners.set(exportName, schema.id);\n\n return { schema, exportName };\n });\n};\n\nconst runtimeKindForKey = (key: ParsedKey): string => {\n if (key.enumId !== null) {\n return ENUM_KIND;\n }\n\n if (key.flagsId !== null) {\n return FLAGS_KIND;\n }\n\n return key.variantType ?? \"\";\n};\n\nconst getRuntimeKeys = (schema: ParsedSchema): string => {\n const entries = schema.keys.map(\n (key) => `${toJsStringLiteral(key.name)}: ${toJsStringLiteral(runtimeKindForKey(key))}`,\n );\n\n return `{ ${entries.join(\", \")} }`;\n};\n\nconst renderRuntimeModule = (file: ParsedSchemaFile): string => {\n const lines: string[] = [];\n const named = getNamedSchemas(file);\n\n for (const [index, { schema, exportName }] of named.entries()) {\n const keysName = `keys_${String(index)}`;\n const id = toJsStringLiteral(schema.id);\n lines.push(`const ${keysName} = ${getRuntimeKeys(schema)};`);\n\n if (schema.path === null) {\n lines.push(\n `export const ${exportName} = { id: ${id}, keys: ${keysName}, ` +\n `at: (path) => ({ id: ${id}, path, keys: ${keysName} }) };`,\n );\n } else {\n lines.push(`export const ${exportName} = { id: ${id}, path: null, keys: ${keysName} };`);\n }\n }\n\n const first = named[0];\n\n if (first !== undefined) {\n lines.push(`export default ${first.exportName};`);\n }\n\n return lines.join(\"\\n\");\n};\n\nconst sanitizeSummary = (summary: string): string => summary.replaceAll(\"*/\", String.raw`*\\/`);\n\nconst allocateInterfaceName = (schemaId: string, usedNames: Set<string>): string => {\n const base = `${schemaId\n .split(/[^a-zA-Z0-9]+/)\n .filter((part) => part.length > 0)\n .map((part) => upperFirst(part))\n .join(\"\")}Keys`;\n\n let name = base;\n let suffix = 2;\n\n while (usedNames.has(name)) {\n name = `${base}${String(suffix)}`;\n suffix += 1;\n }\n\n usedNames.add(name);\n\n return name;\n};\n\nconst renderKeysType = (name: string, schema: ParsedSchema): string[] => {\n const lines = [` type ${name} = {`];\n\n for (const key of schema.keys) {\n if (key.summary !== null) {\n lines.push(` /** ${sanitizeSummary(key.summary)} */`);\n }\n\n lines.push(` ${toJsStringLiteral(key.name)}: ${toJsStringLiteral(runtimeKindForKey(key))};`);\n }\n\n lines.push(\" };\");\n\n return lines;\n};\n\nconst boundRefTypeLines = (interfaceName: string, indent: string): string[] => [\n `${indent}id: string;`,\n `${indent}path: string | null;`,\n `${indent}keys: ${interfaceName};`,\n];\n\nconst renderSchemaConst = ({ schema, exportName }: NamedSchema, interfaceName: string): string[] => {\n if (schema.path !== null) {\n return [\n ` const ${exportName}: {`,\n ` id: ${toJsStringLiteral(schema.id)};`,\n ...boundRefTypeLines(interfaceName, \" \".repeat(8)).slice(1),\n \" };\",\n ];\n }\n\n return [\n ` const ${exportName}: {`,\n ` id: ${JSON.stringify(schema.id)};`,\n ` keys: ${interfaceName};`,\n \" at(path: string): {\",\n ...boundRefTypeLines(interfaceName, \" \".repeat(12)),\n \" };\",\n \" };\",\n ];\n};\n\nconst renderFileModule = (file: ParsedSchemaFile, usedNames: Set<string>): string[] => {\n const lines = [`declare module ${toJsStringLiteral(file.fileName)} {`];\n const exportNames: string[] = [];\n\n for (const [index, named] of getNamedSchemas(file).entries()) {\n if (index > 0) {\n lines.push(\"\");\n }\n\n const interfaceName = allocateInterfaceName(named.schema.id, usedNames);\n lines.push(...renderKeysType(interfaceName, named.schema), \"\", ...renderSchemaConst(named, interfaceName));\n exportNames.push(named.exportName);\n }\n\n const [firstExport] = exportNames;\n\n if (firstExport !== undefined) {\n lines.push(\"\", ` export { ${exportNames.join(\", \")} };`, ` export default ${firstExport};`);\n }\n\n lines.push(\"}\");\n\n return lines;\n};\n\nconst renderResourceModule = (specifier: string): string => [\n `declare module ${toJsStringLiteral(specifier)} {`,\n \" const path: string;\",\n \" export { path };\",\n \" export default path;\",\n \"}\",\n].join(\"\\n\");\n\nconst renderIconModule = (specifier: string): string => [\n `declare module ${toJsStringLiteral(specifier)} {`,\n \" const iconName: string;\",\n \" export default iconName;\",\n \"}\",\n].join(\"\\n\");\n\nconst renderLegacyAssetModule = (specifier: string): string => [\n `declare module ${toJsStringLiteral(specifier)} {`,\n \" const resourceUri: string;\",\n \" const path: string;\",\n \" export { path };\",\n \" export default resourceUri;\",\n \"}\",\n].join(\"\\n\");\n\nconst renderBlockedAssetModule = (specifier: string): string => [\n `declare module ${toJsStringLiteral(specifier)} {`,\n \" const assetImportRequiresResourceOrUrlQuery: {\",\n \" readonly __gtkxAssetImportRequiresResourceOrUrlQuery: unique symbol;\",\n \" };\",\n \" export default assetImportRequiresResourceOrUrlQuery;\",\n \"}\",\n].join(\"\\n\");\n\nconst renderEnvModule = (\n files: ParsedSchemaFile[],\n assetDeclarations?: EnvAssetDeclarations,\n): string => {\n const assets = assetDeclarations ?? { blocked: [], icons: [], legacy: [], resources: [] };\n const usedNames: Set<string> = new Set();\n\n const schemas = files\n .filter((file) => file.schemas.length > 0)\n .map((file) => renderFileModule(file, usedNames).join(\"\\n\"));\n\n const blocked = assets.blocked.map((specifier) => renderBlockedAssetModule(specifier));\n const icons = assets.icons.map((specifier) => renderIconModule(specifier));\n const legacy = assets.legacy.map((specifier) => renderLegacyAssetModule(specifier));\n const resources = assets.resources.map((specifier) => renderResourceModule(specifier));\n\n return `${[GTKX_ENV_MODULE_HEADER, ...blocked, ...icons, ...legacy, ...resources, ...schemas].join(\"\\n\\n\")}\\n`;\n};\n\nexport { renderRuntimeModule, renderEnvModule };\n"]}
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/settings/render.ts"],"names":[],"mappings":"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","sourcesContent":["import { camelCase, sanitizeIdentifier, upperFirst } from \"@gtkx/utils\";\nimport type { ParsedKey, ParsedSchema, ParsedSchemaFile } from \"./parser.js\";\n\ntype NamedSchema = {\n schema: ParsedSchema;\n exportName: string;\n};\n\ntype EnvAssetDeclarations = {\n blocked: string[];\n icons: string[];\n legacy: string[];\n resources: string[];\n};\n\ntype EnvModuleOptions = {\n references?: string[];\n};\n\nconst GTKX_ENV_MODULE_HEADER = `/**\n * Project import declarations generated by GTKX. Regenerated by\n * \\`gtkx codegen\\`, \\`gtkx dev\\`, and \\`gtkx build\\`; do not edit.\n */`;\n\nconst ENUM_KIND = \"enum\";\nconst FLAGS_KIND = \"flags\";\nconst ID_SEPARATOR = /[._]/;\nconst NAME_SEPARATOR = \"_\";\n\nconst toJsStringLiteral = (value: string): string =>\n JSON.stringify(value).replaceAll(\"\\u{2028}\", String.raw`\\u2028`).replaceAll(\"\\u{2029}\", String.raw`\\u2029`);\n\nconst getExportName = (schemaId: string): string =>\n sanitizeIdentifier(schemaId.split(ID_SEPARATOR).map((part) => camelCase(part)).join(NAME_SEPARATOR));\n\nconst collisionError = (file: ParsedSchemaFile, taken: string, schemaId: string, name: string): Error =>\n new Error(\n `${file.fileName} declares ${taken} and ${schemaId}, which both export \\`${name}\\`. ` +\n \"Rename one of the schema ids so that every schema in the file gets an export of its own.\",\n );\n\nconst getNamedSchemas = (file: ParsedSchemaFile): NamedSchema[] => {\n const owners: Map<string, string> = new Map();\n\n return file.schemas.map((schema) => {\n const exportName = getExportName(schema.id);\n const taken = owners.get(exportName);\n\n if (taken !== undefined) {\n throw collisionError(file, taken, schema.id, exportName);\n }\n\n owners.set(exportName, schema.id);\n\n return { schema, exportName };\n });\n};\n\nconst runtimeKindForKey = (key: ParsedKey): string => {\n if (key.enumId !== null) {\n return ENUM_KIND;\n }\n\n if (key.flagsId !== null) {\n return FLAGS_KIND;\n }\n\n return key.variantType ?? \"\";\n};\n\nconst getRuntimeKeys = (schema: ParsedSchema): string => {\n const entries = schema.keys.map(\n (key) => `${toJsStringLiteral(key.name)}: ${toJsStringLiteral(runtimeKindForKey(key))}`,\n );\n\n return `{ ${entries.join(\", \")} }`;\n};\n\nconst renderRuntimeModule = (file: ParsedSchemaFile): string => {\n const lines: string[] = [];\n const named = getNamedSchemas(file);\n\n for (const [index, { schema, exportName }] of named.entries()) {\n const keysName = `keys_${String(index)}`;\n const id = toJsStringLiteral(schema.id);\n lines.push(`const ${keysName} = ${getRuntimeKeys(schema)};`);\n\n if (schema.path === null) {\n lines.push(\n `export const ${exportName} = { id: ${id}, keys: ${keysName}, ` +\n `at: (path) => ({ id: ${id}, path, keys: ${keysName} }) };`,\n );\n } else {\n lines.push(`export const ${exportName} = { id: ${id}, path: null, keys: ${keysName} };`);\n }\n }\n\n const first = named[0];\n\n if (first !== undefined) {\n lines.push(`export default ${first.exportName};`);\n }\n\n return lines.join(\"\\n\");\n};\n\nconst sanitizeSummary = (summary: string): string => summary.replaceAll(\"*/\", String.raw`*\\/`);\n\nconst allocateInterfaceName = (schemaId: string, usedNames: Set<string>): string => {\n const base = `${schemaId\n .split(/[^a-zA-Z0-9]+/)\n .filter((part) => part.length > 0)\n .map((part) => upperFirst(part))\n .join(\"\")}Keys`;\n\n let name = base;\n let suffix = 2;\n\n while (usedNames.has(name)) {\n name = `${base}${String(suffix)}`;\n suffix += 1;\n }\n\n usedNames.add(name);\n\n return name;\n};\n\nconst renderKeysType = (name: string, schema: ParsedSchema): string[] => {\n const lines = [` type ${name} = {`];\n\n for (const key of schema.keys) {\n if (key.summary !== null) {\n lines.push(` /** ${sanitizeSummary(key.summary)} */`);\n }\n\n lines.push(` ${toJsStringLiteral(key.name)}: ${toJsStringLiteral(runtimeKindForKey(key))};`);\n }\n\n lines.push(\" };\");\n\n return lines;\n};\n\nconst boundRefTypeLines = (interfaceName: string, indent: string): string[] => [\n `${indent}id: string;`,\n `${indent}path: string | null;`,\n `${indent}keys: ${interfaceName};`,\n];\n\nconst renderSchemaConst = ({ schema, exportName }: NamedSchema, interfaceName: string): string[] => {\n if (schema.path !== null) {\n return [\n ` const ${exportName}: {`,\n ` id: ${toJsStringLiteral(schema.id)};`,\n ...boundRefTypeLines(interfaceName, \" \".repeat(8)).slice(1),\n \" };\",\n ];\n }\n\n return [\n ` const ${exportName}: {`,\n ` id: ${JSON.stringify(schema.id)};`,\n ` keys: ${interfaceName};`,\n \" at(path: string): {\",\n ...boundRefTypeLines(interfaceName, \" \".repeat(12)),\n \" };\",\n \" };\",\n ];\n};\n\nconst renderFileModule = (file: ParsedSchemaFile, usedNames: Set<string>): string[] => {\n const lines = [`declare module ${toJsStringLiteral(file.fileName)} {`];\n const exportNames: string[] = [];\n\n for (const [index, named] of getNamedSchemas(file).entries()) {\n if (index > 0) {\n lines.push(\"\");\n }\n\n const interfaceName = allocateInterfaceName(named.schema.id, usedNames);\n lines.push(...renderKeysType(interfaceName, named.schema), \"\", ...renderSchemaConst(named, interfaceName));\n exportNames.push(named.exportName);\n }\n\n const [firstExport] = exportNames;\n\n if (firstExport !== undefined) {\n lines.push(\"\", ` export { ${exportNames.join(\", \")} };`, ` export default ${firstExport};`);\n }\n\n lines.push(\"}\");\n\n return lines;\n};\n\nconst renderResourceModule = (specifier: string): string => [\n `declare module ${toJsStringLiteral(specifier)} {`,\n \" const path: string;\",\n \" export { path };\",\n \" export default path;\",\n \"}\",\n].join(\"\\n\");\n\nconst renderIconModule = (specifier: string): string => [\n `declare module ${toJsStringLiteral(specifier)} {`,\n \" const iconName: string;\",\n \" export default iconName;\",\n \"}\",\n].join(\"\\n\");\n\nconst renderLegacyAssetModule = (specifier: string): string => [\n `declare module ${toJsStringLiteral(specifier)} {`,\n \" const resourceUri: string;\",\n \" const path: string;\",\n \" export { path };\",\n \" export default resourceUri;\",\n \"}\",\n].join(\"\\n\");\n\nconst renderBlockedAssetModule = (specifier: string): string => [\n `declare module ${toJsStringLiteral(specifier)} {`,\n \" const assetImportRequiresResourceOrUrlQuery: {\",\n \" readonly __gtkxAssetImportRequiresResourceOrUrlQuery: unique symbol;\",\n \" };\",\n \" export default assetImportRequiresResourceOrUrlQuery;\",\n \"}\",\n].join(\"\\n\");\n\nconst renderEnvModule = (\n files: ParsedSchemaFile[],\n assetDeclarations?: EnvAssetDeclarations,\n options: EnvModuleOptions = {},\n): string => {\n const assets = assetDeclarations ?? { blocked: [], icons: [], legacy: [], resources: [] };\n const usedNames: Set<string> = new Set();\n\n const schemas = files\n .filter((file) => file.schemas.length > 0)\n .map((file) => renderFileModule(file, usedNames).join(\"\\n\"));\n\n const blocked = assets.blocked.map((specifier) => renderBlockedAssetModule(specifier));\n const icons = assets.icons.map((specifier) => renderIconModule(specifier));\n const legacy = assets.legacy.map((specifier) => renderLegacyAssetModule(specifier));\n const resources = assets.resources.map((specifier) => renderResourceModule(specifier));\n const references = (options.references ?? []).map((path) => `/// <reference path=${JSON.stringify(path)} />`);\n\n return `${[\n GTKX_ENV_MODULE_HEADER,\n ...references,\n ...blocked,\n ...icons,\n ...legacy,\n ...resources,\n ...schemas,\n ].join(\"\\n\\n\")}\\n`;\n};\n\nexport { renderRuntimeModule, renderEnvModule };\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/settings/schema.ts"],"names":[],"mappings":"AA4BA,KAAK,eAAe,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,QAAA,MAAM,aAAa,iBAAiB,CAAC;AAMrC,QAAA,MAAM,gBAAgB,GAAI,KAAK,MAAM,EAAE,UAAU,MAAM,GAAG,SAAS,KAAG,MAUrE,CAAC;AAKF,QAAA,MAAM,WAAW,GAAI,KAAK,MAAM,EAAE,UAAU,MAAM,KAAG,IAEpD,CAAC;AAIF,QAAA,MAAM,yBAAyB,GAAI,MAAM,MAAM,EAAE,UAAU,MAAM,KAAG,MAAM,GAAG,IAc5E,CAAC;AA+GF,QAAA,MAAM,2BAA2B,GAAI,aAAa,MAAM,EAAE,KAAG,IAiB5D,CAAC;AA+BF,QAAA,MAAM,6BAA6B,GAAI,MAAM,MAAM,EAAE,SAAS,MAAM,GAAG,IAAI,KAAG,MAAM,GAAG,IAwBtF,CAAC;AAmDF,QAAA,MAAM,aAAa,GACf,SAAS,MAAM,EACf,SAAS,MAAM,GAAG,IAAI,EACtB,6BAA2B,KAC5B,eAkBF,CAAC;AAEF,OAAO,EACH,aAAa,EACb,gBAAgB,EAChB,WAAW,EACX,2BAA2B,EAC3B,yBAAyB,EACzB,6BAA6B,EAC7B,aAAa,GAChB,CAAC"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/settings/schema.ts"],"names":[],"mappings":"AA6BA,KAAK,eAAe,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,QAAA,MAAM,aAAa,iBAAiB,CAAC;AAMrC,QAAA,MAAM,gBAAgB,GAAI,KAAK,MAAM,EAAE,UAAU,MAAM,GAAG,SAAS,KAAG,MAUrE,CAAC;AAKF,QAAA,MAAM,WAAW,GAAI,KAAK,MAAM,EAAE,UAAU,MAAM,KAAG,IAEpD,CAAC;AAIF,QAAA,MAAM,yBAAyB,GAAI,MAAM,MAAM,EAAE,UAAU,MAAM,KAAG,MAAM,GAAG,IAc5E,CAAC;AA+GF,QAAA,MAAM,2BAA2B,GAAI,aAAa,MAAM,EAAE,KAAG,IAiB5D,CAAC;AA+BF,QAAA,MAAM,6BAA6B,GAAI,MAAM,MAAM,EAAE,SAAS,MAAM,GAAG,IAAI,KAAG,MAAM,GAAG,IAwBtF,CAAC;AAmDF,QAAA,MAAM,aAAa,GACf,SAAS,MAAM,EACf,SAAS,MAAM,GAAG,IAAI,EACtB,6BAA2B,KAC5B,eAmBF,CAAC;AAEF,OAAO,EACH,aAAa,EACb,gBAAgB,EAChB,WAAW,EACX,2BAA2B,EAC3B,yBAAyB,EACzB,6BAA6B,EAC7B,aAAa,GAChB,CAAC"}
@@ -3,6 +3,7 @@ import { createHash } from "node:crypto";
3
3
  import { copyFileSync, existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, realpathSync, writeFileSync, } from "node:fs";
4
4
  import { tmpdir } from "node:os";
5
5
  import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
6
+ import { I18N_TYPES_FILENAME, i18nTypesPath } from "../i18n/types.js";
6
7
  import { DATA_IMPORT_PREFIX } from "../internal/data-dir.js";
7
8
  import { discoverSourceImports } from "../internal/source-imports.js";
8
9
  import { removeTempDir } from "../internal/staging-dir.js";
@@ -219,7 +220,8 @@ const emitSchemaEnv = (rootDir, dataDir, isV2ResourceImports = false) => {
219
220
  assertUniqueSchemaBasenames(importedFiles);
220
221
  const imported = parseProjectSchemas(importedFiles, getRelativeModuleSpecifier);
221
222
  const assets = findAssetModuleSpecifiers(imports, isV2ResourceImports);
222
- const content = renderEnvModule([...legacy, ...imported], assets);
223
+ const references = existsSync(i18nTypesPath(rootDir)) ? [`./${I18N_TYPES_FILENAME}`] : [];
224
+ const content = renderEnvModule([...legacy, ...imported], assets, { references });
223
225
  const path = schemaEnvPath(rootDir);
224
226
  const isWritten = didWriteChanges(path, content);
225
227
  return { path, isWritten };