@gtkx/cli 1.0.0-rc.4 → 1.0.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 (149) hide show
  1. package/README.md +5 -5
  2. package/dist/builder.d.ts +1 -1
  3. package/dist/builder.d.ts.map +1 -1
  4. package/dist/builder.js +2 -1
  5. package/dist/builder.js.map +1 -1
  6. package/dist/cli.js +4 -2
  7. package/dist/cli.js.map +1 -1
  8. package/dist/codegen/freshness.d.ts.map +1 -1
  9. package/dist/codegen/freshness.js +0 -2
  10. package/dist/codegen/freshness.js.map +1 -1
  11. package/dist/codegen/run-codegen.d.ts +1 -1
  12. package/dist/codegen/run-codegen.d.ts.map +1 -1
  13. package/dist/codegen/run-codegen.js +1 -0
  14. package/dist/codegen/run-codegen.js.map +1 -1
  15. package/dist/codegen/store-resolver.d.ts +1 -1
  16. package/dist/codegen/store-resolver.d.ts.map +1 -1
  17. package/dist/codegen/store-resolver.js.map +1 -1
  18. package/dist/commands/dev.d.ts.map +1 -1
  19. package/dist/commands/dev.js +3 -1
  20. package/dist/commands/dev.js.map +1 -1
  21. package/dist/dev/entry-env.d.ts +3 -0
  22. package/dist/dev/entry-env.d.ts.map +1 -0
  23. package/dist/dev/entry-env.js +3 -0
  24. package/dist/dev/entry-env.js.map +1 -0
  25. package/dist/dev/runner-deps.d.ts.map +1 -1
  26. package/dist/dev/runner-deps.js +1 -0
  27. package/dist/dev/runner-deps.js.map +1 -1
  28. package/dist/dev/runner-main.d.ts.map +1 -1
  29. package/dist/dev/runner-main.js +3 -3
  30. package/dist/dev/runner-main.js.map +1 -1
  31. package/dist/dev/runner.d.ts +1 -0
  32. package/dist/dev/runner.d.ts.map +1 -1
  33. package/dist/dev/runner.js +22 -12
  34. package/dist/dev/runner.js.map +1 -1
  35. package/dist/dev/supervisor.d.ts +10 -3
  36. package/dist/dev/supervisor.d.ts.map +1 -1
  37. package/dist/dev/supervisor.js +23 -4
  38. package/dist/dev/supervisor.js.map +1 -1
  39. package/dist/internal/application-args.d.ts +6 -0
  40. package/dist/internal/application-args.d.ts.map +1 -0
  41. package/dist/internal/application-args.js +10 -0
  42. package/dist/internal/application-args.js.map +1 -0
  43. package/dist/internal/errors.d.ts +1 -2
  44. package/dist/internal/errors.d.ts.map +1 -1
  45. package/dist/internal/errors.js +1 -1
  46. package/dist/internal/errors.js.map +1 -1
  47. package/dist/internal/run-cli-tool.d.ts +10 -0
  48. package/dist/internal/run-cli-tool.d.ts.map +1 -0
  49. package/dist/internal/run-cli-tool.js +15 -0
  50. package/dist/internal/run-cli-tool.js.map +1 -0
  51. package/dist/internal.d.ts +3 -0
  52. package/dist/internal.d.ts.map +1 -0
  53. package/dist/internal.js +3 -0
  54. package/dist/internal.js.map +1 -0
  55. package/dist/mcp/client.d.ts +1 -1
  56. package/dist/mcp/client.d.ts.map +1 -1
  57. package/dist/mcp/client.js.map +1 -1
  58. package/dist/mcp/handlers.d.ts +1 -1
  59. package/dist/mcp/handlers.d.ts.map +1 -1
  60. package/dist/mcp/handlers.js +78 -41
  61. package/dist/mcp/handlers.js.map +1 -1
  62. package/dist/mcp/index.d.ts.map +1 -1
  63. package/dist/mcp/index.js +1 -0
  64. package/dist/mcp/index.js.map +1 -1
  65. package/dist/mcp/serialize-widget.d.ts +2 -2
  66. package/dist/mcp/serialize-widget.d.ts.map +1 -1
  67. package/dist/mcp/serialize-widget.js +47 -17
  68. package/dist/mcp/serialize-widget.js.map +1 -1
  69. package/dist/mcp/widget-properties.d.ts +6 -0
  70. package/dist/mcp/widget-properties.d.ts.map +1 -0
  71. package/dist/mcp/widget-properties.js +102 -0
  72. package/dist/mcp/widget-properties.js.map +1 -0
  73. package/dist/settings/compile.d.ts.map +1 -1
  74. package/dist/settings/compile.js +8 -12
  75. package/dist/settings/compile.js.map +1 -1
  76. package/dist/vite-plugins/asset-emitter.d.ts +9 -0
  77. package/dist/vite-plugins/asset-emitter.d.ts.map +1 -0
  78. package/dist/vite-plugins/asset-emitter.js +2 -0
  79. package/dist/vite-plugins/asset-emitter.js.map +1 -0
  80. package/dist/vite-plugins/asset-extensions.d.ts +1 -2
  81. package/dist/vite-plugins/asset-extensions.d.ts.map +1 -1
  82. package/dist/vite-plugins/asset-extensions.js +1 -1
  83. package/dist/vite-plugins/asset-extensions.js.map +1 -1
  84. package/dist/vite-plugins/built-url.d.ts.map +1 -1
  85. package/dist/vite-plugins/built-url.js +14 -10
  86. package/dist/vite-plugins/built-url.js.map +1 -1
  87. package/dist/vite-plugins/ensure-store.d.ts +4 -0
  88. package/dist/vite-plugins/ensure-store.d.ts.map +1 -0
  89. package/dist/vite-plugins/ensure-store.js +10 -0
  90. package/dist/vite-plugins/ensure-store.js.map +1 -0
  91. package/dist/vite-plugins/icons.d.ts.map +1 -1
  92. package/dist/vite-plugins/icons.js.map +1 -1
  93. package/dist/vite-plugins/react-compiler.d.ts +1 -1
  94. package/dist/vite-plugins/react-compiler.d.ts.map +1 -1
  95. package/dist/vite-plugins/react-compiler.js.map +1 -1
  96. package/dist/vite-plugins/resources.d.ts +1 -1
  97. package/dist/vite-plugins/resources.d.ts.map +1 -1
  98. package/dist/vite-plugins/resources.js +6 -15
  99. package/dist/vite-plugins/resources.js.map +1 -1
  100. package/dist/vite-plugins/settings.js.map +1 -1
  101. package/dist/vite-plugins/undeclared-library.d.ts +1 -1
  102. package/dist/vite-plugins/undeclared-library.d.ts.map +1 -1
  103. package/dist/vite-plugins/undeclared-library.js.map +1 -1
  104. package/dist/vite-plugins/worker.d.ts +4 -0
  105. package/dist/vite-plugins/worker.d.ts.map +1 -0
  106. package/dist/vite-plugins/worker.js +136 -0
  107. package/dist/vite-plugins/worker.js.map +1 -0
  108. package/dist/vitest-plugin.d.ts +7 -0
  109. package/dist/vitest-plugin.d.ts.map +1 -1
  110. package/dist/vitest-plugin.js +14 -1
  111. package/dist/vitest-plugin.js.map +1 -1
  112. package/package.json +16 -12
  113. package/src/builder.ts +3 -2
  114. package/src/cli.ts +4 -2
  115. package/src/codegen/freshness.ts +0 -2
  116. package/src/codegen/run-codegen.ts +1 -1
  117. package/src/codegen/store-resolver.ts +1 -1
  118. package/src/commands/dev.ts +3 -1
  119. package/src/dev/entry-env.ts +3 -0
  120. package/src/dev/runner-deps.ts +1 -0
  121. package/src/dev/runner-main.ts +3 -4
  122. package/src/dev/runner.ts +44 -13
  123. package/src/dev/supervisor.ts +54 -11
  124. package/src/internal/application-args.ts +13 -0
  125. package/src/internal/errors.ts +1 -1
  126. package/src/internal/run-cli-tool.ts +22 -0
  127. package/src/internal.ts +2 -0
  128. package/src/mcp/client.ts +1 -1
  129. package/src/mcp/handlers.ts +123 -56
  130. package/src/mcp/index.ts +1 -0
  131. package/src/mcp/serialize-widget.ts +71 -21
  132. package/src/mcp/widget-properties.ts +153 -0
  133. package/src/settings/compile.ts +8 -11
  134. package/src/vite-plugins/asset-emitter.ts +5 -0
  135. package/src/vite-plugins/asset-extensions.ts +1 -1
  136. package/src/vite-plugins/built-url.ts +19 -13
  137. package/src/vite-plugins/ensure-store.ts +14 -0
  138. package/src/vite-plugins/icons.ts +2 -5
  139. package/src/vite-plugins/react-compiler.ts +2 -1
  140. package/src/vite-plugins/resources.ts +10 -19
  141. package/src/vite-plugins/settings.ts +2 -2
  142. package/src/vite-plugins/undeclared-library.ts +1 -1
  143. package/src/vite-plugins/worker.ts +235 -0
  144. package/src/vitest-plugin.ts +15 -1
  145. package/dist/internal/resolve-cli-tool.d.ts +0 -3
  146. package/dist/internal/resolve-cli-tool.d.ts.map +0 -1
  147. package/dist/internal/resolve-cli-tool.js +0 -27
  148. package/dist/internal/resolve-cli-tool.js.map +0 -1
  149. package/src/internal/resolve-cli-tool.ts +0 -37
@@ -6,13 +6,20 @@ type SupervisedChild = {
6
6
  on(event: "exit", listener: (code: number | null, signal: NodeJS.Signals | null) => void): void;
7
7
  once(event: "exit", listener: (code: number | null, signal: NodeJS.Signals | null) => void): void;
8
8
  };
9
- type ForkRunner = (modulePath: string, args: string[], cwd: string) => SupervisedChild;
9
+ type ForkRunner = (modulePath: string, args: string[], env: NodeJS.ProcessEnv, cwd: string) => SupervisedChild;
10
10
  type DevWatch = {
11
11
  paths: string[];
12
12
  regenerate: () => Promise<void>;
13
13
  };
14
+ type DevSupervisorOptions = {
15
+ entryPath: string;
16
+ cwd: string;
17
+ args?: string[] | undefined;
18
+ watch?: DevWatch | undefined;
19
+ fork?: ForkRunner | undefined;
20
+ };
14
21
  declare const RESTART_EXIT_CODE = 75;
15
22
  declare const defaultForkRunner: ForkRunner;
16
- declare const runDevSupervisor: (entryPath: string, cwd: string, watch?: DevWatch, fork?: ForkRunner) => Promise<never>;
17
- export { RESTART_EXIT_CODE, defaultForkRunner, runDevSupervisor, type SupervisedChild, type ForkRunner, type DevWatch };
23
+ declare const runDevSupervisor: (options: DevSupervisorOptions) => Promise<never>;
24
+ export { RESTART_EXIT_CODE, defaultForkRunner, runDevSupervisor, type DevWatch, type ForkRunner, type SupervisedChild, };
18
25
  //# sourceMappingURL=supervisor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"supervisor.d.ts","sourceRoot":"","sources":["../../src/dev/supervisor.ts"],"names":[],"mappings":"AAMA,KAAK,eAAe,GAAG;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;IAChD,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI,CAAC;IAChG,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI,CAAC;CACrG,CAAC;AAEF,KAAK,UAAU,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,KAAK,eAAe,CAAC;AAEvF,KAAK,QAAQ,GAAG;IACZ,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC,CAAC;AAoBF,QAAA,MAAM,iBAAiB,KAAK,CAAC;AAE7B,QAAA,MAAM,iBAAiB,EAAE,UACqD,CAAC;AA8M/E,QAAA,MAAM,gBAAgB,GAClB,WAAW,MAAM,EACjB,KAAK,MAAM,EACX,QAAQ,QAAQ,EAChB,OAAM,UAA8B,KACrC,OAAO,CAAC,KAAK,CAmBf,CAAC;AAEF,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAAE,KAAK,QAAQ,EAAE,CAAC"}
1
+ {"version":3,"file":"supervisor.d.ts","sourceRoot":"","sources":["../../src/dev/supervisor.ts"],"names":[],"mappings":"AAOA,KAAK,eAAe,GAAG;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;IAChD,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI,CAAC;IAChG,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI,CAAC;CACrG,CAAC;AAEF,KAAK,UAAU,GAAG,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,GAAG,EAAE,MAAM,KAAK,eAAe,CAAC;AAE/G,KAAK,QAAQ,GAAG;IACZ,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC,CAAC;AAgBF,KAAK,oBAAoB,GAAG;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC5B,KAAK,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC7B,IAAI,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CACjC,CAAC;AAOF,QAAA,MAAM,iBAAiB,KAAK,CAAC;AAe7B,QAAA,MAAM,iBAAiB,EAAE,UAUxB,CAAC;AAoNF,QAAA,MAAM,gBAAgB,GAAU,SAAS,oBAAoB,KAAG,OAAO,CAAC,KAAK,CAsB5E,CAAC;AAEF,OAAO,EACH,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,eAAe,GACvB,CAAC"}
@@ -3,11 +3,28 @@ import { fork as nodeFork } from "node:child_process";
3
3
  import { watch as watchFs } from "node:fs";
4
4
  import { basename, dirname } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
+ import { DEV_ENTRY_ENV } from "./entry-env.js";
6
7
  const DEV_RUNNER_URL = new URL("../../bin/gtkx-dev-runner.js", import.meta.url);
7
8
  const FORCE_KILL_TIMEOUT_MS = 5000;
8
9
  const CONFIG_DEBOUNCE_MS = 150;
9
10
  const RESTART_EXIT_CODE = 75;
10
- const defaultForkRunner = (modulePath, args, cwd) => nodeFork(modulePath, [...args], { cwd, stdio: "inherit", detached: true });
11
+ const CONDITION_FLAG = /^(?:--conditions|-C)(?:=.*)?$/;
12
+ const SPLIT_CONDITION_FLAG = /^(?:--conditions|-C)$/;
13
+ const withoutConditions = (argv) => argv.filter((argument, index) => !CONDITION_FLAG.test(argument) && !SPLIT_CONDITION_FLAG.test(argv[index - 1] ?? ""));
14
+ const getNodeOptions = (env) => {
15
+ const options = env.NODE_OPTIONS;
16
+ return options === undefined ? undefined : withoutConditions(options.split(/\s+/)).join(" ");
17
+ };
18
+ const defaultForkRunner = (modulePath, args, env, cwd) => {
19
+ const nodeOptions = getNodeOptions(env);
20
+ return nodeFork(modulePath, args, {
21
+ cwd,
22
+ env: { ...env, ...(nodeOptions !== undefined && { NODE_OPTIONS: nodeOptions }) },
23
+ stdio: "inherit",
24
+ detached: true,
25
+ execArgv: withoutConditions(process.execArgv),
26
+ });
27
+ };
11
28
  const forwardSignal = (child, signal) => {
12
29
  if (!child.killed) {
13
30
  child.kill(signal);
@@ -49,7 +66,7 @@ const handleChildExit = (state, code, signal) => {
49
66
  process.exit(code ?? exitCodeForSignal(signal));
50
67
  };
51
68
  const launch = (state) => {
52
- const child = state.fork(state.runnerPath, [state.entryPath], state.cwd);
69
+ const child = state.fork(state.runnerPath, state.args, { ...process.env, [DEV_ENTRY_ENV]: state.entryPath }, state.cwd);
53
70
  state.child = child;
54
71
  child.on("exit", (code, signal) => {
55
72
  handleChildExit(state, code, signal);
@@ -160,11 +177,13 @@ const installShutdown = (state) => {
160
177
  exitCode: (signal, graceful) => state.capturedChildExit ?? (graceful ? 0 : exitCodeForSignal(signal)),
161
178
  });
162
179
  };
163
- const runDevSupervisor = async (entryPath, cwd, watch, fork = defaultForkRunner) => {
180
+ const runDevSupervisor = async (options) => {
181
+ const { entryPath, cwd, args = [], watch, fork = defaultForkRunner } = options;
164
182
  const state = {
165
183
  runnerPath: fileURLToPath(DEV_RUNNER_URL),
166
184
  entryPath,
167
185
  cwd,
186
+ args,
168
187
  watch,
169
188
  watchers: [],
170
189
  fork,
@@ -178,5 +197,5 @@ const runDevSupervisor = async (entryPath, cwd, watch, fork = defaultForkRunner)
178
197
  launch(state);
179
198
  return new Promise(() => undefined);
180
199
  };
181
- export { RESTART_EXIT_CODE, defaultForkRunner, runDevSupervisor };
200
+ export { RESTART_EXIT_CODE, defaultForkRunner, runDevSupervisor, };
182
201
  //# sourceMappingURL=supervisor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"supervisor.js","sourceRoot":"","sources":["../../src/dev/supervisor.ts"],"names":[],"mappings":"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","sourcesContent":["import { error, exitCodeForSignal, info, installGracefulShutdown } from \"@gtkx/utils\";\nimport { fork as nodeFork } from \"node:child_process\";\nimport { type FSWatcher, watch as watchFs } from \"node:fs\";\nimport { basename, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\ntype SupervisedChild = {\n killed: boolean;\n pid?: number | undefined;\n exitCode: number | null;\n kill(signal?: number | NodeJS.Signals): boolean;\n on(event: \"exit\", listener: (code: number | null, signal: NodeJS.Signals | null) => void): void;\n once(event: \"exit\", listener: (code: number | null, signal: NodeJS.Signals | null) => void): void;\n};\n\ntype ForkRunner = (modulePath: string, args: string[], cwd: string) => SupervisedChild;\n\ntype DevWatch = {\n paths: string[];\n regenerate: () => Promise<void>;\n};\n\ntype SupervisorState = {\n runnerPath: string;\n entryPath: string;\n cwd: string;\n watch: DevWatch | undefined;\n watchers: FSWatcher[];\n fork: ForkRunner;\n child: SupervisedChild | null;\n isShuttingDown: boolean;\n isRestarting: boolean;\n capturedChildExit: number | undefined;\n};\n\ntype DebounceTimer = { handle: NodeJS.Timeout | null };\n\nconst DEV_RUNNER_URL = new URL(\"../../bin/gtkx-dev-runner.js\", import.meta.url);\nconst FORCE_KILL_TIMEOUT_MS = 5000;\nconst CONFIG_DEBOUNCE_MS = 150;\nconst RESTART_EXIT_CODE = 75;\n\nconst defaultForkRunner: ForkRunner = (modulePath, args, cwd) =>\n nodeFork(modulePath, [...args], { cwd, stdio: \"inherit\", detached: true });\n\nconst forwardSignal = (child: SupervisedChild, signal: NodeJS.Signals): void => {\n if (!child.killed) {\n child.kill(signal);\n }\n};\n\nconst didForceKillChild = (child: SupervisedChild | null): boolean => {\n if (!child?.pid || child.exitCode !== null || child.killed) {\n return false;\n }\n\n try {\n return process.kill(child.pid, \"SIGKILL\");\n } catch {\n return false;\n }\n};\n\nconst captureShutdownExit = (state: SupervisorState, code: number | null, signal: NodeJS.Signals | null): void => {\n if (code !== null) {\n state.capturedChildExit = code;\n } else if (signal) {\n state.capturedChildExit = exitCodeForSignal(signal);\n }\n};\n\nconst handleChildExit = (state: SupervisorState, code: number | null, signal: NodeJS.Signals | null): void => {\n state.child = null;\n\n if (state.isRestarting) {\n return;\n }\n\n if (state.isShuttingDown) {\n captureShutdownExit(state, code, signal);\n\n return;\n }\n\n if (code === RESTART_EXIT_CODE) {\n info(\"Restarting dev runner...\");\n launch(state);\n\n return;\n }\n\n process.exit(code ?? exitCodeForSignal(signal));\n};\n\nconst launch = (state: SupervisorState): void => {\n const child = state.fork(state.runnerPath, [state.entryPath], state.cwd);\n state.child = child;\n\n child.on(\"exit\", (code, signal) => {\n handleChildExit(state, code, signal);\n });\n};\n\nconst isRestartBlocked = (state: SupervisorState): boolean => state.isRestarting || state.isShuttingDown;\n\nconst relaunchAfterExit = (state: SupervisorState): void => {\n state.isRestarting = false;\n\n if (state.isShuttingDown) {\n return;\n }\n\n info(\"Restarting dev runner...\");\n launch(state);\n};\n\nconst restart = async (state: SupervisorState): Promise<void> => {\n const watch = state.watch;\n\n if (watch === undefined || isRestartBlocked(state)) {\n return;\n }\n\n state.isRestarting = true;\n info(\"gtkx.config.ts changed; regenerating bindings...\");\n\n try {\n await watch.regenerate();\n } catch (error_) {\n error(\"Codegen failed; keeping the current dev runner. Fix the error and save again.\", error_);\n state.isRestarting = false;\n\n return;\n }\n\n if (state.isShuttingDown) {\n state.isRestarting = false;\n\n return;\n }\n\n const current = state.child;\n\n if (current === null) {\n state.isRestarting = false;\n launch(state);\n\n return;\n }\n\n current.once(\"exit\", () => {\n relaunchAfterExit(state);\n });\n\n forwardSignal(current, \"SIGTERM\");\n};\n\nconst scheduleRestart = (state: SupervisorState, timer: DebounceTimer): void => {\n if (timer.handle !== null) {\n clearTimeout(timer.handle);\n }\n\n timer.handle = setTimeout(() => void restart(state), CONFIG_DEBOUNCE_MS);\n};\n\nconst isWatchedChange = (state: SupervisorState, names: Set<string>, filename: string | Buffer | null): boolean => {\n if (filename === null || state.isShuttingDown) {\n return false;\n }\n\n return names.has(basename(filename.toString()));\n};\n\nconst groupWatchNamesByDirectory = (paths: string[]): Map<string, Set<string>> => {\n const namesByDirectory: Map<string, Set<string>> = new Map();\n\n for (const path of paths) {\n const directory = dirname(path);\n const names = namesByDirectory.get(directory) ?? new Set<string>();\n names.add(basename(path));\n namesByDirectory.set(directory, names);\n }\n\n return namesByDirectory;\n};\n\nconst watchConfigDirectory = (\n state: SupervisorState,\n directory: string,\n names: Set<string>,\n timer: DebounceTimer,\n): void => {\n const watcher = watchFs(directory, (_event, filename) => {\n if (isWatchedChange(state, names, filename)) {\n scheduleRestart(state, timer);\n }\n });\n\n watcher.on(\"error\", (): void => undefined);\n state.watchers.push(watcher);\n};\n\nconst installConfigWatchers = (state: SupervisorState): void => {\n const watch = state.watch;\n\n if (watch === undefined || watch.paths.length === 0) {\n return;\n }\n\n const timer: DebounceTimer = { handle: null };\n\n for (const [directory, names] of groupWatchNamesByDirectory(watch.paths)) {\n watchConfigDirectory(state, directory, names, timer);\n }\n};\n\nconst closeWatchers = (state: SupervisorState): void => {\n for (const watcher of state.watchers) {\n watcher.close();\n }\n};\n\nconst shutdownOnSignal = (state: SupervisorState, signal: NodeJS.Signals): Promise<void> =>\n new Promise<void>((resolve) => {\n state.isShuttingDown = true;\n closeWatchers(state);\n\n if (!state.child) {\n resolve();\n\n return;\n }\n\n state.child.once(\"exit\", () => {\n resolve();\n });\n\n forwardSignal(state.child, signal);\n });\n\nconst installShutdown = (state: SupervisorState): void => {\n installGracefulShutdown({\n onSignal: (signal) => shutdownOnSignal(state, signal),\n onForce: () => didForceKillChild(state.child),\n forceKillAfterMs: FORCE_KILL_TIMEOUT_MS,\n exitCode: (signal, graceful) => state.capturedChildExit ?? (graceful ? 0 : exitCodeForSignal(signal)),\n });\n};\n\nconst runDevSupervisor = async (\n entryPath: string,\n cwd: string,\n watch?: DevWatch,\n fork: ForkRunner = defaultForkRunner,\n): Promise<never> => {\n const state: SupervisorState = {\n runnerPath: fileURLToPath(DEV_RUNNER_URL),\n entryPath,\n cwd,\n watch,\n watchers: [],\n fork,\n child: null,\n isShuttingDown: false,\n isRestarting: false,\n capturedChildExit: undefined,\n };\n\n installConfigWatchers(state);\n installShutdown(state);\n launch(state);\n\n return new Promise<never>((): void => undefined);\n};\n\nexport { RESTART_EXIT_CODE, defaultForkRunner, runDevSupervisor, type SupervisedChild, type ForkRunner, type DevWatch };\n"]}
1
+ {"version":3,"file":"supervisor.js","sourceRoot":"","sources":["../../src/dev/supervisor.ts"],"names":[],"mappings":"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","sourcesContent":["import { error, exitCodeForSignal, info, installGracefulShutdown } from \"@gtkx/utils\";\nimport { fork as nodeFork } from \"node:child_process\";\nimport { type FSWatcher, watch as watchFs } from \"node:fs\";\nimport { basename, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { DEV_ENTRY_ENV } from \"./entry-env.js\";\n\ntype SupervisedChild = {\n killed: boolean;\n pid?: number | undefined;\n exitCode: number | null;\n kill(signal?: number | NodeJS.Signals): boolean;\n on(event: \"exit\", listener: (code: number | null, signal: NodeJS.Signals | null) => void): void;\n once(event: \"exit\", listener: (code: number | null, signal: NodeJS.Signals | null) => void): void;\n};\n\ntype ForkRunner = (modulePath: string, args: string[], env: NodeJS.ProcessEnv, cwd: string) => SupervisedChild;\n\ntype DevWatch = {\n paths: string[];\n regenerate: () => Promise<void>;\n};\n\ntype SupervisorState = {\n runnerPath: string;\n entryPath: string;\n cwd: string;\n args: string[];\n watch: DevWatch | undefined;\n watchers: FSWatcher[];\n fork: ForkRunner;\n child: SupervisedChild | null;\n isShuttingDown: boolean;\n isRestarting: boolean;\n capturedChildExit: number | undefined;\n};\n\ntype DevSupervisorOptions = {\n entryPath: string;\n cwd: string;\n args?: string[] | undefined;\n watch?: DevWatch | undefined;\n fork?: ForkRunner | undefined;\n};\n\ntype DebounceTimer = { handle: NodeJS.Timeout | null };\n\nconst DEV_RUNNER_URL = new URL(\"../../bin/gtkx-dev-runner.js\", import.meta.url);\nconst FORCE_KILL_TIMEOUT_MS = 5000;\nconst CONFIG_DEBOUNCE_MS = 150;\nconst RESTART_EXIT_CODE = 75;\nconst CONDITION_FLAG = /^(?:--conditions|-C)(?:=.*)?$/;\nconst SPLIT_CONDITION_FLAG = /^(?:--conditions|-C)$/;\n\nconst withoutConditions = (argv: string[]): string[] =>\n argv.filter(\n (argument, index) => !CONDITION_FLAG.test(argument) && !SPLIT_CONDITION_FLAG.test(argv[index - 1] ?? \"\"),\n );\n\nconst getNodeOptions = (env: NodeJS.ProcessEnv): string | undefined => {\n const options = env.NODE_OPTIONS;\n\n return options === undefined ? undefined : withoutConditions(options.split(/\\s+/)).join(\" \");\n};\n\nconst defaultForkRunner: ForkRunner = (modulePath, args, env, cwd) => {\n const nodeOptions = getNodeOptions(env);\n\n return nodeFork(modulePath, args, {\n cwd,\n env: { ...env, ...(nodeOptions !== undefined && { NODE_OPTIONS: nodeOptions }) },\n stdio: \"inherit\",\n detached: true,\n execArgv: withoutConditions(process.execArgv),\n });\n};\n\nconst forwardSignal = (child: SupervisedChild, signal: NodeJS.Signals): void => {\n if (!child.killed) {\n child.kill(signal);\n }\n};\n\nconst didForceKillChild = (child: SupervisedChild | null): boolean => {\n if (!child?.pid || child.exitCode !== null || child.killed) {\n return false;\n }\n\n try {\n return process.kill(child.pid, \"SIGKILL\");\n } catch {\n return false;\n }\n};\n\nconst captureShutdownExit = (state: SupervisorState, code: number | null, signal: NodeJS.Signals | null): void => {\n if (code !== null) {\n state.capturedChildExit = code;\n } else if (signal) {\n state.capturedChildExit = exitCodeForSignal(signal);\n }\n};\n\nconst handleChildExit = (state: SupervisorState, code: number | null, signal: NodeJS.Signals | null): void => {\n state.child = null;\n\n if (state.isRestarting) {\n return;\n }\n\n if (state.isShuttingDown) {\n captureShutdownExit(state, code, signal);\n\n return;\n }\n\n if (code === RESTART_EXIT_CODE) {\n info(\"Restarting dev runner...\");\n launch(state);\n\n return;\n }\n\n process.exit(code ?? exitCodeForSignal(signal));\n};\n\nconst launch = (state: SupervisorState): void => {\n const child = state.fork(\n state.runnerPath,\n state.args,\n { ...process.env, [DEV_ENTRY_ENV]: state.entryPath },\n state.cwd,\n );\n\n state.child = child;\n\n child.on(\"exit\", (code, signal) => {\n handleChildExit(state, code, signal);\n });\n};\n\nconst isRestartBlocked = (state: SupervisorState): boolean => state.isRestarting || state.isShuttingDown;\n\nconst relaunchAfterExit = (state: SupervisorState): void => {\n state.isRestarting = false;\n\n if (state.isShuttingDown) {\n return;\n }\n\n info(\"Restarting dev runner...\");\n launch(state);\n};\n\nconst restart = async (state: SupervisorState): Promise<void> => {\n const watch = state.watch;\n\n if (watch === undefined || isRestartBlocked(state)) {\n return;\n }\n\n state.isRestarting = true;\n info(\"gtkx.config.ts changed; regenerating bindings...\");\n\n try {\n await watch.regenerate();\n } catch (error_) {\n error(\"Codegen failed; keeping the current dev runner. Fix the error and save again.\", error_);\n state.isRestarting = false;\n\n return;\n }\n\n if (state.isShuttingDown) {\n state.isRestarting = false;\n\n return;\n }\n\n const current = state.child;\n\n if (current === null) {\n state.isRestarting = false;\n launch(state);\n\n return;\n }\n\n current.once(\"exit\", () => {\n relaunchAfterExit(state);\n });\n\n forwardSignal(current, \"SIGTERM\");\n};\n\nconst scheduleRestart = (state: SupervisorState, timer: DebounceTimer): void => {\n if (timer.handle !== null) {\n clearTimeout(timer.handle);\n }\n\n timer.handle = setTimeout(() => void restart(state), CONFIG_DEBOUNCE_MS);\n};\n\nconst isWatchedChange = (state: SupervisorState, names: Set<string>, filename: string | Buffer | null): boolean => {\n if (filename === null || state.isShuttingDown) {\n return false;\n }\n\n return names.has(basename(filename.toString()));\n};\n\nconst groupWatchNamesByDirectory = (paths: string[]): Map<string, Set<string>> => {\n const namesByDirectory: Map<string, Set<string>> = new Map();\n\n for (const path of paths) {\n const directory = dirname(path);\n const names = namesByDirectory.get(directory) ?? new Set<string>();\n names.add(basename(path));\n namesByDirectory.set(directory, names);\n }\n\n return namesByDirectory;\n};\n\nconst watchConfigDirectory = (\n state: SupervisorState,\n directory: string,\n names: Set<string>,\n timer: DebounceTimer,\n): void => {\n const watcher = watchFs(directory, (_event, filename) => {\n if (isWatchedChange(state, names, filename)) {\n scheduleRestart(state, timer);\n }\n });\n\n watcher.on(\"error\", (): void => undefined);\n state.watchers.push(watcher);\n};\n\nconst installConfigWatchers = (state: SupervisorState): void => {\n const watch = state.watch;\n\n if (watch === undefined || watch.paths.length === 0) {\n return;\n }\n\n const timer: DebounceTimer = { handle: null };\n\n for (const [directory, names] of groupWatchNamesByDirectory(watch.paths)) {\n watchConfigDirectory(state, directory, names, timer);\n }\n};\n\nconst closeWatchers = (state: SupervisorState): void => {\n for (const watcher of state.watchers) {\n watcher.close();\n }\n};\n\nconst shutdownOnSignal = (state: SupervisorState, signal: NodeJS.Signals): Promise<void> =>\n new Promise<void>((resolve) => {\n state.isShuttingDown = true;\n closeWatchers(state);\n\n if (!state.child) {\n resolve();\n\n return;\n }\n\n state.child.once(\"exit\", () => {\n resolve();\n });\n\n forwardSignal(state.child, signal);\n });\n\nconst installShutdown = (state: SupervisorState): void => {\n installGracefulShutdown({\n onSignal: (signal) => shutdownOnSignal(state, signal),\n onForce: () => didForceKillChild(state.child),\n forceKillAfterMs: FORCE_KILL_TIMEOUT_MS,\n exitCode: (signal, graceful) => state.capturedChildExit ?? (graceful ? 0 : exitCodeForSignal(signal)),\n });\n};\n\nconst runDevSupervisor = async (options: DevSupervisorOptions): Promise<never> => {\n const { entryPath, cwd, args = [], watch, fork = defaultForkRunner } = options;\n\n const state: SupervisorState = {\n runnerPath: fileURLToPath(DEV_RUNNER_URL),\n entryPath,\n cwd,\n args,\n watch,\n watchers: [],\n fork,\n child: null,\n isShuttingDown: false,\n isRestarting: false,\n capturedChildExit: undefined,\n };\n\n installConfigWatchers(state);\n installShutdown(state);\n launch(state);\n\n return new Promise<never>((): void => undefined);\n};\n\nexport {\n RESTART_EXIT_CODE,\n defaultForkRunner,\n runDevSupervisor,\n type DevWatch,\n type ForkRunner,\n type SupervisedChild,\n};\n"]}
@@ -0,0 +1,6 @@
1
+ declare const splitApplicationArgs: (argv: string[]) => {
2
+ cliArgs: string[];
3
+ applicationArgs: string[];
4
+ };
5
+ export { splitApplicationArgs };
6
+ //# sourceMappingURL=application-args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"application-args.d.ts","sourceRoot":"","sources":["../../src/internal/application-args.ts"],"names":[],"mappings":"AAEA,QAAA,MAAM,oBAAoB,GAAI,MAAM,MAAM,EAAE,KAAG;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,eAAe,EAAE,MAAM,EAAE,CAAA;CAQ5F,CAAC;AAEF,OAAO,EAAE,oBAAoB,EAAE,CAAC"}
@@ -0,0 +1,10 @@
1
+ const APPLICATION_ARGS_SEPARATOR = "--";
2
+ const splitApplicationArgs = (argv) => {
3
+ const separator = argv.indexOf(APPLICATION_ARGS_SEPARATOR);
4
+ if (separator === -1) {
5
+ return { cliArgs: argv, applicationArgs: [] };
6
+ }
7
+ return { cliArgs: argv.slice(0, separator), applicationArgs: argv.slice(separator + 1) };
8
+ };
9
+ export { splitApplicationArgs };
10
+ //# sourceMappingURL=application-args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"application-args.js","sourceRoot":"","sources":["../../src/internal/application-args.ts"],"names":[],"mappings":"AAAA,MAAM,0BAA0B,GAAG,IAAI,CAAC;AAExC,MAAM,oBAAoB,GAAG,CAAC,IAAc,EAAoD,EAAE;IAC9F,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC;IAE3D,IAAI,SAAS,KAAK,CAAC,CAAC,EAAE,CAAC;QACnB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;IAClD,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,eAAe,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,EAAE,CAAC;AAC7F,CAAC,CAAC;AAEF,OAAO,EAAE,oBAAoB,EAAE,CAAC","sourcesContent":["const APPLICATION_ARGS_SEPARATOR = \"--\";\n\nconst splitApplicationArgs = (argv: string[]): { cliArgs: string[]; applicationArgs: string[] } => {\n const separator = argv.indexOf(APPLICATION_ARGS_SEPARATOR);\n\n if (separator === -1) {\n return { cliArgs: argv, applicationArgs: [] };\n }\n\n return { cliArgs: argv.slice(0, separator), applicationArgs: argv.slice(separator + 1) };\n};\n\nexport { splitApplicationArgs };\n"]}
@@ -1,5 +1,4 @@
1
1
  import type { ArgsDef, CommandDef } from "citty";
2
- declare const printError: (cause: unknown) => never;
3
2
  declare const withErrorBoundary: <T extends ArgsDef>(command: CommandDef<T>) => CommandDef<T>;
4
- export { printError, withErrorBoundary };
3
+ export { withErrorBoundary };
5
4
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/internal/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAKjD,QAAA,MAAM,UAAU,GAAI,OAAO,OAAO,KAAG,KASpC,CAAC;AAEF,QAAA,MAAM,iBAAiB,GAAI,CAAC,SAAS,OAAO,EAAE,SAAS,UAAU,CAAC,CAAC,CAAC,KAAG,UAAU,CAAC,CAAC,CAiBlF,CAAC;AAEF,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,CAAC"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/internal/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAgBjD,QAAA,MAAM,iBAAiB,GAAI,CAAC,SAAS,OAAO,EAAE,SAAS,UAAU,CAAC,CAAC,CAAC,KAAG,UAAU,CAAC,CAAC,CAiBlF,CAAC;AAEF,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
@@ -25,5 +25,5 @@ const withErrorBoundary = (command) => {
25
25
  },
26
26
  };
27
27
  };
28
- export { printError, withErrorBoundary };
28
+ export { withErrorBoundary };
29
29
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/internal/errors.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,eAAe,GAAG,CAAC,CAAC;AAE1B,MAAM,UAAU,GAAG,CAAC,KAAc,EAAS,EAAE;IACzC,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAEtB,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QACtD,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;AAClC,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAoB,OAAsB,EAAiB,EAAE;IACnF,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAExB,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACpB,OAAO,OAAO,CAAC;IACnB,CAAC;IAED,OAAO;QACH,GAAG,OAAO;QACV,GAAG,EAAE,KAAK,EAAE,OAAO,EAAoB,EAAE;YACrC,IAAI,CAAC;gBACD,OAAO,MAAM,GAAG,CAAC,OAAO,CAAC,CAAC;YAC9B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC;YAC7B,CAAC;QACL,CAAC;KACJ,CAAC;AACN,CAAC,CAAC;AAEF,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,CAAC","sourcesContent":["import type { ArgsDef, CommandDef } from \"citty\";\nimport { logger } from \"@gtkx/utils\";\n\nconst ERROR_EXIT_CODE = 1;\n\nconst printError = (cause: unknown): never => {\n const message = cause instanceof Error ? cause.message : String(cause);\n logger.error(message);\n\n if (cause instanceof Error && cause.stack !== undefined) {\n logger.debug(cause.stack);\n }\n\n process.exit(ERROR_EXIT_CODE);\n};\n\nconst withErrorBoundary = <T extends ArgsDef>(command: CommandDef<T>): CommandDef<T> => {\n const run = command.run;\n\n if (run === undefined) {\n return command;\n }\n\n return {\n ...command,\n run: async (context): Promise<unknown> => {\n try {\n return await run(context);\n } catch (error) {\n return printError(error);\n }\n },\n };\n};\n\nexport { printError, withErrorBoundary };\n"]}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/internal/errors.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,eAAe,GAAG,CAAC,CAAC;AAE1B,MAAM,UAAU,GAAG,CAAC,KAAc,EAAS,EAAE;IACzC,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAEtB,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QACtD,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;AAClC,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAoB,OAAsB,EAAiB,EAAE;IACnF,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IAExB,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACpB,OAAO,OAAO,CAAC;IACnB,CAAC;IAED,OAAO;QACH,GAAG,OAAO;QACV,GAAG,EAAE,KAAK,EAAE,OAAO,EAAoB,EAAE;YACrC,IAAI,CAAC;gBACD,OAAO,MAAM,GAAG,CAAC,OAAO,CAAC,CAAC;YAC9B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC;YAC7B,CAAC;QACL,CAAC;KACJ,CAAC;AACN,CAAC,CAAC;AAEF,OAAO,EAAE,iBAAiB,EAAE,CAAC","sourcesContent":["import type { ArgsDef, CommandDef } from \"citty\";\nimport { logger } from \"@gtkx/utils\";\n\nconst ERROR_EXIT_CODE = 1;\n\nconst printError = (cause: unknown): never => {\n const message = cause instanceof Error ? cause.message : String(cause);\n logger.error(message);\n\n if (cause instanceof Error && cause.stack !== undefined) {\n logger.debug(cause.stack);\n }\n\n process.exit(ERROR_EXIT_CODE);\n};\n\nconst withErrorBoundary = <T extends ArgsDef>(command: CommandDef<T>): CommandDef<T> => {\n const run = command.run;\n\n if (run === undefined) {\n return command;\n }\n\n return {\n ...command,\n run: async (context): Promise<unknown> => {\n try {\n return await run(context);\n } catch (error) {\n return printError(error);\n }\n },\n };\n};\n\nexport { withErrorBoundary };\n"]}
@@ -0,0 +1,10 @@
1
+ import { type ExecFileSyncOptions } from "node:child_process";
2
+ type CliToolInvocation = {
3
+ tool: string;
4
+ args: string[];
5
+ target?: string;
6
+ options?: ExecFileSyncOptions;
7
+ };
8
+ declare const runCliTool: ({ tool, args, target, options }: CliToolInvocation) => void;
9
+ export { runCliTool };
10
+ //# sourceMappingURL=run-cli-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-cli-tool.d.ts","sourceRoot":"","sources":["../../src/internal/run-cli-tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE5E,KAAK,iBAAiB,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,mBAAmB,CAAC;CACjC,CAAC;AAEF,QAAA,MAAM,UAAU,GAAI,iCAAiC,iBAAiB,KAAG,IASxE,CAAC;AAEF,OAAO,EAAE,UAAU,EAAE,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { formatChildProcessError, resolveExecutable } from "@gtkx/utils";
2
+ import { execFileSync } from "node:child_process";
3
+ const runCliTool = ({ tool, args, target, options }) => {
4
+ try {
5
+ execFileSync(resolveExecutable(tool), args, options);
6
+ }
7
+ catch (error) {
8
+ const details = formatChildProcessError(error);
9
+ const suffix = details ? `:\n${details}` : "";
10
+ const subject = target === undefined ? "" : ` for ${target}`;
11
+ throw new Error(`${tool} failed${subject}${suffix}`, { cause: error });
12
+ }
13
+ };
14
+ export { runCliTool };
15
+ //# sourceMappingURL=run-cli-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-cli-tool.js","sourceRoot":"","sources":["../../src/internal/run-cli-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,YAAY,EAA4B,MAAM,oBAAoB,CAAC;AAS5E,MAAM,UAAU,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAqB,EAAQ,EAAE;IAC5E,IAAI,CAAC;QACD,YAAY,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACzD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,uBAAuB,CAAC,KAAK,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,MAAM,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9C,MAAM,OAAO,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,MAAM,EAAE,CAAC;QAC7D,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,UAAU,OAAO,GAAG,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3E,CAAC;AACL,CAAC,CAAC;AAEF,OAAO,EAAE,UAAU,EAAE,CAAC","sourcesContent":["import { formatChildProcessError, resolveExecutable } from \"@gtkx/utils\";\nimport { execFileSync, type ExecFileSyncOptions } from \"node:child_process\";\n\ntype CliToolInvocation = {\n tool: string;\n args: string[];\n target?: string;\n options?: ExecFileSyncOptions;\n};\n\nconst runCliTool = ({ tool, args, target, options }: CliToolInvocation): void => {\n try {\n execFileSync(resolveExecutable(tool), args, options);\n } catch (error) {\n const details = formatChildProcessError(error);\n const suffix = details ? `:\\n${details}` : \"\";\n const subject = target === undefined ? \"\" : ` for ${target}`;\n throw new Error(`${tool} failed${subject}${suffix}`, { cause: error });\n }\n};\n\nexport { runCliTool };\n"]}
@@ -0,0 +1,3 @@
1
+ export { dispatch } from "./mcp/handlers.js";
2
+ export { WidgetRegistry } from "./mcp/widget-registry.js";
3
+ //# sourceMappingURL=internal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { dispatch } from "./mcp/handlers.js";
2
+ export { WidgetRegistry } from "./mcp/widget-registry.js";
3
+ //# sourceMappingURL=internal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC","sourcesContent":["export { dispatch } from \"./mcp/handlers.js\";\nexport { WidgetRegistry } from \"./mcp/widget-registry.js\";\n"]}
@@ -24,5 +24,5 @@ declare class McpClient {
24
24
  connect(): Promise<void>;
25
25
  disconnect(): void;
26
26
  }
27
- export { McpClient, type McpClientOptions };
27
+ export { McpClient };
28
28
  //# sourceMappingURL=client.d.ts.map
@@ -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,KAAK,gBAAgB,EAAE,CAAC"}
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 +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,EAAyB,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, type McpClientOptions };\n"]}
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"]}
@@ -5,5 +5,5 @@ type HandlerContext = {
5
5
  registry: WidgetRegistry;
6
6
  };
7
7
  declare const dispatch: (method: string, params: unknown, ctx: HandlerContext) => Promise<unknown>;
8
- export { dispatch, type HandlerContext };
8
+ export { dispatch };
9
9
  //# 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;AAYpC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAI3D,KAAK,cAAc,GAAG;IAClB,GAAG,EAAE,GAAG,CAAC,WAAW,CAAC;IACrB,QAAQ,EAAE,cAAc,CAAC;CAC5B,CAAC;AAyLF,QAAA,MAAM,QAAQ,GAAU,QAAQ,MAAM,EAAE,QAAQ,OAAO,EAAE,KAAK,cAAc,KAAG,OAAO,CAAC,OAAO,CAM7F,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAE,KAAK,cAAc,EAAE,CAAC"}
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,9 +1,8 @@
1
1
  import * as Gtk from "@gtkx/gi/gtk";
2
2
  import { invalidRequestError, methodNotFoundError, ServerRequestParamsSchemas, widgetNotFoundError, } from "@gtkx/mcp/internal";
3
- import { mkdirSync, writeFileSync } from "node:fs";
4
- import { dirname } from "node:path";
5
3
  import { serializeWidget } from "./serialize-widget.js";
6
4
  import { loadTestingModule } from "./testing-loader.js";
5
+ import { readWidgetProperties } from "./widget-properties.js";
7
6
  const HANDLERS = {
8
7
  "app.getWindows": validated(ServerRequestParamsSchemas["app.getWindows"], ({ registry }) => Promise.resolve({
9
8
  windows: registry.toplevels().map((window) => ({
@@ -23,31 +22,52 @@ const HANDLERS = {
23
22
  };
24
23
  }),
25
24
  "widget.query": validated(ServerRequestParamsSchemas["widget.query"], handleQuery),
26
- "widget.getProps": validated(ServerRequestParamsSchemas["widget.getProps"], async ({ registry }, params) => {
27
- const { testing, widget } = await widgetTarget(registry, params.widgetId);
28
- return serializeWidget(widget, (target) => registry.getOrCreateId(target), testing);
29
- }),
30
- "widget.click": validated(ServerRequestParamsSchemas["widget.click"], async ({ registry }, params) => {
31
- const { testing, widget } = await widgetTarget(registry, params.widgetId);
25
+ "widget.getProps": targeted(ServerRequestParamsSchemas["widget.getProps"], ({ registry }, { testing, widget }, params) => Promise.resolve({
26
+ ...(params.properties !== undefined && {
27
+ properties: readWidgetProperties(widget, params.properties, registry),
28
+ }),
29
+ ...serializeWidget(widget, (target) => registry.getOrCreateId(target), testing, params.maxDepth),
30
+ })),
31
+ "widget.click": targeted(ServerRequestParamsSchemas["widget.click"], async (_ctx, { testing, widget }) => {
32
32
  await testing.userEvent.click(widget);
33
33
  return { success: true };
34
34
  }),
35
- "widget.type": validated(ServerRequestParamsSchemas["widget.type"], async ({ registry }, params) => {
36
- const { testing, widget } = await widgetTarget(registry, params.widgetId);
35
+ "widget.type": targeted(ServerRequestParamsSchemas["widget.type"], async (_ctx, { testing, widget }, params) => {
37
36
  if (params.clear) {
38
37
  await testing.userEvent.clear(widget);
39
38
  }
40
39
  await testing.userEvent.type(widget, params.text);
41
40
  return { success: true };
42
41
  }),
43
- "widget.fireEvent": validated(ServerRequestParamsSchemas["widget.fireEvent"], async ({ registry }, params) => {
44
- const { testing, widget } = await widgetTarget(registry, params.widgetId);
42
+ "widget.fireEvent": targeted(ServerRequestParamsSchemas["widget.fireEvent"], async (_ctx, { testing, widget }, params) => {
45
43
  const signalArgs = (params.args ?? []).map((arg) => extractSignalArg(arg));
44
+ const isRealized = widget.getRealized();
45
+ const isMapped = widget.getMapped();
46
+ const isSensitive = widget.getSensitive();
46
47
  await testing.fireEvent(widget, params.signal, ...signalArgs);
47
- return { success: true };
48
+ return {
49
+ signal: params.signal,
50
+ isRealized,
51
+ isMapped,
52
+ isSensitive,
53
+ note: emissionNote(isRealized, isMapped),
54
+ };
48
55
  }),
49
56
  "widget.screenshot": validated(ServerRequestParamsSchemas["widget.screenshot"], handleScreenshot),
50
57
  };
58
+ const QUERY_RUNNERS = {
59
+ role: runRoleQuery,
60
+ text: runTextQuery,
61
+ name: runNameQuery,
62
+ labelText: runLabelTextQuery,
63
+ };
64
+ const SEARCHED_BY = {
65
+ role: "the accessible role, narrowed by any options given",
66
+ text: "the text the widget renders",
67
+ name: "the widget name (gtk_widget_get_name, which reports the GType name such as \"GtkButton\" when no name " +
68
+ "was set), the accessible label, and the text the widget renders",
69
+ labelText: "the accessible label, the labelled-by relation, and the label whose mnemonic targets the widget",
70
+ };
51
71
  function validated(schema, handler) {
52
72
  return (ctx, params) => {
53
73
  const parsed = schema.safeParse(params ?? {});
@@ -57,6 +77,9 @@ function validated(schema, handler) {
57
77
  return handler(ctx, parsed.data);
58
78
  };
59
79
  }
80
+ function targeted(schema, handler) {
81
+ return validated(schema, async (ctx, params) => handler(ctx, await widgetTarget(ctx.registry, params.widgetId), params));
82
+ }
60
83
  const widgetTarget = async (registry, widgetId) => ({
61
84
  testing: await loadTestingModule(),
62
85
  widget: requireWidget(registry, widgetId),
@@ -75,6 +98,15 @@ const extractSignalArg = (arg) => {
75
98
  const isTypedArg = typeof arg === "object" && arg !== null && "type" in arg && "value" in arg;
76
99
  return isTypedArg ? arg.value : arg;
77
100
  };
101
+ const emissionNote = (isRealized, isMapped) => {
102
+ if (isRealized && isMapped) {
103
+ return ("The signal was emitted. Default handlers that animate, such as a button activate, settle " +
104
+ "asynchronously, so read the widget again rather than assuming the effect has landed.");
105
+ }
106
+ return ("The signal was emitted on a widget that is not realized and mapped, so a default handler that " +
107
+ "requires a drawn widget does nothing. Present the containing window or open the containing " +
108
+ "popover first, then fire the signal again.");
109
+ };
78
110
  const resolveRole = (value) => {
79
111
  if (typeof value === "number") {
80
112
  return value;
@@ -90,33 +122,40 @@ const matchesOrEmpty = async (find) => {
90
122
  return [];
91
123
  }
92
124
  };
125
+ function runRoleQuery(testing, app, params) {
126
+ const roleValue = resolveRole(params.value);
127
+ if (roleValue === undefined) {
128
+ throw invalidRequestError(`Unknown accessible role "${String(params.value)}"; use the lowercase role shown in the ` +
129
+ "widget tree, e.g. \"button\", \"list\", \"list_item\", or \"checkbox\".");
130
+ }
131
+ return matchesOrEmpty(() => testing.findAllByRole(app, roleValue, params.options));
132
+ }
133
+ function runTextQuery(testing, app, params) {
134
+ return matchesOrEmpty(() => testing.findAllByText(app, String(params.value), params.options));
135
+ }
136
+ function runLabelTextQuery(testing, app, params) {
137
+ return matchesOrEmpty(() => testing.findAllByLabelText(app, String(params.value), params.options));
138
+ }
139
+ async function runNameQuery(testing, app, params) {
140
+ const matches = await Promise.all([
141
+ matchesOrEmpty(() => testing.findAllByName(app, String(params.value), params.options)),
142
+ runLabelTextQuery(testing, app, params),
143
+ runTextQuery(testing, app, params),
144
+ ]);
145
+ return [...new Set(matches.flat())];
146
+ }
147
+ const emptyQueryHint = (params) => `Nothing matched by:"${params.by}" value:"${String(params.value)}", which compared ${SEARCHED_BY[params.by]}. ` +
148
+ "Call gtkx_get_widget_tree to see what is mounted; by:\"name\" is the widest match, and by:\"role\" accepts " +
149
+ "options.name to match the accessible name of a known role.";
93
150
  async function handleQuery({ app, registry }, params) {
94
151
  const testing = await loadTestingModule();
95
- let widgets = [];
96
- switch (params.by) {
97
- case "role": {
98
- const roleValue = resolveRole(params.value);
99
- if (roleValue === undefined) {
100
- throw invalidRequestError(`Unknown accessible role "${String(params.value)}"; use the lowercase role shown in the ` +
101
- "widget tree, e.g. \"button\", \"list\", \"list_item\", or \"checkbox\".");
102
- }
103
- widgets = await matchesOrEmpty(() => testing.findAllByRole(app, roleValue, params.options));
104
- break;
105
- }
106
- case "text": {
107
- widgets = await matchesOrEmpty(() => testing.findAllByText(app, String(params.value), params.options));
108
- break;
109
- }
110
- case "name": {
111
- widgets = await matchesOrEmpty(() => testing.findAllByName(app, String(params.value), params.options));
112
- break;
113
- }
114
- case "labelText": {
115
- widgets = await matchesOrEmpty(() => testing.findAllByLabelText(app, String(params.value), params.options));
116
- break;
117
- }
118
- }
119
- return { widgets: widgets.map((w) => serializeWidget(w, (widget) => registry.getOrCreateId(widget), testing, 0)) };
152
+ const widgets = await QUERY_RUNNERS[params.by](testing, app, params);
153
+ const resolveId = (widget) => registry.getOrCreateId(widget);
154
+ return {
155
+ widgets: widgets.map((widget) => serializeWidget(widget, resolveId, testing, 0)),
156
+ searched: SEARCHED_BY[params.by],
157
+ ...(widgets.length === 0 && { hint: emptyQueryHint(params) }),
158
+ };
120
159
  }
121
160
  const defaultScreenshotTarget = (registry) => {
122
161
  const [toplevel] = registry.toplevels();
@@ -128,10 +167,8 @@ const defaultScreenshotTarget = (registry) => {
128
167
  async function handleScreenshot({ registry }, params) {
129
168
  const testing = await loadTestingModule();
130
169
  const target = params.windowId ? requireWidget(registry, params.windowId) : defaultScreenshotTarget(registry);
131
- const result = await testing.screenshot(target);
170
+ const result = await testing.screenshot(target, { path: params.path });
132
171
  if (params.path) {
133
- mkdirSync(dirname(params.path), { recursive: true });
134
- writeFileSync(params.path, Buffer.from(result.data, "base64"));
135
172
  return { data: result.data, mimeType: result.mimeType, savedPath: params.path };
136
173
  }
137
174
  return { data: result.data, mimeType: result.mimeType };