From 3cba445faf15099a2a2d3ca065d5dd46cb4a5e08 Mon Sep 17 00:00:00 2001 From: "Anthony Fu (via agent)" Date: Tue, 28 Jul 2026 06:39:54 +0000 Subject: [PATCH 1/4] refactor(recipes): rename openHelpers to commonRpcFunctions Move the open-in-editor/open-in-finder RPC recipe bundle from devframe/recipes/open-helpers to devframe/recipes/common-rpc-functions, renaming the exported openHelpers array to commonRpcFunctions. devframe/recipes/open-helpers remains as a deprecated compatibility shim (openHelpers aliased to commonRpcFunctions) so existing imports keep working. --- alias.ts | 1 + docs/.vitepress/config.ts | 2 +- docs/guide/standalone-cli.md | 4 +- ...pen-helpers.md => common-rpc-functions.md} | 12 +-- docs/helpers/index.md | 2 +- docs/helpers/utilities.md | 2 +- packages/devframe/package.json | 1 + ...s.test.ts => common-rpc-functions.test.ts} | 17 +++-- .../src/recipes/common-rpc-functions.ts | 66 +++++++++++++++++ packages/devframe/src/recipes/open-helpers.ts | 74 +++---------------- packages/devframe/tsdown.config.ts | 1 + plugins/messages/src/node/index.ts | 4 +- skills/devframe/SKILL.md | 2 +- .../common-rpc-functions.snapshot.d.ts | 64 ++++++++++++++++ .../recipes/common-rpc-functions.snapshot.js | 8 ++ .../recipes/open-helpers.snapshot.d.ts | 31 +------- .../devframe/recipes/open-helpers.snapshot.js | 1 + tsconfig.base.json | 3 + 18 files changed, 183 insertions(+), 112 deletions(-) rename docs/helpers/{open-helpers.md => common-rpc-functions.md} (74%) rename packages/devframe/src/recipes/__tests__/{open-helpers.test.ts => common-rpc-functions.test.ts} (53%) create mode 100644 packages/devframe/src/recipes/common-rpc-functions.ts create mode 100644 tests/__snapshots__/tsnapi/devframe/recipes/common-rpc-functions.snapshot.d.ts create mode 100644 tests/__snapshots__/tsnapi/devframe/recipes/common-rpc-functions.snapshot.js diff --git a/alias.ts b/alias.ts index 788d6b25..e53df041 100644 --- a/alias.ts +++ b/alias.ts @@ -73,6 +73,7 @@ export const alias = { '@devframes/plugin-terminals': p('terminals/src/index.ts'), '@devframes/plugin-git': p('git/src/index.ts'), 'devframe/recipes/interactive-auth': r('devframe/src/recipes/interactive-auth.ts'), + 'devframe/recipes/common-rpc-functions': r('devframe/src/recipes/common-rpc-functions.ts'), 'devframe/recipes/open-helpers': r('devframe/src/recipes/open-helpers.ts'), 'devframe/client': r('devframe/src/client/index.ts'), 'devframe': r('devframe/src'), diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 7b905336..c2c5e8d5 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -56,7 +56,7 @@ function helpersItems(prefix: string) { { text: 'Vite Bridge', link: `${prefix}/helpers/vite-bridge` }, { text: 'Nuxt Module', link: `${prefix}/helpers/nuxt` }, { text: 'Next Helper', link: `${prefix}/helpers/next` }, - { text: 'Open Helpers', link: `${prefix}/helpers/open-helpers` }, + { text: 'Common RPC Functions', link: `${prefix}/helpers/common-rpc-functions` }, { text: 'Interactive Auth', link: `${prefix}/helpers/interactive-auth` }, ] satisfies DefaultTheme.NavItemWithLink[] } diff --git a/docs/guide/standalone-cli.md b/docs/guide/standalone-cli.md index eb73c65e..3239d8f6 100644 --- a/docs/guide/standalone-cli.md +++ b/docs/guide/standalone-cli.md @@ -199,9 +199,9 @@ defineDevframe({ The adapter derives each flag's CAC option from its schema — booleans become `--verbose` / `--no-verbose`; everything else becomes `--depth `. Keys are camelCase in TypeScript, kebab-case on the command line (`configFile` → `--config-file`). Flags that aren't in your schema (`--host`, `--port`, or anything added via `cli.configure`) still pass through untouched. -## Open helpers +## Common RPC functions -For the two actions every CLI devtool needs — open a file in the editor, reveal a path in the OS file explorer — use the prebuilt recipes from `devframe/recipes/open-helpers` instead of re-implementing them. See [Helpers → Open Helpers](/helpers/open-helpers) for the full reference. +For the two actions every CLI devtool needs — open a file in the editor, reveal a path in the OS file explorer — use the prebuilt recipes from `devframe/recipes/common-rpc-functions` instead of re-implementing them. See [Helpers → Common RPC Functions](/helpers/common-rpc-functions) for the full reference. ## Snapshot queries for static builds diff --git a/docs/helpers/open-helpers.md b/docs/helpers/common-rpc-functions.md similarity index 74% rename from docs/helpers/open-helpers.md rename to docs/helpers/common-rpc-functions.md index 9e7b60bb..b5be0641 100644 --- a/docs/helpers/open-helpers.md +++ b/docs/helpers/common-rpc-functions.md @@ -2,18 +2,18 @@ outline: deep --- -# Open Helpers +# Common RPC Functions Prebuilt RPC actions for the two file-system actions every CLI devtool needs — opening a file in the editor, revealing a path in the OS file explorer. Use the recipe instead of re-implementing them so every devframe converges on the same registered names and payload shape. ```ts -import { openHelpers } from 'devframe/recipes/open-helpers' +import { commonRpcFunctions } from 'devframe/recipes/common-rpc-functions' defineDevframe({ id: 'my-tool', name: 'My Tool', setup(ctx) { - openHelpers.forEach(fn => ctx.rpc.register(fn)) + commonRpcFunctions.forEach(fn => ctx.rpc.register(fn)) }, }) ``` @@ -24,16 +24,18 @@ defineDevframe({ |--------|------------------|------|------|---------| | `openInEditor` | `devframe:open-in-editor` | `action` | `[filename: string]` | Open the file in the user's editor via [`launchEditor`](./utilities#devframe-utils-launch-editor). Accepts `file`, `file:line`, or `file:line:column`. | | `openInFinder` | `devframe:open-in-finder` | `action` | `[path: string]` | Reveal the path in the OS file explorer via [`open`](./utilities#devframe-utils-open). | -| `openHelpers` | — | `readonly [openInEditor, openInFinder]` | — | Convenience array for batch registration. | +| `commonRpcFunctions` | — | `readonly [openInEditor, openInFinder]` | — | Convenience array for batch registration. | Both functions are `action`-type RPCs returning `void` and use `valibot` schemas (`v.string()`) for their single argument. +The `devframe/recipes/open-helpers` entry (`openHelpers`) remains as a deprecated alias for this module — new code should import `commonRpcFunctions` from `devframe/recipes/common-rpc-functions`. + ## Pick and choose Register only the helper you need rather than the whole array: ```ts -import { openInEditor } from 'devframe/recipes/open-helpers' +import { openInEditor } from 'devframe/recipes/common-rpc-functions' defineDevframe({ id: 'my-tool', diff --git a/docs/helpers/index.md b/docs/helpers/index.md index f5f2c8a2..90a967b0 100644 --- a/docs/helpers/index.md +++ b/docs/helpers/index.md @@ -12,7 +12,7 @@ Helpers are the optional, opt-in surface around the core `defineDevframe` API: s | [Vite Bridge](./vite-bridge) | `devframe/helpers/vite` | Vite plugin for mounting a devframe inside any Vite-based host (Astro, SolidStart, plain Vite). | | [Nuxt Module](./nuxt) | `@devframes/nuxt` | Nuxt module that wires a Nuxt SPA as a devframe client and serves the dev-time RPC bridge. | | [Next Helper](./next) | `@devframes/next` | Route-handler host + React client for mounting devframes inside a Next.js App Router app (experimental). | -| [Open Helpers](./open-helpers) | `devframe/recipes/open-helpers` | Prebuilt RPC actions for "open in editor" and "reveal in Finder". | +| [Common RPC Functions](./common-rpc-functions) | `devframe/recipes/common-rpc-functions` | Prebuilt RPC actions for "open in editor" and "reveal in Finder". | | [Interactive Auth](./interactive-auth) | `devframe/recipes/interactive-auth` | Ready-made OTP auth layer — handshake, resolver gate, connect-time trust, and the code/link banner. | Helpers vs. [adapters](/adapters/): an adapter takes a `DevframeDefinition` and deploys it as a runnable surface (CLI, dev server, static build, MCP server). A helper is a smaller piece — a Vite plugin, a Nuxt module, a recipe, a utility function — that you compose alongside an adapter. diff --git a/docs/helpers/utilities.md b/docs/helpers/utilities.md index 20071e56..c886be91 100644 --- a/docs/helpers/utilities.md +++ b/docs/helpers/utilities.md @@ -46,7 +46,7 @@ launchEditor('src/main.ts:42:7') launchEditor('src/main.ts:42:7', 'code') ``` -The auto-detection reads the `LAUNCH_EDITOR` environment variable and falls back to common defaults. Most devframes consume this through the prebuilt `openInEditor` recipe — see [Open helpers](./open-helpers). +The auto-detection reads the `LAUNCH_EDITOR` environment variable and falls back to common defaults. Most devframes consume this through the prebuilt `openInEditor` recipe — see [Common RPC Functions](./common-rpc-functions). ### `devframe/utils/hash` diff --git a/packages/devframe/package.json b/packages/devframe/package.json index 67428a87..101a12f1 100644 --- a/packages/devframe/package.json +++ b/packages/devframe/package.json @@ -32,6 +32,7 @@ "./node": "./dist/node/index.mjs", "./node/auth": "./dist/node/auth.mjs", "./node/hub-internals": "./dist/node/hub-internals.mjs", + "./recipes/common-rpc-functions": "./dist/recipes/common-rpc-functions.mjs", "./recipes/interactive-auth": "./dist/recipes/interactive-auth.mjs", "./recipes/open-helpers": "./dist/recipes/open-helpers.mjs", "./rpc": "./dist/rpc/index.mjs", diff --git a/packages/devframe/src/recipes/__tests__/open-helpers.test.ts b/packages/devframe/src/recipes/__tests__/common-rpc-functions.test.ts similarity index 53% rename from packages/devframe/src/recipes/__tests__/open-helpers.test.ts rename to packages/devframe/src/recipes/__tests__/common-rpc-functions.test.ts index 5526e0bc..9a024ff6 100644 --- a/packages/devframe/src/recipes/__tests__/open-helpers.test.ts +++ b/packages/devframe/src/recipes/__tests__/common-rpc-functions.test.ts @@ -1,7 +1,8 @@ import { describe, expect, it } from 'vitest' -import { openHelpers, openInEditor, openInFinder } from '../open-helpers' +import { commonRpcFunctions, openInEditor, openInFinder } from '../common-rpc-functions' +import { openHelpers } from '../open-helpers' -describe('recipes/open-helpers', () => { +describe('recipes/common-rpc-functions', () => { it('exposes `openInEditor` as a devframe-namespaced action', () => { expect(openInEditor.name).toBe('devframe:open-in-editor') expect(openInEditor.type).toBe('action') @@ -16,9 +17,13 @@ describe('recipes/open-helpers', () => { expect(typeof openInFinder.handler).toBe('function') }) - it('bundles both helpers in `openHelpers`', () => { - expect(openHelpers).toHaveLength(2) - expect(openHelpers).toContain(openInEditor) - expect(openHelpers).toContain(openInFinder) + it('bundles both helpers in `commonRpcFunctions`', () => { + expect(commonRpcFunctions).toHaveLength(2) + expect(commonRpcFunctions).toContain(openInEditor) + expect(commonRpcFunctions).toContain(openInFinder) + }) + + it('keeps the deprecated `devframe/recipes/open-helpers` entry working as an alias', () => { + expect(openHelpers).toBe(commonRpcFunctions) }) }) diff --git a/packages/devframe/src/recipes/common-rpc-functions.ts b/packages/devframe/src/recipes/common-rpc-functions.ts new file mode 100644 index 00000000..b5816938 --- /dev/null +++ b/packages/devframe/src/recipes/common-rpc-functions.ts @@ -0,0 +1,66 @@ +import { launchEditor } from 'devframe/utils/launch-editor' +import { open } from 'devframe/utils/open' +import * as v from 'valibot' +import { defineRpcFunction } from '../rpc/define' + +/** + * Prebuilt RPC action that opens a file in the user's configured editor. + * + * Registered name: `devframe:open-in-editor`. + * + * ```ts + * import { openInEditor } from 'devframe/recipes/common-rpc-functions' + * + * defineDevframe({ + * id: 'my-tool', + * name: 'My Tool', + * setup(ctx) { + * ctx.rpc.register(openInEditor) + * }, + * }) + * ``` + */ +export const openInEditor = defineRpcFunction({ + name: 'devframe:open-in-editor', + type: 'action', + jsonSerializable: true, + args: [v.string()], + returns: v.void(), + async handler(filename: string) { + launchEditor(filename) + }, +}) + +/** + * Prebuilt RPC action that reveals a path in the OS file explorer. + * + * Registered name: `devframe:open-in-finder`. + * + * ```ts + * import { openInFinder } from 'devframe/recipes/common-rpc-functions' + * + * ctx.rpc.register(openInFinder) + * ``` + */ +export const openInFinder = defineRpcFunction({ + name: 'devframe:open-in-finder', + type: 'action', + jsonSerializable: true, + args: [v.string()], + returns: v.void(), + async handler(path: string) { + await open(path) + }, +}) + +/** + * Convenience array bundling both helpers so callers can register them + * in a single `forEach`. + * + * ```ts + * import { commonRpcFunctions } from 'devframe/recipes/common-rpc-functions' + * + * commonRpcFunctions.forEach(fn => ctx.rpc.register(fn)) + * ``` + */ +export const commonRpcFunctions = [openInEditor, openInFinder] as const diff --git a/packages/devframe/src/recipes/open-helpers.ts b/packages/devframe/src/recipes/open-helpers.ts index 274b2a4b..85c18ed7 100644 --- a/packages/devframe/src/recipes/open-helpers.ts +++ b/packages/devframe/src/recipes/open-helpers.ts @@ -1,66 +1,12 @@ -import { launchEditor } from 'devframe/utils/launch-editor' -import { open } from 'devframe/utils/open' -import * as v from 'valibot' -import { defineRpcFunction } from '../rpc/define' +// Deprecated compatibility shim for the open helpers recipe. +// +// Prefer the canonical `devframe/recipes/common-rpc-functions` entry. This +// module re-exports the same implementation under the historical name so +// existing imports keep working. It will be removed in a future major +// release. +import { commonRpcFunctions } from './common-rpc-functions' -/** - * Prebuilt RPC action that opens a file in the user's configured editor. - * - * Registered name: `devframe:open-in-editor`. - * - * ```ts - * import { openInEditor } from 'devframe/recipes/open-helpers' - * - * defineDevframe({ - * id: 'my-tool', - * name: 'My Tool', - * setup(ctx) { - * ctx.rpc.register(openInEditor) - * }, - * }) - * ``` - */ -export const openInEditor = defineRpcFunction({ - name: 'devframe:open-in-editor', - type: 'action', - jsonSerializable: true, - args: [v.string()], - returns: v.void(), - async handler(filename: string) { - launchEditor(filename) - }, -}) +export { openInEditor, openInFinder } from './common-rpc-functions' -/** - * Prebuilt RPC action that reveals a path in the OS file explorer. - * - * Registered name: `devframe:open-in-finder`. - * - * ```ts - * import { openInFinder } from 'devframe/recipes/open-helpers' - * - * ctx.rpc.register(openInFinder) - * ``` - */ -export const openInFinder = defineRpcFunction({ - name: 'devframe:open-in-finder', - type: 'action', - jsonSerializable: true, - args: [v.string()], - returns: v.void(), - async handler(path: string) { - await open(path) - }, -}) - -/** - * Convenience array bundling both helpers so callers can register them - * in a single `forEach`. - * - * ```ts - * import { openHelpers } from 'devframe/recipes/open-helpers' - * - * openHelpers.forEach(fn => ctx.rpc.register(fn)) - * ``` - */ -export const openHelpers = [openInEditor, openInFinder] as const +/** @deprecated Use `commonRpcFunctions` from `devframe/recipes/common-rpc-functions` instead. */ +export const openHelpers: typeof commonRpcFunctions = commonRpcFunctions diff --git a/packages/devframe/tsdown.config.ts b/packages/devframe/tsdown.config.ts index 1ca9eeef..ee003592 100644 --- a/packages/devframe/tsdown.config.ts +++ b/packages/devframe/tsdown.config.ts @@ -106,6 +106,7 @@ const serverEntries = { 'adapters/embedded': 'src/adapters/embedded.ts', 'adapters/mcp': 'src/adapters/mcp/index.ts', 'helpers/vite': 'src/helpers/vite.ts', + 'recipes/common-rpc-functions': 'src/recipes/common-rpc-functions.ts', 'recipes/open-helpers': 'src/recipes/open-helpers.ts', 'recipes/interactive-auth': 'src/recipes/interactive-auth.ts', } diff --git a/plugins/messages/src/node/index.ts b/plugins/messages/src/node/index.ts index 9d676e25..42e566bc 100644 --- a/plugins/messages/src/node/index.ts +++ b/plugins/messages/src/node/index.ts @@ -1,5 +1,5 @@ import type { DevframeNodeContext } from 'devframe/types' -import { openHelpers } from 'devframe/recipes/open-helpers' +import { commonRpcFunctions } from 'devframe/recipes/common-rpc-functions' import { PLUGIN_ID } from '../constants' import { diagnostics } from '../diagnostics' import { getMessagesHost } from '../rpc/functions/_define' @@ -26,7 +26,7 @@ export function setupMessages(ctx: DevframeNodeContext): void { // may have registered the helpers already — skip those. The recipes are // context-free (`SetupContext = undefined`, plain handlers); widening to // the node collector's context is safe. - for (const fn of openHelpers) { + for (const fn of commonRpcFunctions) { if (!ctx.rpc.definitions.has(fn.name)) ctx.rpc.register(fn as unknown as Parameters[0]) } diff --git a/skills/devframe/SKILL.md b/skills/devframe/SKILL.md index 60d1b2d9..fa844f1c 100644 --- a/skills/devframe/SKILL.md +++ b/skills/devframe/SKILL.md @@ -560,7 +560,7 @@ Devframe re-exports a curated set of helpers under `devframe/utils/*`. They are | `createStreamSink` / `createStreamReader` from `devframe/utils/streaming-channel` | — | Low-level streaming primitives | | `evaluateWhen` / `WhenExpression` from `devframe/utils/when` | `whenexpr` | When-clause expressions | -For "open file in editor" + "reveal in finder", prefer the prebuilt `openHelpers` RPC recipe — it wires the two utilities into named RPC functions ready to register. +For "open file in editor" + "reveal in finder", prefer the prebuilt `commonRpcFunctions` RPC recipe (`devframe/recipes/common-rpc-functions`) — it wires the two utilities into named RPC functions ready to register. ## Security (secure by default) diff --git a/tests/__snapshots__/tsnapi/devframe/recipes/common-rpc-functions.snapshot.d.ts b/tests/__snapshots__/tsnapi/devframe/recipes/common-rpc-functions.snapshot.d.ts new file mode 100644 index 00000000..e9d420ae --- /dev/null +++ b/tests/__snapshots__/tsnapi/devframe/recipes/common-rpc-functions.snapshot.d.ts @@ -0,0 +1,64 @@ +/** + * Generated by tsnapi — public API snapshot of `devframe/recipes/common-rpc-functions` + */ +// #region Variables +export declare const commonRpcFunctions: readonly [{ + name: "devframe:open-in-editor"; + type?: "action" | undefined; + cacheable?: boolean; + args: readonly [v.StringSchema]; + returns: v.VoidSchema; + jsonSerializable?: boolean; + agent?: RpcFunctionAgentOptions; + setup?: ((context: undefined) => Thenable>) | undefined; + handler?: ((args_0: string) => void) | undefined; + dump?: RpcDump<[string], void, undefined> | undefined; + snapshot?: boolean; + __cache?: WeakMap>> | undefined; + __promise?: Thenable> | undefined; +}, { + name: "devframe:open-in-finder"; + type?: "action" | undefined; + cacheable?: boolean; + args: readonly [v.StringSchema]; + returns: v.VoidSchema; + jsonSerializable?: boolean; + agent?: RpcFunctionAgentOptions; + setup?: ((context: undefined) => Thenable>) | undefined; + handler?: ((args_0: string) => void) | undefined; + dump?: RpcDump<[string], void, undefined> | undefined; + snapshot?: boolean; + __cache?: WeakMap>> | undefined; + __promise?: Thenable> | undefined; +}]; +export declare const openInEditor: { + name: "devframe:open-in-editor"; + type?: "action" | undefined; + cacheable?: boolean; + args: readonly [v.StringSchema]; + returns: v.VoidSchema; + jsonSerializable?: boolean; + agent?: RpcFunctionAgentOptions; + setup?: ((context: undefined) => Thenable>) | undefined; + handler?: ((args_0: string) => void) | undefined; + dump?: RpcDump<[string], void, undefined> | undefined; + snapshot?: boolean; + __cache?: WeakMap>> | undefined; + __promise?: Thenable> | undefined; +}; +export declare const openInFinder: { + name: "devframe:open-in-finder"; + type?: "action" | undefined; + cacheable?: boolean; + args: readonly [v.StringSchema]; + returns: v.VoidSchema; + jsonSerializable?: boolean; + agent?: RpcFunctionAgentOptions; + setup?: ((context: undefined) => Thenable>) | undefined; + handler?: ((args_0: string) => void) | undefined; + dump?: RpcDump<[string], void, undefined> | undefined; + snapshot?: boolean; + __cache?: WeakMap>> | undefined; + __promise?: Thenable> | undefined; +}; +// #endregion \ No newline at end of file diff --git a/tests/__snapshots__/tsnapi/devframe/recipes/common-rpc-functions.snapshot.js b/tests/__snapshots__/tsnapi/devframe/recipes/common-rpc-functions.snapshot.js new file mode 100644 index 00000000..d3c0bace --- /dev/null +++ b/tests/__snapshots__/tsnapi/devframe/recipes/common-rpc-functions.snapshot.js @@ -0,0 +1,8 @@ +/** + * Generated by tsnapi — public API snapshot of `devframe/recipes/common-rpc-functions` + */ +// #region Variables +export var commonRpcFunctions /* const */ +export var openInEditor /* const */ +export var openInFinder /* const */ +// #endregion \ No newline at end of file diff --git a/tests/__snapshots__/tsnapi/devframe/recipes/open-helpers.snapshot.d.ts b/tests/__snapshots__/tsnapi/devframe/recipes/open-helpers.snapshot.d.ts index ea53a20a..fa3f3935 100644 --- a/tests/__snapshots__/tsnapi/devframe/recipes/open-helpers.snapshot.d.ts +++ b/tests/__snapshots__/tsnapi/devframe/recipes/open-helpers.snapshot.d.ts @@ -2,35 +2,8 @@ * Generated by tsnapi — public API snapshot of `devframe/recipes/open-helpers` */ // #region Variables -export declare const openHelpers: readonly [{ - name: "devframe:open-in-editor"; - type?: "action" | undefined; - cacheable?: boolean; - args: readonly [v.StringSchema]; - returns: v.VoidSchema; - jsonSerializable?: boolean; - agent?: RpcFunctionAgentOptions; - setup?: ((context: undefined) => Thenable>) | undefined; - handler?: ((args_0: string) => void) | undefined; - dump?: RpcDump<[string], void, undefined> | undefined; - snapshot?: boolean; - __cache?: WeakMap>> | undefined; - __promise?: Thenable> | undefined; -}, { - name: "devframe:open-in-finder"; - type?: "action" | undefined; - cacheable?: boolean; - args: readonly [v.StringSchema]; - returns: v.VoidSchema; - jsonSerializable?: boolean; - agent?: RpcFunctionAgentOptions; - setup?: ((context: undefined) => Thenable>) | undefined; - handler?: ((args_0: string) => void) | undefined; - dump?: RpcDump<[string], void, undefined> | undefined; - snapshot?: boolean; - __cache?: WeakMap>> | undefined; - __promise?: Thenable> | undefined; -}]; +/** @deprecated */ +export declare const openHelpers: typeof commonRpcFunctions; export declare const openInEditor: { name: "devframe:open-in-editor"; type?: "action" | undefined; diff --git a/tests/__snapshots__/tsnapi/devframe/recipes/open-helpers.snapshot.js b/tests/__snapshots__/tsnapi/devframe/recipes/open-helpers.snapshot.js index 58ef90e9..98b63ad4 100644 --- a/tests/__snapshots__/tsnapi/devframe/recipes/open-helpers.snapshot.js +++ b/tests/__snapshots__/tsnapi/devframe/recipes/open-helpers.snapshot.js @@ -2,6 +2,7 @@ * Generated by tsnapi — public API snapshot of `devframe/recipes/open-helpers` */ // #region Variables +/** @deprecated */ export var openHelpers /* const */ export var openInEditor /* const */ export var openInFinder /* const */ diff --git a/tsconfig.base.json b/tsconfig.base.json index e6c6a69f..558a0a33 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -205,6 +205,9 @@ "devframe/recipes/interactive-auth": [ "./packages/devframe/src/recipes/interactive-auth.ts" ], + "devframe/recipes/common-rpc-functions": [ + "./packages/devframe/src/recipes/common-rpc-functions.ts" + ], "devframe/recipes/open-helpers": [ "./packages/devframe/src/recipes/open-helpers.ts" ], From e153305b0bbdcf4f0a0f3e7fc51be416bc23976d Mon Sep 17 00:00:00 2001 From: "Anthony Fu (via agent)" Date: Tue, 28 Jul 2026 07:32:52 +0000 Subject: [PATCH 2/4] feat(recipes): validate openInEditor's editor arg against known editors Load devframe/utils/launch-editor and devframe/utils/open lazily via dynamic import in the openInEditor/openInFinder handlers instead of a top-level import. openInEditor gains an optional second argument to pick the editor command explicitly. It's validated against a new KNOWN_EDITORS constant (and KnownEditor type) via v.picklist, so the RPC surface can't be used to spawn an arbitrary command. --- docs/helpers/common-rpc-functions.md | 9 ++- .../__tests__/common-rpc-functions.test.ts | 16 ++++- .../src/recipes/common-rpc-functions.ts | 59 +++++++++++++++++-- .../common-rpc-functions.snapshot.d.ts | 29 +++++---- .../recipes/common-rpc-functions.snapshot.js | 1 + .../recipes/open-helpers.snapshot.d.ts | 12 ++-- .../devframe/utils/launch-editor.snapshot.js | 4 +- 7 files changed, 100 insertions(+), 30 deletions(-) diff --git a/docs/helpers/common-rpc-functions.md b/docs/helpers/common-rpc-functions.md index b5be0641..b600c3ca 100644 --- a/docs/helpers/common-rpc-functions.md +++ b/docs/helpers/common-rpc-functions.md @@ -22,11 +22,13 @@ defineDevframe({ | Export | Registered name | Type | Args | Purpose | |--------|------------------|------|------|---------| -| `openInEditor` | `devframe:open-in-editor` | `action` | `[filename: string]` | Open the file in the user's editor via [`launchEditor`](./utilities#devframe-utils-launch-editor). Accepts `file`, `file:line`, or `file:line:column`. | +| `openInEditor` | `devframe:open-in-editor` | `action` | `[filename: string, editor?: KnownEditor]` | Open the file in the user's editor via [`launchEditor`](./utilities#devframe-utils-launch-editor). `filename` accepts `file`, `file:line`, or `file:line:column`. The optional `editor` picks the editor command explicitly instead of relying on auto-detection. | | `openInFinder` | `devframe:open-in-finder` | `action` | `[path: string]` | Reveal the path in the OS file explorer via [`open`](./utilities#devframe-utils-open). | | `commonRpcFunctions` | — | `readonly [openInEditor, openInFinder]` | — | Convenience array for batch registration. | +| `KNOWN_EDITORS` | — | `readonly string[]` | — | The editor commands `openInEditor`'s `editor` argument accepts (`code`, `vim`, `subl`, `idea`, …). | +| `KnownEditor` | — | type | — | Union of `KNOWN_EDITORS`. | -Both functions are `action`-type RPCs returning `void` and use `valibot` schemas (`v.string()`) for their single argument. +Both functions are `action`-type RPCs returning `void` and use `valibot` schemas for their arguments — `openInEditor`'s `editor` argument is `v.optional(v.picklist(KNOWN_EDITORS))`, so a value outside `KNOWN_EDITORS` fails validation rather than reaching the underlying `launch-editor` process spawn. Both handlers dynamically `import()` their underlying `devframe/utils/*` implementation, so the `launch-editor` and `open` dependencies only load when the recipe actually runs. The `devframe/recipes/open-helpers` entry (`openHelpers`) remains as a deprecated alias for this module — new code should import `commonRpcFunctions` from `devframe/recipes/common-rpc-functions`. @@ -52,7 +54,8 @@ The SPA calls these like any other RPC: ```ts const rpc = await connectDevframe() await rpc.call('devframe:open-in-editor', 'src/main.ts:42:7') +await rpc.call('devframe:open-in-editor', 'src/main.ts:42:7', 'code') await rpc.call('devframe:open-in-finder', '/abs/path/to/dir') ``` -`launchEditor`'s editor auto-detection reads the `LAUNCH_EDITOR` environment variable on the server side — there is no client-side configuration. +`launchEditor`'s editor auto-detection reads the `LAUNCH_EDITOR` environment variable on the server side when no `editor` argument is passed — there is no client-side configuration. diff --git a/packages/devframe/src/recipes/__tests__/common-rpc-functions.test.ts b/packages/devframe/src/recipes/__tests__/common-rpc-functions.test.ts index 9a024ff6..a4db8438 100644 --- a/packages/devframe/src/recipes/__tests__/common-rpc-functions.test.ts +++ b/packages/devframe/src/recipes/__tests__/common-rpc-functions.test.ts @@ -1,15 +1,27 @@ +import * as v from 'valibot' import { describe, expect, it } from 'vitest' -import { commonRpcFunctions, openInEditor, openInFinder } from '../common-rpc-functions' +import { commonRpcFunctions, KNOWN_EDITORS, openInEditor, openInFinder } from '../common-rpc-functions' import { openHelpers } from '../open-helpers' describe('recipes/common-rpc-functions', () => { it('exposes `openInEditor` as a devframe-namespaced action', () => { expect(openInEditor.name).toBe('devframe:open-in-editor') expect(openInEditor.type).toBe('action') - expect(openInEditor.args).toHaveLength(1) + expect(openInEditor.args).toHaveLength(2) expect(typeof openInEditor.handler).toBe('function') }) + it('restricts `openInEditor`\'s optional second argument to `KNOWN_EDITORS`', () => { + expect(KNOWN_EDITORS).toContain('code') + expect(KNOWN_EDITORS).toContain('vim') + + const editorSchema = openInEditor.args[1] + expect(v.safeParse(editorSchema, undefined).success).toBe(true) + for (const editor of KNOWN_EDITORS) + expect(v.safeParse(editorSchema, editor).success).toBe(true) + expect(v.safeParse(editorSchema, 'not-a-real-editor').success).toBe(false) + }) + it('exposes `openInFinder` as a devframe-namespaced action', () => { expect(openInFinder.name).toBe('devframe:open-in-finder') expect(openInFinder.type).toBe('action') diff --git a/packages/devframe/src/recipes/common-rpc-functions.ts b/packages/devframe/src/recipes/common-rpc-functions.ts index b5816938..2fd988d2 100644 --- a/packages/devframe/src/recipes/common-rpc-functions.ts +++ b/packages/devframe/src/recipes/common-rpc-functions.ts @@ -1,13 +1,60 @@ -import { launchEditor } from 'devframe/utils/launch-editor' -import { open } from 'devframe/utils/open' import * as v from 'valibot' import { defineRpcFunction } from '../rpc/define' +/** + * Editor commands that `launch-editor` (the library behind + * `devframe/utils/launch-editor`) recognizes with a tailored + * `file:line:column` invocation. `openInEditor`'s optional second argument + * is restricted to this list, so the RPC surface can't be used to spawn an + * arbitrary command. + */ +export const KNOWN_EDITORS = [ + 'atom', + 'subl', + 'sublime', + 'sublime_text', + 'wstorm', + 'charm', + 'zed', + 'notepad++', + 'vim', + 'mvim', + 'joe', + 'gvim', + 'emacs', + 'emacsclient', + 'rmate', + 'mate', + 'code', + 'code-insiders', + 'codium', + 'vscodium', + 'trae', + 'antigravity', + 'cursor', + 'appcode', + 'clion', + 'idea', + 'phpstorm', + 'pycharm', + 'rubymine', + 'webstorm', + 'goland', + 'rider', +] as const + +/** One of the editor commands in {@link KNOWN_EDITORS}. */ +export type KnownEditor = (typeof KNOWN_EDITORS)[number] + /** * Prebuilt RPC action that opens a file in the user's configured editor. * * Registered name: `devframe:open-in-editor`. * + * The optional second argument picks the editor command explicitly (must be + * one of {@link KNOWN_EDITORS}); otherwise it's auto-detected per + * `devframe/utils/launch-editor`. + * * ```ts * import { openInEditor } from 'devframe/recipes/common-rpc-functions' * @@ -24,10 +71,11 @@ export const openInEditor = defineRpcFunction({ name: 'devframe:open-in-editor', type: 'action', jsonSerializable: true, - args: [v.string()], + args: [v.string(), v.optional(v.picklist(KNOWN_EDITORS))], returns: v.void(), - async handler(filename: string) { - launchEditor(filename) + async handler(filename: string, editor?: KnownEditor) { + const { launchEditor } = await import('devframe/utils/launch-editor') + launchEditor(filename, editor) }, }) @@ -49,6 +97,7 @@ export const openInFinder = defineRpcFunction({ args: [v.string()], returns: v.void(), async handler(path: string) { + const { open } = await import('devframe/utils/open') await open(path) }, }) diff --git a/tests/__snapshots__/tsnapi/devframe/recipes/common-rpc-functions.snapshot.d.ts b/tests/__snapshots__/tsnapi/devframe/recipes/common-rpc-functions.snapshot.d.ts index e9d420ae..b0291c71 100644 --- a/tests/__snapshots__/tsnapi/devframe/recipes/common-rpc-functions.snapshot.d.ts +++ b/tests/__snapshots__/tsnapi/devframe/recipes/common-rpc-functions.snapshot.d.ts @@ -1,21 +1,25 @@ /** * Generated by tsnapi — public API snapshot of `devframe/recipes/common-rpc-functions` */ +// #region Types +export type KnownEditor = (typeof KNOWN_EDITORS)[number]; +// #endregion + // #region Variables export declare const commonRpcFunctions: readonly [{ name: "devframe:open-in-editor"; type?: "action" | undefined; cacheable?: boolean; - args: readonly [v.StringSchema]; + args: readonly [v.StringSchema, v.OptionalSchema, undefined>]; returns: v.VoidSchema; jsonSerializable?: boolean; agent?: RpcFunctionAgentOptions; - setup?: ((context: undefined) => Thenable>) | undefined; - handler?: ((args_0: string) => void) | undefined; - dump?: RpcDump<[string], void, undefined> | undefined; + setup?: ((context: undefined) => Thenable>) | undefined; + handler?: ((args_0: string, args_1: "atom" | "subl" | "sublime" | "sublime_text" | "wstorm" | "charm" | "zed" | "notepad++" | "vim" | "mvim" | "joe" | "gvim" | "emacs" | "emacsclient" | "rmate" | "mate" | "code" | "code-insiders" | "codium" | "vscodium" | "trae" | "antigravity" | "cursor" | "appcode" | "clion" | "idea" | "phpstorm" | "pycharm" | "rubymine" | "webstorm" | "goland" | "rider" | undefined) => void) | undefined; + dump?: RpcDump<[string, "atom" | "subl" | "sublime" | "sublime_text" | "wstorm" | "charm" | "zed" | "notepad++" | "vim" | "mvim" | "joe" | "gvim" | "emacs" | "emacsclient" | "rmate" | "mate" | "code" | "code-insiders" | "codium" | "vscodium" | "trae" | "antigravity" | "cursor" | "appcode" | "clion" | "idea" | "phpstorm" | "pycharm" | "rubymine" | "webstorm" | "goland" | "rider" | undefined], void, undefined> | undefined; snapshot?: boolean; - __cache?: WeakMap>> | undefined; - __promise?: Thenable> | undefined; + __cache?: WeakMap>> | undefined; + __promise?: Thenable> | undefined; }, { name: "devframe:open-in-finder"; type?: "action" | undefined; @@ -31,20 +35,21 @@ export declare const commonRpcFunctions: readonly [{ __cache?: WeakMap>> | undefined; __promise?: Thenable> | undefined; }]; +export declare const KNOWN_EDITORS: readonly ["atom", "subl", "sublime", "sublime_text", "wstorm", "charm", "zed", "notepad++", "vim", "mvim", "joe", "gvim", "emacs", "emacsclient", "rmate", "mate", "code", "code-insiders", "codium", "vscodium", "trae", "antigravity", "cursor", "appcode", "clion", "idea", "phpstorm", "pycharm", "rubymine", "webstorm", "goland", "rider"]; export declare const openInEditor: { name: "devframe:open-in-editor"; type?: "action" | undefined; cacheable?: boolean; - args: readonly [v.StringSchema]; + args: readonly [v.StringSchema, v.OptionalSchema, undefined>]; returns: v.VoidSchema; jsonSerializable?: boolean; agent?: RpcFunctionAgentOptions; - setup?: ((context: undefined) => Thenable>) | undefined; - handler?: ((args_0: string) => void) | undefined; - dump?: RpcDump<[string], void, undefined> | undefined; + setup?: ((context: undefined) => Thenable>) | undefined; + handler?: ((args_0: string, args_1: "atom" | "subl" | "sublime" | "sublime_text" | "wstorm" | "charm" | "zed" | "notepad++" | "vim" | "mvim" | "joe" | "gvim" | "emacs" | "emacsclient" | "rmate" | "mate" | "code" | "code-insiders" | "codium" | "vscodium" | "trae" | "antigravity" | "cursor" | "appcode" | "clion" | "idea" | "phpstorm" | "pycharm" | "rubymine" | "webstorm" | "goland" | "rider" | undefined) => void) | undefined; + dump?: RpcDump<[string, "atom" | "subl" | "sublime" | "sublime_text" | "wstorm" | "charm" | "zed" | "notepad++" | "vim" | "mvim" | "joe" | "gvim" | "emacs" | "emacsclient" | "rmate" | "mate" | "code" | "code-insiders" | "codium" | "vscodium" | "trae" | "antigravity" | "cursor" | "appcode" | "clion" | "idea" | "phpstorm" | "pycharm" | "rubymine" | "webstorm" | "goland" | "rider" | undefined], void, undefined> | undefined; snapshot?: boolean; - __cache?: WeakMap>> | undefined; - __promise?: Thenable> | undefined; + __cache?: WeakMap>> | undefined; + __promise?: Thenable> | undefined; }; export declare const openInFinder: { name: "devframe:open-in-finder"; diff --git a/tests/__snapshots__/tsnapi/devframe/recipes/common-rpc-functions.snapshot.js b/tests/__snapshots__/tsnapi/devframe/recipes/common-rpc-functions.snapshot.js index d3c0bace..244b9591 100644 --- a/tests/__snapshots__/tsnapi/devframe/recipes/common-rpc-functions.snapshot.js +++ b/tests/__snapshots__/tsnapi/devframe/recipes/common-rpc-functions.snapshot.js @@ -3,6 +3,7 @@ */ // #region Variables export var commonRpcFunctions /* const */ +export var KNOWN_EDITORS /* const */ export var openInEditor /* const */ export var openInFinder /* const */ // #endregion \ No newline at end of file diff --git a/tests/__snapshots__/tsnapi/devframe/recipes/open-helpers.snapshot.d.ts b/tests/__snapshots__/tsnapi/devframe/recipes/open-helpers.snapshot.d.ts index fa3f3935..872aef73 100644 --- a/tests/__snapshots__/tsnapi/devframe/recipes/open-helpers.snapshot.d.ts +++ b/tests/__snapshots__/tsnapi/devframe/recipes/open-helpers.snapshot.d.ts @@ -8,16 +8,16 @@ export declare const openInEditor: { name: "devframe:open-in-editor"; type?: "action" | undefined; cacheable?: boolean; - args: readonly [v.StringSchema]; + args: readonly [v.StringSchema, v.OptionalSchema, undefined>]; returns: v.VoidSchema; jsonSerializable?: boolean; agent?: RpcFunctionAgentOptions; - setup?: ((context: undefined) => Thenable>) | undefined; - handler?: ((args_0: string) => void) | undefined; - dump?: RpcDump<[string], void, undefined> | undefined; + setup?: ((context: undefined) => Thenable>) | undefined; + handler?: ((args_0: string, args_1: "atom" | "subl" | "sublime" | "sublime_text" | "wstorm" | "charm" | "zed" | "notepad++" | "vim" | "mvim" | "joe" | "gvim" | "emacs" | "emacsclient" | "rmate" | "mate" | "code" | "code-insiders" | "codium" | "vscodium" | "trae" | "antigravity" | "cursor" | "appcode" | "clion" | "idea" | "phpstorm" | "pycharm" | "rubymine" | "webstorm" | "goland" | "rider" | undefined) => void) | undefined; + dump?: RpcDump<[string, "atom" | "subl" | "sublime" | "sublime_text" | "wstorm" | "charm" | "zed" | "notepad++" | "vim" | "mvim" | "joe" | "gvim" | "emacs" | "emacsclient" | "rmate" | "mate" | "code" | "code-insiders" | "codium" | "vscodium" | "trae" | "antigravity" | "cursor" | "appcode" | "clion" | "idea" | "phpstorm" | "pycharm" | "rubymine" | "webstorm" | "goland" | "rider" | undefined], void, undefined> | undefined; snapshot?: boolean; - __cache?: WeakMap>> | undefined; - __promise?: Thenable> | undefined; + __cache?: WeakMap>> | undefined; + __promise?: Thenable> | undefined; }; export declare const openInFinder: { name: "devframe:open-in-finder"; diff --git a/tests/__snapshots__/tsnapi/devframe/utils/launch-editor.snapshot.js b/tests/__snapshots__/tsnapi/devframe/utils/launch-editor.snapshot.js index 556e756d..6a853fac 100644 --- a/tests/__snapshots__/tsnapi/devframe/utils/launch-editor.snapshot.js +++ b/tests/__snapshots__/tsnapi/devframe/utils/launch-editor.snapshot.js @@ -1,6 +1,6 @@ /** * Generated by tsnapi — public API snapshot of `devframe/utils/launch-editor` */ -// #region Other -export { launchEditor } +// #region Functions +export function launchEditor(_, _) {} // #endregion \ No newline at end of file From a7f85e6f0ae9d72f2d7af6ff1a084d30010ae439 Mon Sep 17 00:00:00 2001 From: "Anthony Fu (via agent)" Date: Tue, 28 Jul 2026 09:58:06 +0000 Subject: [PATCH 3/4] refactor(recipes): declare KnownEditor as a literal union MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Write KnownEditor directly as a union of editor-command literals instead of deriving it via (typeof KNOWN_EDITORS)[number] — the tsnapi snapshot now prints the actual union instead of the indexed access expression. KNOWN_EDITORS is now typed against KnownEditor (as const satisfies readonly KnownEditor[]) to keep the two in sync. --- .../src/recipes/common-rpc-functions.ts | 42 ++++++++++++++++--- .../common-rpc-functions.snapshot.d.ts | 2 +- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/packages/devframe/src/recipes/common-rpc-functions.ts b/packages/devframe/src/recipes/common-rpc-functions.ts index 2fd988d2..5abc68a4 100644 --- a/packages/devframe/src/recipes/common-rpc-functions.ts +++ b/packages/devframe/src/recipes/common-rpc-functions.ts @@ -5,9 +5,44 @@ import { defineRpcFunction } from '../rpc/define' * Editor commands that `launch-editor` (the library behind * `devframe/utils/launch-editor`) recognizes with a tailored * `file:line:column` invocation. `openInEditor`'s optional second argument - * is restricted to this list, so the RPC surface can't be used to spawn an + * is restricted to this union, so the RPC surface can't be used to spawn an * arbitrary command. */ +export type KnownEditor + = | 'atom' + | 'subl' + | 'sublime' + | 'sublime_text' + | 'wstorm' + | 'charm' + | 'zed' + | 'notepad++' + | 'vim' + | 'mvim' + | 'joe' + | 'gvim' + | 'emacs' + | 'emacsclient' + | 'rmate' + | 'mate' + | 'code' + | 'code-insiders' + | 'codium' + | 'vscodium' + | 'trae' + | 'antigravity' + | 'cursor' + | 'appcode' + | 'clion' + | 'idea' + | 'phpstorm' + | 'pycharm' + | 'rubymine' + | 'webstorm' + | 'goland' + | 'rider' + +/** Runtime list of every {@link KnownEditor}, in the order `v.picklist` reports them. */ export const KNOWN_EDITORS = [ 'atom', 'subl', @@ -41,10 +76,7 @@ export const KNOWN_EDITORS = [ 'webstorm', 'goland', 'rider', -] as const - -/** One of the editor commands in {@link KNOWN_EDITORS}. */ -export type KnownEditor = (typeof KNOWN_EDITORS)[number] +] as const satisfies readonly KnownEditor[] /** * Prebuilt RPC action that opens a file in the user's configured editor. diff --git a/tests/__snapshots__/tsnapi/devframe/recipes/common-rpc-functions.snapshot.d.ts b/tests/__snapshots__/tsnapi/devframe/recipes/common-rpc-functions.snapshot.d.ts index b0291c71..381892a6 100644 --- a/tests/__snapshots__/tsnapi/devframe/recipes/common-rpc-functions.snapshot.d.ts +++ b/tests/__snapshots__/tsnapi/devframe/recipes/common-rpc-functions.snapshot.d.ts @@ -2,7 +2,7 @@ * Generated by tsnapi — public API snapshot of `devframe/recipes/common-rpc-functions` */ // #region Types -export type KnownEditor = (typeof KNOWN_EDITORS)[number]; +export type KnownEditor = 'atom' | 'subl' | 'sublime' | 'sublime_text' | 'wstorm' | 'charm' | 'zed' | 'notepad++' | 'vim' | 'mvim' | 'joe' | 'gvim' | 'emacs' | 'emacsclient' | 'rmate' | 'mate' | 'code' | 'code-insiders' | 'codium' | 'vscodium' | 'trae' | 'antigravity' | 'cursor' | 'appcode' | 'clion' | 'idea' | 'phpstorm' | 'pycharm' | 'rubymine' | 'webstorm' | 'goland' | 'rider'; // #endregion // #region Variables From 32d54086dbaff303835d7a0954c478c0e98b680b Mon Sep 17 00:00:00 2001 From: Anthony Fu Date: Tue, 28 Jul 2026 19:10:04 +0900 Subject: [PATCH 4/4] chore: update --- .../src/recipes/common-rpc-functions.ts | 6 ++--- .../common-rpc-functions.snapshot.d.ts | 26 +++++++++---------- .../recipes/open-helpers.snapshot.d.ts | 12 ++++----- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/packages/devframe/src/recipes/common-rpc-functions.ts b/packages/devframe/src/recipes/common-rpc-functions.ts index 5abc68a4..927164be 100644 --- a/packages/devframe/src/recipes/common-rpc-functions.ts +++ b/packages/devframe/src/recipes/common-rpc-functions.ts @@ -43,7 +43,7 @@ export type KnownEditor | 'rider' /** Runtime list of every {@link KnownEditor}, in the order `v.picklist` reports them. */ -export const KNOWN_EDITORS = [ +export const KNOWN_EDITORS: KnownEditor[] = [ 'atom', 'subl', 'sublime', @@ -76,7 +76,7 @@ export const KNOWN_EDITORS = [ 'webstorm', 'goland', 'rider', -] as const satisfies readonly KnownEditor[] +] /** * Prebuilt RPC action that opens a file in the user's configured editor. @@ -103,7 +103,7 @@ export const openInEditor = defineRpcFunction({ name: 'devframe:open-in-editor', type: 'action', jsonSerializable: true, - args: [v.string(), v.optional(v.picklist(KNOWN_EDITORS))], + args: [v.string(), v.optional(v.picklist(KNOWN_EDITORS))], returns: v.void(), async handler(filename: string, editor?: KnownEditor) { const { launchEditor } = await import('devframe/utils/launch-editor') diff --git a/tests/__snapshots__/tsnapi/devframe/recipes/common-rpc-functions.snapshot.d.ts b/tests/__snapshots__/tsnapi/devframe/recipes/common-rpc-functions.snapshot.d.ts index 381892a6..7114a897 100644 --- a/tests/__snapshots__/tsnapi/devframe/recipes/common-rpc-functions.snapshot.d.ts +++ b/tests/__snapshots__/tsnapi/devframe/recipes/common-rpc-functions.snapshot.d.ts @@ -10,16 +10,16 @@ export declare const commonRpcFunctions: readonly [{ name: "devframe:open-in-editor"; type?: "action" | undefined; cacheable?: boolean; - args: readonly [v.StringSchema, v.OptionalSchema, undefined>]; + args: readonly [v.StringSchema, v.OptionalSchema, undefined>]; returns: v.VoidSchema; jsonSerializable?: boolean; agent?: RpcFunctionAgentOptions; - setup?: ((context: undefined) => Thenable>) | undefined; - handler?: ((args_0: string, args_1: "atom" | "subl" | "sublime" | "sublime_text" | "wstorm" | "charm" | "zed" | "notepad++" | "vim" | "mvim" | "joe" | "gvim" | "emacs" | "emacsclient" | "rmate" | "mate" | "code" | "code-insiders" | "codium" | "vscodium" | "trae" | "antigravity" | "cursor" | "appcode" | "clion" | "idea" | "phpstorm" | "pycharm" | "rubymine" | "webstorm" | "goland" | "rider" | undefined) => void) | undefined; - dump?: RpcDump<[string, "atom" | "subl" | "sublime" | "sublime_text" | "wstorm" | "charm" | "zed" | "notepad++" | "vim" | "mvim" | "joe" | "gvim" | "emacs" | "emacsclient" | "rmate" | "mate" | "code" | "code-insiders" | "codium" | "vscodium" | "trae" | "antigravity" | "cursor" | "appcode" | "clion" | "idea" | "phpstorm" | "pycharm" | "rubymine" | "webstorm" | "goland" | "rider" | undefined], void, undefined> | undefined; + setup?: ((context: undefined) => Thenable>) | undefined; + handler?: ((args_0: string, args_1: KnownEditor | undefined) => void) | undefined; + dump?: RpcDump<[string, KnownEditor | undefined], void, undefined> | undefined; snapshot?: boolean; - __cache?: WeakMap>> | undefined; - __promise?: Thenable> | undefined; + __cache?: WeakMap>> | undefined; + __promise?: Thenable> | undefined; }, { name: "devframe:open-in-finder"; type?: "action" | undefined; @@ -35,21 +35,21 @@ export declare const commonRpcFunctions: readonly [{ __cache?: WeakMap>> | undefined; __promise?: Thenable> | undefined; }]; -export declare const KNOWN_EDITORS: readonly ["atom", "subl", "sublime", "sublime_text", "wstorm", "charm", "zed", "notepad++", "vim", "mvim", "joe", "gvim", "emacs", "emacsclient", "rmate", "mate", "code", "code-insiders", "codium", "vscodium", "trae", "antigravity", "cursor", "appcode", "clion", "idea", "phpstorm", "pycharm", "rubymine", "webstorm", "goland", "rider"]; +export declare const KNOWN_EDITORS: KnownEditor[]; export declare const openInEditor: { name: "devframe:open-in-editor"; type?: "action" | undefined; cacheable?: boolean; - args: readonly [v.StringSchema, v.OptionalSchema, undefined>]; + args: readonly [v.StringSchema, v.OptionalSchema, undefined>]; returns: v.VoidSchema; jsonSerializable?: boolean; agent?: RpcFunctionAgentOptions; - setup?: ((context: undefined) => Thenable>) | undefined; - handler?: ((args_0: string, args_1: "atom" | "subl" | "sublime" | "sublime_text" | "wstorm" | "charm" | "zed" | "notepad++" | "vim" | "mvim" | "joe" | "gvim" | "emacs" | "emacsclient" | "rmate" | "mate" | "code" | "code-insiders" | "codium" | "vscodium" | "trae" | "antigravity" | "cursor" | "appcode" | "clion" | "idea" | "phpstorm" | "pycharm" | "rubymine" | "webstorm" | "goland" | "rider" | undefined) => void) | undefined; - dump?: RpcDump<[string, "atom" | "subl" | "sublime" | "sublime_text" | "wstorm" | "charm" | "zed" | "notepad++" | "vim" | "mvim" | "joe" | "gvim" | "emacs" | "emacsclient" | "rmate" | "mate" | "code" | "code-insiders" | "codium" | "vscodium" | "trae" | "antigravity" | "cursor" | "appcode" | "clion" | "idea" | "phpstorm" | "pycharm" | "rubymine" | "webstorm" | "goland" | "rider" | undefined], void, undefined> | undefined; + setup?: ((context: undefined) => Thenable>) | undefined; + handler?: ((args_0: string, args_1: KnownEditor | undefined) => void) | undefined; + dump?: RpcDump<[string, KnownEditor | undefined], void, undefined> | undefined; snapshot?: boolean; - __cache?: WeakMap>> | undefined; - __promise?: Thenable> | undefined; + __cache?: WeakMap>> | undefined; + __promise?: Thenable> | undefined; }; export declare const openInFinder: { name: "devframe:open-in-finder"; diff --git a/tests/__snapshots__/tsnapi/devframe/recipes/open-helpers.snapshot.d.ts b/tests/__snapshots__/tsnapi/devframe/recipes/open-helpers.snapshot.d.ts index 872aef73..436d011f 100644 --- a/tests/__snapshots__/tsnapi/devframe/recipes/open-helpers.snapshot.d.ts +++ b/tests/__snapshots__/tsnapi/devframe/recipes/open-helpers.snapshot.d.ts @@ -8,16 +8,16 @@ export declare const openInEditor: { name: "devframe:open-in-editor"; type?: "action" | undefined; cacheable?: boolean; - args: readonly [v.StringSchema, v.OptionalSchema, undefined>]; + args: readonly [v.StringSchema, v.OptionalSchema, undefined>]; returns: v.VoidSchema; jsonSerializable?: boolean; agent?: RpcFunctionAgentOptions; - setup?: ((context: undefined) => Thenable>) | undefined; - handler?: ((args_0: string, args_1: "atom" | "subl" | "sublime" | "sublime_text" | "wstorm" | "charm" | "zed" | "notepad++" | "vim" | "mvim" | "joe" | "gvim" | "emacs" | "emacsclient" | "rmate" | "mate" | "code" | "code-insiders" | "codium" | "vscodium" | "trae" | "antigravity" | "cursor" | "appcode" | "clion" | "idea" | "phpstorm" | "pycharm" | "rubymine" | "webstorm" | "goland" | "rider" | undefined) => void) | undefined; - dump?: RpcDump<[string, "atom" | "subl" | "sublime" | "sublime_text" | "wstorm" | "charm" | "zed" | "notepad++" | "vim" | "mvim" | "joe" | "gvim" | "emacs" | "emacsclient" | "rmate" | "mate" | "code" | "code-insiders" | "codium" | "vscodium" | "trae" | "antigravity" | "cursor" | "appcode" | "clion" | "idea" | "phpstorm" | "pycharm" | "rubymine" | "webstorm" | "goland" | "rider" | undefined], void, undefined> | undefined; + setup?: ((context: undefined) => Thenable>) | undefined; + handler?: ((args_0: string, args_1: KnownEditor | undefined) => void) | undefined; + dump?: RpcDump<[string, KnownEditor | undefined], void, undefined> | undefined; snapshot?: boolean; - __cache?: WeakMap>> | undefined; - __promise?: Thenable> | undefined; + __cache?: WeakMap>> | undefined; + __promise?: Thenable> | undefined; }; export declare const openInFinder: { name: "devframe:open-in-finder";