convex 1.48.0 → 1.49.0-alpha.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.
- package/CHANGELOG.md +7 -0
- package/dist/browser.bundle.js +1 -1
- package/dist/browser.bundle.js.map +1 -1
- package/dist/cjs/bundler/context.js +7 -5
- package/dist/cjs/bundler/context.js.map +2 -2
- package/dist/cjs/bundler/fs.js +47 -6
- package/dist/cjs/bundler/fs.js.map +2 -2
- package/dist/cjs/cli/account.js +237 -0
- package/dist/cjs/cli/account.js.map +7 -0
- package/dist/cjs/cli/configure.js +15 -2
- package/dist/cjs/cli/configure.js.map +2 -2
- package/dist/cjs/cli/lib/accountManagement.js +196 -0
- package/dist/cjs/cli/lib/accountManagement.js.map +7 -0
- package/dist/cjs/cli/lib/accounts.js +334 -0
- package/dist/cjs/cli/lib/accounts.js.map +7 -0
- package/dist/cjs/cli/lib/deployKeyWarning.js +43 -0
- package/dist/cjs/cli/lib/deployKeyWarning.js.map +7 -0
- package/dist/cjs/cli/lib/deployment.js +2 -0
- package/dist/cjs/cli/lib/deployment.js.map +2 -2
- package/dist/cjs/cli/lib/deploymentSelection.js +27 -18
- package/dist/cjs/cli/lib/deploymentSelection.js.map +2 -2
- package/dist/cjs/cli/lib/envvars.js +32 -0
- package/dist/cjs/cli/lib/envvars.js.map +2 -2
- package/dist/cjs/cli/lib/fsUtils.js +1 -1
- package/dist/cjs/cli/lib/fsUtils.js.map +2 -2
- package/dist/cjs/cli/lib/generateDocs.js +1 -1
- package/dist/cjs/cli/lib/generateDocs.js.map +1 -1
- package/dist/cjs/cli/lib/login.js +42 -4
- package/dist/cjs/cli/lib/login.js.map +3 -3
- package/dist/cjs/cli/lib/mcp/requestContext.js +5 -1
- package/dist/cjs/cli/lib/mcp/requestContext.js.map +2 -2
- package/dist/cjs/cli/lib/plugins/claudeCode.js +188 -0
- package/dist/cjs/cli/lib/plugins/claudeCode.js.map +7 -0
- package/dist/cjs/cli/lib/plugins/codex.js +167 -0
- package/dist/cjs/cli/lib/plugins/codex.js.map +7 -0
- package/dist/cjs/cli/lib/plugins/harness.js +50 -0
- package/dist/cjs/cli/lib/plugins/harness.js.map +7 -0
- package/dist/cjs/cli/lib/plugins/marketplaces.js +76 -0
- package/dist/cjs/cli/lib/plugins/marketplaces.js.map +7 -0
- package/dist/cjs/cli/lib/plugins/skills.js +98 -0
- package/dist/cjs/cli/lib/plugins/skills.js.map +7 -0
- package/dist/cjs/cli/lib/plugins/utils.js +125 -0
- package/dist/cjs/cli/lib/plugins/utils.js.map +7 -0
- package/dist/cjs/cli/lib/utils/utils.js +18 -9
- package/dist/cjs/cli/lib/utils/utils.js.map +2 -2
- package/dist/cjs/cli/login.js +213 -114
- package/dist/cjs/cli/login.js.map +3 -3
- package/dist/cjs/cli/logout.js +113 -12
- package/dist/cjs/cli/logout.js.map +3 -3
- package/dist/cjs/cli/mcp.js +43 -10
- package/dist/cjs/cli/mcp.js.map +3 -3
- package/dist/cjs/cli/plugins.js +114 -0
- package/dist/cjs/cli/plugins.js.map +7 -0
- package/dist/cjs/cli/program.js +3 -1
- package/dist/cjs/cli/program.js.map +2 -2
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/server/impl/actions_impl.js.map +2 -2
- package/dist/cjs-types/bundler/context.d.ts +5 -0
- package/dist/cjs-types/bundler/context.d.ts.map +1 -1
- package/dist/cjs-types/bundler/fs.d.ts +7 -2
- package/dist/cjs-types/bundler/fs.d.ts.map +1 -1
- package/dist/cjs-types/cli/account.d.ts +6 -0
- package/dist/cjs-types/cli/account.d.ts.map +1 -0
- package/dist/cjs-types/cli/configure.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/accountManagement.d.ts +10 -0
- package/dist/cjs-types/cli/lib/accountManagement.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/accounts.d.ts +59 -0
- package/dist/cjs-types/cli/lib/accounts.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/deployKeyWarning.d.ts +3 -0
- package/dist/cjs-types/cli/lib/deployKeyWarning.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/deployment.d.ts +2 -0
- package/dist/cjs-types/cli/lib/deployment.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/deploymentSelection.d.ts +2 -1
- package/dist/cjs-types/cli/lib/deploymentSelection.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/envvars.d.ts +6 -0
- package/dist/cjs-types/cli/lib/envvars.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/fsUtils.d.ts +1 -0
- package/dist/cjs-types/cli/lib/fsUtils.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/login.d.ts +3 -1
- package/dist/cjs-types/cli/lib/login.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/mcp/requestContext.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/mcp/tools/insights.d.ts +2 -2
- package/dist/cjs-types/cli/lib/plugins/claudeCode.d.ts +25 -0
- package/dist/cjs-types/cli/lib/plugins/claudeCode.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/plugins/codex.d.ts +25 -0
- package/dist/cjs-types/cli/lib/plugins/codex.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/plugins/harness.d.ts +33 -0
- package/dist/cjs-types/cli/lib/plugins/harness.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/plugins/marketplaces.d.ts +40 -0
- package/dist/cjs-types/cli/lib/plugins/marketplaces.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/plugins/skills.d.ts +18 -0
- package/dist/cjs-types/cli/lib/plugins/skills.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/plugins/utils.d.ts +21 -0
- package/dist/cjs-types/cli/lib/plugins/utils.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/utils/utils.d.ts +5 -0
- package/dist/cjs-types/cli/lib/utils/utils.d.ts.map +1 -1
- package/dist/cjs-types/cli/login.d.ts +21 -0
- package/dist/cjs-types/cli/login.d.ts.map +1 -1
- package/dist/cjs-types/cli/logout.d.ts +8 -1
- package/dist/cjs-types/cli/logout.d.ts.map +1 -1
- package/dist/cjs-types/cli/mcp.d.ts.map +1 -1
- package/dist/cjs-types/cli/plugins.d.ts +3 -0
- package/dist/cjs-types/cli/plugins.d.ts.map +1 -0
- package/dist/cjs-types/cli/program.d.ts.map +1 -1
- package/dist/cjs-types/index.d.ts +1 -1
- package/dist/cjs-types/index.d.ts.map +1 -1
- package/dist/cjs-types/server/impl/actions_impl.d.ts +3 -2
- package/dist/cjs-types/server/impl/actions_impl.d.ts.map +1 -1
- package/dist/cli.bundle.cjs +10059 -7094
- package/dist/cli.bundle.cjs.map +4 -4
- package/dist/esm/bundler/context.js +7 -5
- package/dist/esm/bundler/context.js.map +2 -2
- package/dist/esm/bundler/fs.js +47 -6
- package/dist/esm/bundler/fs.js.map +2 -2
- package/dist/esm/cli/account.js +221 -0
- package/dist/esm/cli/account.js.map +7 -0
- package/dist/esm/cli/configure.js +15 -2
- package/dist/esm/cli/configure.js.map +2 -2
- package/dist/esm/cli/lib/accountManagement.js +179 -0
- package/dist/esm/cli/lib/accountManagement.js.map +7 -0
- package/dist/esm/cli/lib/accounts.js +289 -0
- package/dist/esm/cli/lib/accounts.js.map +7 -0
- package/dist/esm/cli/lib/deployKeyWarning.js +27 -0
- package/dist/esm/cli/lib/deployKeyWarning.js.map +7 -0
- package/dist/esm/cli/lib/deployment.js +2 -2
- package/dist/esm/cli/lib/deployment.js.map +2 -2
- package/dist/esm/cli/lib/deploymentSelection.js +35 -20
- package/dist/esm/cli/lib/deploymentSelection.js.map +2 -2
- package/dist/esm/cli/lib/envvars.js +35 -1
- package/dist/esm/cli/lib/envvars.js.map +2 -2
- package/dist/esm/cli/lib/fsUtils.js +1 -1
- package/dist/esm/cli/lib/fsUtils.js.map +2 -2
- package/dist/esm/cli/lib/generateDocs.js +1 -1
- package/dist/esm/cli/lib/generateDocs.js.map +1 -1
- package/dist/esm/cli/lib/login.js +52 -4
- package/dist/esm/cli/lib/login.js.map +3 -3
- package/dist/esm/cli/lib/mcp/requestContext.js +5 -1
- package/dist/esm/cli/lib/mcp/requestContext.js.map +2 -2
- package/dist/esm/cli/lib/plugins/claudeCode.js +160 -0
- package/dist/esm/cli/lib/plugins/claudeCode.js.map +7 -0
- package/dist/esm/cli/lib/plugins/codex.js +140 -0
- package/dist/esm/cli/lib/plugins/codex.js.map +7 -0
- package/dist/esm/cli/lib/plugins/harness.js +17 -0
- package/dist/esm/cli/lib/plugins/harness.js.map +7 -0
- package/dist/esm/cli/lib/plugins/marketplaces.js +53 -0
- package/dist/esm/cli/lib/plugins/marketplaces.js.map +7 -0
- package/dist/esm/cli/lib/plugins/skills.js +65 -0
- package/dist/esm/cli/lib/plugins/skills.js.map +7 -0
- package/dist/esm/cli/lib/plugins/utils.js +86 -0
- package/dist/esm/cli/lib/plugins/utils.js.map +7 -0
- package/dist/esm/cli/lib/utils/utils.js +16 -9
- package/dist/esm/cli/lib/utils/utils.js.map +2 -2
- package/dist/esm/cli/login.js +225 -112
- package/dist/esm/cli/login.js.map +3 -3
- package/dist/esm/cli/logout.js +110 -13
- package/dist/esm/cli/logout.js.map +2 -2
- package/dist/esm/cli/mcp.js +34 -10
- package/dist/esm/cli/mcp.js.map +2 -2
- package/dist/esm/cli/plugins.js +99 -0
- package/dist/esm/cli/plugins.js.map +7 -0
- package/dist/esm/cli/program.js +3 -1
- package/dist/esm/cli/program.js.map +2 -2
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/server/impl/actions_impl.js.map +2 -2
- package/dist/esm-types/bundler/context.d.ts +5 -0
- package/dist/esm-types/bundler/context.d.ts.map +1 -1
- package/dist/esm-types/bundler/fs.d.ts +7 -2
- package/dist/esm-types/bundler/fs.d.ts.map +1 -1
- package/dist/esm-types/cli/account.d.ts +6 -0
- package/dist/esm-types/cli/account.d.ts.map +1 -0
- package/dist/esm-types/cli/configure.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/accountManagement.d.ts +10 -0
- package/dist/esm-types/cli/lib/accountManagement.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/accounts.d.ts +59 -0
- package/dist/esm-types/cli/lib/accounts.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/deployKeyWarning.d.ts +3 -0
- package/dist/esm-types/cli/lib/deployKeyWarning.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/deployment.d.ts +2 -0
- package/dist/esm-types/cli/lib/deployment.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/deploymentSelection.d.ts +2 -1
- package/dist/esm-types/cli/lib/deploymentSelection.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/envvars.d.ts +6 -0
- package/dist/esm-types/cli/lib/envvars.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/fsUtils.d.ts +1 -0
- package/dist/esm-types/cli/lib/fsUtils.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/login.d.ts +3 -1
- package/dist/esm-types/cli/lib/login.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/mcp/requestContext.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/mcp/tools/insights.d.ts +2 -2
- package/dist/esm-types/cli/lib/plugins/claudeCode.d.ts +25 -0
- package/dist/esm-types/cli/lib/plugins/claudeCode.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/plugins/codex.d.ts +25 -0
- package/dist/esm-types/cli/lib/plugins/codex.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/plugins/harness.d.ts +33 -0
- package/dist/esm-types/cli/lib/plugins/harness.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/plugins/marketplaces.d.ts +40 -0
- package/dist/esm-types/cli/lib/plugins/marketplaces.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/plugins/skills.d.ts +18 -0
- package/dist/esm-types/cli/lib/plugins/skills.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/plugins/utils.d.ts +21 -0
- package/dist/esm-types/cli/lib/plugins/utils.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/utils/utils.d.ts +5 -0
- package/dist/esm-types/cli/lib/utils/utils.d.ts.map +1 -1
- package/dist/esm-types/cli/login.d.ts +21 -0
- package/dist/esm-types/cli/login.d.ts.map +1 -1
- package/dist/esm-types/cli/logout.d.ts +8 -1
- package/dist/esm-types/cli/logout.d.ts.map +1 -1
- package/dist/esm-types/cli/mcp.d.ts.map +1 -1
- package/dist/esm-types/cli/plugins.d.ts +3 -0
- package/dist/esm-types/cli/plugins.d.ts.map +1 -0
- package/dist/esm-types/cli/program.d.ts.map +1 -1
- package/dist/esm-types/index.d.ts +1 -1
- package/dist/esm-types/index.d.ts.map +1 -1
- package/dist/esm-types/server/impl/actions_impl.d.ts +3 -2
- package/dist/esm-types/server/impl/actions_impl.d.ts.map +1 -1
- package/dist/react.bundle.js +1 -1
- package/dist/react.bundle.js.map +1 -1
- package/package.json +2 -2
- package/src/bundler/context.ts +9 -5
- package/src/bundler/fs.ts +54 -5
- package/src/cli/account.ts +320 -0
- package/src/cli/configure.ts +18 -2
- package/src/cli/lib/accountManagement.ts +262 -0
- package/src/cli/lib/accounts.ts +400 -0
- package/src/cli/lib/deployKeyWarning.ts +43 -0
- package/src/cli/lib/deployment.ts +2 -2
- package/src/cli/lib/deploymentSelection.ts +37 -18
- package/src/cli/lib/envvars.ts +43 -1
- package/src/cli/lib/fsUtils.ts +5 -2
- package/src/cli/lib/generateDocs.ts +1 -1
- package/src/cli/lib/login.ts +64 -3
- package/src/cli/lib/mcp/requestContext.ts +7 -1
- package/src/cli/lib/plugins/claudeCode.ts +201 -0
- package/src/cli/lib/plugins/codex.ts +177 -0
- package/src/cli/lib/plugins/harness.ts +49 -0
- package/src/cli/lib/plugins/marketplaces.ts +94 -0
- package/src/cli/lib/plugins/skills.ts +101 -0
- package/src/cli/lib/plugins/utils.ts +121 -0
- package/src/cli/lib/utils/utils.ts +19 -15
- package/src/cli/login.ts +293 -168
- package/src/cli/logout.ts +142 -17
- package/src/cli/mcp.ts +48 -11
- package/src/cli/plugins.ts +154 -0
- package/src/cli/program.ts +4 -0
- package/src/index.ts +1 -1
- package/src/server/impl/actions_impl.ts +3 -2
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/cli/lib/plugins/codex.ts"],
|
|
4
|
+
"sourcesContent": ["import os from \"os\";\nimport path from \"path\";\nimport { z } from \"zod\";\nimport { nodeFs } from \"../../../bundler/fs.js\";\nimport type { Cli, Places } from \"./harness.js\";\nimport {\n convexMarketplaces,\n type Marketplace,\n type Plugin,\n} from \"./marketplaces.js\";\nimport {\n fetchGitHubJson,\n onPath,\n parseList,\n subfolders,\n versionOf,\n} from \"./utils.js\";\n\n/** Builds `getCodexLocations` for the given places, so tests can point it at fixtures. */\nexport const createGetCodexLocations =\n (places: Places) => async (): Promise<Cli[]> => {\n // The ChatGPT app also has `codex-cli/bin/codex`, a script that runs this\n // binary. Running that script from another app sets off macOS's App\n // Management prompt, and running the binary doesn't.\n const desktop = path.join(\n places.applications,\n \"ChatGPT.app\",\n \"Contents\",\n \"Resources\",\n \"codex-cli\",\n \"CodexCLI.app\",\n \"Contents\",\n \"MacOS\",\n \"codex\",\n );\n const found: Omit<Cli, \"version\">[] = [\n ...onPath(\"codex\", places.path).map((p) => ({\n source: \"terminal\" as const,\n path: p,\n })),\n ...(nodeFs.exists(desktop)\n ? [{ source: \"desktop\" as const, path: desktop }]\n : []),\n // The extension keeps its binary in a folder named for the platform, like\n // `bin/macos-aarch64`.\n ...subfolders(path.join(places.home, \".vscode\", \"extensions\"))\n .filter((dir) => path.basename(dir).startsWith(\"openai.chatgpt-\"))\n .flatMap((dir) => subfolders(path.join(dir, \"bin\")))\n .map((dir) => ({\n source: \"vscode\" as const,\n path: path.join(dir, \"codex\"),\n })),\n ];\n return Promise.all(\n found.map(async (cli) => ({\n ...cli,\n version: await versionOf(cli.path),\n })),\n );\n };\n\n/** Every copy of Codex on this machine: the terminal CLI, the ChatGPT app's copy and the VS Code extension's copies. */\nexport const getCodexLocations = createGetCodexLocations({\n home: os.homedir(),\n path: process.env.PATH ?? \"\",\n applications: \"/Applications\",\n});\n\n/** The newest Convex plugin a Codex user can install, which is main of our repo. */\nasync function codexLatest(): Promise<Record<string, string>> {\n const plugin = await fetchGitHubJson<{ version: string }>(\n \"convex/convex-codex-plugin/main/plugins/convex/.codex-plugin/plugin.json\",\n );\n return plugin === null ? {} : { convex: plugin.version };\n}\n\n/** `codex plugin marketplace list --json` */\nconst codexMarketplaceList = z.object({\n marketplaces: z.array(\n z.object({\n name: z.string(),\n root: z.string(),\n marketplaceSource: z\n .object({ sourceType: z.string(), source: z.string() })\n .optional(),\n }),\n ),\n});\n\n/** `codex plugin list --json` */\nconst codexPluginList = z.object({\n installed: z.array(\n z.object({\n name: z.string(),\n marketplaceName: z.string(),\n version: z.string(),\n enabled: z.boolean(),\n }),\n ),\n});\n\n/** Reads the plugins in `codex plugin list --json`, or returns null when it doesn't match. */\nfunction codexPlugins(pluginList: string): Plugin[] | null {\n const plugins = parseList(\n codexPluginList,\n pluginList,\n \"codex plugin list --json\",\n );\n if (plugins === null) return null;\n return plugins.installed.map((p) => ({\n name: p.name,\n marketplace: p.marketplaceName,\n version: p.version,\n enabled: p.enabled,\n }));\n}\n\n/** Reads Codex's Convex marketplaces from `codex plugin marketplace list --json` and `codex plugin list --json`, or returns null when either doesn't match. */\nexport function codexMarketplaces(\n marketplaceList: string,\n pluginList: string,\n): Marketplace[] | null {\n const marketplaces = parseList(\n codexMarketplaceList,\n marketplaceList,\n \"codex plugin marketplace list --json\",\n );\n const plugins = codexPlugins(pluginList);\n if (marketplaces === null || plugins === null) return null;\n return convexMarketplaces(\n marketplaces.marketplaces.map((m) => ({\n name: m.name,\n // Anything that isn't a git marketplace is shown by its folder.\n source:\n m.marketplaceSource?.sourceType === \"git\"\n ? { kind: \"git\", url: m.marketplaceSource.source }\n : { kind: \"folder\", path: m.root },\n })),\n plugins,\n );\n}\n\nconst pluginId = \"convex@convex-codex-plugin\";\n/** The install step that brings an installed plugin to the latest version. When it fails, the user keeps an old version. */\nconst upgradeStep = [\"plugin\", \"marketplace\", \"upgrade\", \"convex-codex-plugin\"];\n\n/** Codex as `npx convex plugins` installs and reads it. */\nexport const codex = {\n id: \"codex\" as const,\n name: \"Codex\",\n plugin: pluginId,\n upgradeStep,\n installSteps: [\n // Notes:\n //\n // 1. The marketplace is added from the `get-convex` org, the org's name\n // before the rename to `convex`. Codex refuses to re-add a marketplace\n // from a different source, so switching would make install fail for\n // anyone who installed before. Switch once install handles an existing\n // marketplace.\n //\n // 2. Codex installs plugins from its own local copy of each marketplace, so\n // it doesn't see the new plugin versions we publish until that copy is\n // updated.\n\n // Add the marketplace\n [\"plugin\", \"marketplace\", \"add\", \"get-convex/convex-codex-plugin\"],\n // Update the local copy from GitHub, so the latest plugin version is\n // available to install - this is important\n upgradeStep,\n // Install the latest plugin from the updated marketplace\n [\"plugin\", \"add\", pluginId],\n ],\n plugins: codexPlugins,\n marketplaces: codexMarketplaces,\n latest: codexLatest,\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
import * as semver from "semver";
|
|
3
|
+
import { getClaudeCodeLocations } from "./claudeCode.js";
|
|
4
|
+
import { getCodexLocations } from "./codex.js";
|
|
5
|
+
function newest(clis) {
|
|
6
|
+
const version = (cli) => semver.coerce(cli.version, { includePrerelease: true });
|
|
7
|
+
return [...clis].sort((a, b) => semver.rcompare(version(a), version(b)))[0];
|
|
8
|
+
}
|
|
9
|
+
export const createGetNewestHarnessLocations = (getters) => async () => ({
|
|
10
|
+
codex: newest(await getters.getCodexLocations()),
|
|
11
|
+
claudeCode: newest(await getters.getClaudeCodeLocations())
|
|
12
|
+
});
|
|
13
|
+
export const getNewestHarnessLocations = createGetNewestHarnessLocations({
|
|
14
|
+
getCodexLocations,
|
|
15
|
+
getClaudeCodeLocations
|
|
16
|
+
});
|
|
17
|
+
//# sourceMappingURL=harness.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/cli/lib/plugins/harness.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * The Claude Code and Codex CLIs found on the user's machine. Users of the\n * desktop apps or the VS Code extensions often have no CLI on PATH, but each\n * app ships its own copy, which takes the same commands and shares the same\n * plugin state as the terminal CLI.\n */\nimport * as semver from \"semver\";\nimport { getClaudeCodeLocations } from \"./claudeCode.js\";\nimport { getCodexLocations } from \"./codex.js\";\n\n/** Where a copy of a harness CLI was found. */\ntype CliSource = \"terminal\" | \"desktop\" | \"vscode\";\n\n/** A copy of a harness CLI and the first line it prints for `--version`. */\nexport type Cli = { source: CliSource; path: string; version: string };\n\n/** Where to look for harness CLIs. */\nexport type Places = {\n home: string;\n /** Directories separated like `$PATH`. */\n path: string;\n /** Where macOS apps are installed, `/Applications`. */\n applications: string;\n};\n\n/** The copy with the highest version. Versions compare as semver, where a release beats its prereleases. */\nfunction newest(clis: Cli[]): Cli | undefined {\n // Every copy printed its version when the finder ran it.\n const version = (cli: Cli) =>\n semver.coerce(cli.version, { includePrerelease: true })!;\n return [...clis].sort((a, b) => semver.rcompare(version(a), version(b)))[0];\n}\n\n/** Builds `getNewestHarnessLocations` from the given location getters, so tests can pass fixed locations. */\nexport const createGetNewestHarnessLocations =\n (getters: {\n getCodexLocations: () => Promise<Cli[]>;\n getClaudeCodeLocations: () => Promise<Cli[]>;\n }) =>\n async () => ({\n codex: newest(await getters.getCodexLocations()),\n claudeCode: newest(await getters.getClaudeCodeLocations()),\n });\n\n/** The newest copy of each harness's CLI on this machine, or `undefined` for a harness that isn't installed. */\nexport const getNewestHarnessLocations = createGetNewestHarnessLocations({\n getCodexLocations,\n getClaudeCodeLocations,\n});\n"],
|
|
5
|
+
"mappings": ";AAMA,YAAY,YAAY;AACxB,SAAS,8BAA8B;AACvC,SAAS,yBAAyB;AAkBlC,SAAS,OAAO,MAA8B;AAE5C,QAAM,UAAU,CAAC,QACf,OAAO,OAAO,IAAI,SAAS,EAAE,mBAAmB,KAAK,CAAC;AACxD,SAAO,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,SAAS,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;AAC5E;AAGO,aAAM,kCACX,CAAC,YAID,aAAa;AAAA,EACX,OAAO,OAAO,MAAM,QAAQ,kBAAkB,CAAC;AAAA,EAC/C,YAAY,OAAO,MAAM,QAAQ,uBAAuB,CAAC;AAC3D;AAGK,aAAM,4BAA4B,gCAAgC;AAAA,EACvE;AAAA,EACA;AACF,CAAC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
import { logOutput } from "../../../bundler/log.js";
|
|
3
|
+
import { formatRows } from "./utils.js";
|
|
4
|
+
const pluginNames = ["convex", "convex-beta"];
|
|
5
|
+
export function convexMarketplaces(marketplaces, plugins) {
|
|
6
|
+
const convex = plugins.filter((p) => pluginNames.includes(p.name));
|
|
7
|
+
return marketplaces.map((m) => ({
|
|
8
|
+
...m,
|
|
9
|
+
plugins: convex.filter((p) => p.marketplace === m.name)
|
|
10
|
+
})).filter((m) => m.name.startsWith("convex") || m.plugins.length > 0);
|
|
11
|
+
}
|
|
12
|
+
function sourceText(source) {
|
|
13
|
+
switch (source.kind) {
|
|
14
|
+
case "github":
|
|
15
|
+
return `github.com/${source.repo}`;
|
|
16
|
+
case "git":
|
|
17
|
+
return source.url.replace(/^https?:\/\//, "").replace(/\.git$/, "");
|
|
18
|
+
case "folder":
|
|
19
|
+
return source.path;
|
|
20
|
+
case "other":
|
|
21
|
+
return source.type;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export function logMarketplaces(title, marketplaces, latest) {
|
|
25
|
+
logOutput(title);
|
|
26
|
+
if (marketplaces.length === 0) {
|
|
27
|
+
logOutput(" No Convex plugin installed");
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const marketplaceLines = formatRows(
|
|
31
|
+
marketplaces.map((m) => [m.name, sourceText(m.source)])
|
|
32
|
+
);
|
|
33
|
+
const pluginLines = formatRows(
|
|
34
|
+
marketplaces.flatMap((m) => m.plugins).map((p) => [
|
|
35
|
+
p.name,
|
|
36
|
+
p.version,
|
|
37
|
+
latest[p.name] === void 0 ? "" : `latest ${latest[p.name]}`,
|
|
38
|
+
p.scope ?? "-",
|
|
39
|
+
p.enabled ? "enabled" : "disabled",
|
|
40
|
+
p.cachedVersion === void 0 ? "" : `cached copy ${p.cachedVersion}`
|
|
41
|
+
]),
|
|
42
|
+
" "
|
|
43
|
+
);
|
|
44
|
+
let next = 0;
|
|
45
|
+
marketplaces.forEach((m, i) => {
|
|
46
|
+
logOutput(marketplaceLines[i]);
|
|
47
|
+
for (const line of pluginLines.slice(next, next + m.plugins.length)) {
|
|
48
|
+
logOutput(line);
|
|
49
|
+
}
|
|
50
|
+
next += m.plugins.length;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=marketplaces.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/cli/lib/plugins/marketplaces.ts"],
|
|
4
|
+
"sourcesContent": ["import { logOutput } from \"../../../bundler/log.js\";\nimport { formatRows } from \"./utils.js\";\n\n/** Names of the Convex plugins, including the old internal beta. */\nconst pluginNames = [\"convex\", \"convex-beta\"];\n\n/** A Convex plugin as its harness reports it. */\nexport type Plugin = {\n name: string;\n marketplace: string;\n /** The version that runs. */\n version: string;\n /** Claude Code only. */\n scope?: string;\n enabled: boolean;\n /** Claude Code folder installs only. The copy cached at install time, when it differs from the folder. */\n cachedVersion?: string | undefined;\n};\n\n/** Where a marketplace comes from. `other` is a source type we haven't seen, by its type name. */\nexport type Source =\n | { kind: \"github\"; repo: string }\n | { kind: \"git\"; url: string }\n | { kind: \"folder\"; path: string }\n | { kind: \"other\"; type: string };\n\n/** A marketplace named after Convex or holding a Convex plugin, with the Convex plugins installed from it. */\nexport type Marketplace = { name: string; source: Source; plugins: Plugin[] };\n\n/** Keeps the marketplaces named after Convex or holding a Convex plugin, each with its Convex plugins. */\nexport function convexMarketplaces(\n marketplaces: { name: string; source: Source }[],\n plugins: Plugin[],\n): Marketplace[] {\n const convex = plugins.filter((p) => pluginNames.includes(p.name));\n return marketplaces\n .map((m) => ({\n ...m,\n plugins: convex.filter((p) => p.marketplace === m.name),\n }))\n .filter((m) => m.name.startsWith(\"convex\") || m.plugins.length > 0);\n}\n\n/** Describes a marketplace's source for people. */\nfunction sourceText(source: Source): string {\n switch (source.kind) {\n case \"github\":\n return `github.com/${source.repo}`;\n case \"git\":\n return source.url.replace(/^https?:\\/\\//, \"\").replace(/\\.git$/, \"\");\n case \"folder\":\n return source.path;\n case \"other\":\n return source.type;\n }\n}\n\n/** Prints each Convex marketplace with its Convex plugins indented under it. */\nexport function logMarketplaces(\n title: string,\n marketplaces: Marketplace[],\n latest: Record<string, string>,\n) {\n logOutput(title);\n if (marketplaces.length === 0) {\n logOutput(\" No Convex plugin installed\");\n return;\n }\n const marketplaceLines = formatRows(\n marketplaces.map((m) => [m.name, sourceText(m.source)]),\n );\n // Plugin rows are formatted together so their columns line up across marketplaces.\n const pluginLines = formatRows(\n marketplaces\n .flatMap((m) => m.plugins)\n .map((p) => [\n p.name,\n p.version,\n latest[p.name] === undefined ? \"\" : `latest ${latest[p.name]}`,\n p.scope ?? \"-\",\n p.enabled ? \"enabled\" : \"disabled\",\n p.cachedVersion === undefined ? \"\" : `cached copy ${p.cachedVersion}`,\n ]),\n \" \",\n );\n let next = 0;\n marketplaces.forEach((m, i) => {\n logOutput(marketplaceLines[i]);\n for (const line of pluginLines.slice(next, next + m.plugins.length)) {\n logOutput(line);\n }\n next += m.plugins.length;\n });\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,iBAAiB;AAC1B,SAAS,kBAAkB;AAG3B,MAAM,cAAc,CAAC,UAAU,aAAa;AA0BrC,gBAAS,mBACd,cACA,SACe;AACf,QAAM,SAAS,QAAQ,OAAO,CAAC,MAAM,YAAY,SAAS,EAAE,IAAI,CAAC;AACjE,SAAO,aACJ,IAAI,CAAC,OAAO;AAAA,IACX,GAAG;AAAA,IACH,SAAS,OAAO,OAAO,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI;AAAA,EACxD,EAAE,EACD,OAAO,CAAC,MAAM,EAAE,KAAK,WAAW,QAAQ,KAAK,EAAE,QAAQ,SAAS,CAAC;AACtE;AAGA,SAAS,WAAW,QAAwB;AAC1C,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK;AACH,aAAO,cAAc,OAAO,IAAI;AAAA,IAClC,KAAK;AACH,aAAO,OAAO,IAAI,QAAQ,gBAAgB,EAAE,EAAE,QAAQ,UAAU,EAAE;AAAA,IACpE,KAAK;AACH,aAAO,OAAO;AAAA,IAChB,KAAK;AACH,aAAO,OAAO;AAAA,EAClB;AACF;AAGO,gBAAS,gBACd,OACA,cACA,QACA;AACA,YAAU,KAAK;AACf,MAAI,aAAa,WAAW,GAAG;AAC7B,cAAU,8BAA8B;AACxC;AAAA,EACF;AACA,QAAM,mBAAmB;AAAA,IACvB,aAAa,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,WAAW,EAAE,MAAM,CAAC,CAAC;AAAA,EACxD;AAEA,QAAM,cAAc;AAAA,IAClB,aACG,QAAQ,CAAC,MAAM,EAAE,OAAO,EACxB,IAAI,CAAC,MAAM;AAAA,MACV,EAAE;AAAA,MACF,EAAE;AAAA,MACF,OAAO,EAAE,IAAI,MAAM,SAAY,KAAK,UAAU,OAAO,EAAE,IAAI,CAAC;AAAA,MAC5D,EAAE,SAAS;AAAA,MACX,EAAE,UAAU,YAAY;AAAA,MACxB,EAAE,kBAAkB,SAAY,KAAK,eAAe,EAAE,aAAa;AAAA,IACrE,CAAC;AAAA,IACH;AAAA,EACF;AACA,MAAI,OAAO;AACX,eAAa,QAAQ,CAAC,GAAG,MAAM;AAC7B,cAAU,iBAAiB,CAAC,CAAC;AAC7B,eAAW,QAAQ,YAAY,MAAM,MAAM,OAAO,EAAE,QAAQ,MAAM,GAAG;AACnE,gBAAU,IAAI;AAAA,IAChB;AACA,YAAQ,EAAE,QAAQ;AAAA,EACpB,CAAC;AACH;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
import os from "os";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { nodeFs } from "../../../bundler/fs.js";
|
|
5
|
+
import { logOutput } from "../../../bundler/log.js";
|
|
6
|
+
import { fetchAgentSkillsCatalog } from "../versionApi.js";
|
|
7
|
+
function skillsFolders(dir, depth) {
|
|
8
|
+
let entries;
|
|
9
|
+
try {
|
|
10
|
+
entries = nodeFs.listDir(dir);
|
|
11
|
+
} catch {
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
14
|
+
return entries.filter((entry) => entry.isDirectory()).flatMap((entry) => {
|
|
15
|
+
const child = path.join(dir, entry.name);
|
|
16
|
+
if (entry.name === "skills") return [child];
|
|
17
|
+
return depth > 1 ? skillsFolders(child, depth - 1) : [];
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
export function convexSkillsFolders(root, names) {
|
|
21
|
+
return nodeFs.listDir(root).filter((entry) => entry.isDirectory() && entry.name.startsWith(".")).flatMap((entry) => skillsFolders(path.join(root, entry.name), 2)).map((folder) => {
|
|
22
|
+
const entries = nodeFs.listDir(folder).map((entry) => entry.name);
|
|
23
|
+
const current = entries.filter((name) => names.current.has(name));
|
|
24
|
+
const deleted = entries.filter((name) => names.deleted.has(name));
|
|
25
|
+
const brokenLinks = [...current, ...deleted].filter(
|
|
26
|
+
(name) => !nodeFs.exists(path.join(folder, name))
|
|
27
|
+
).length;
|
|
28
|
+
return {
|
|
29
|
+
path: folder,
|
|
30
|
+
current: current.length,
|
|
31
|
+
deleted: deleted.length,
|
|
32
|
+
brokenLinks
|
|
33
|
+
};
|
|
34
|
+
}).filter((folder) => folder.current + folder.deleted > 0);
|
|
35
|
+
}
|
|
36
|
+
function logSkills(title, root, label, names) {
|
|
37
|
+
const folders = convexSkillsFolders(root, names);
|
|
38
|
+
logOutput(title);
|
|
39
|
+
if (folders.length === 0) {
|
|
40
|
+
logOutput(" No Convex skills found");
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
for (const folder of folders) {
|
|
44
|
+
logOutput(
|
|
45
|
+
` ${folder.path.replace(root, label)} ${folder.current} Convex skills, ${folder.deleted} deleted, ${folder.brokenLinks} broken links`
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export async function logConvexSkills() {
|
|
50
|
+
const catalog = await fetchAgentSkillsCatalog();
|
|
51
|
+
if (catalog.kind === "error") {
|
|
52
|
+
logOutput("Skills: couldn't fetch the list of Convex skills");
|
|
53
|
+
} else {
|
|
54
|
+
const names = (kind) => new Set(
|
|
55
|
+
catalog.data.skills.filter((skill) => skill.status.kind === kind).map((skill) => skill.skillName)
|
|
56
|
+
);
|
|
57
|
+
const skillNames = {
|
|
58
|
+
current: names("active"),
|
|
59
|
+
deleted: names("deleted")
|
|
60
|
+
};
|
|
61
|
+
logSkills("Global skills", os.homedir(), "~", skillNames);
|
|
62
|
+
logSkills("Project skills", process.cwd(), ".", skillNames);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=skills.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/cli/lib/plugins/skills.ts"],
|
|
4
|
+
"sourcesContent": ["import os from \"os\";\nimport path from \"path\";\nimport { nodeFs } from \"../../../bundler/fs.js\";\nimport { logOutput } from \"../../../bundler/log.js\";\nimport { fetchAgentSkillsCatalog } from \"../versionApi.js\";\n\n/** Finds folders named `skills` in a folder's children and grandchildren, without following links. */\nfunction skillsFolders(dir: string, depth: number): string[] {\n let entries;\n try {\n entries = nodeFs.listDir(dir);\n } catch {\n return [];\n }\n return entries\n .filter((entry) => entry.isDirectory())\n .flatMap((entry) => {\n const child = path.join(dir, entry.name);\n if (entry.name === \"skills\") return [child];\n return depth > 1 ? skillsFolders(child, depth - 1) : [];\n });\n}\n\n/** Convex skill names from the catalog on version.convex.dev, split into current and deleted ones. */\ntype SkillNames = { current: Set<string>; deleted: Set<string> };\n\n/** A skills folder holding Convex skills. */\ntype SkillsFolder = {\n path: string;\n current: number;\n deleted: number;\n brokenLinks: number;\n};\n\n/** Finds the skills folders in a root's hidden folders that hold Convex skills, counting deleted skills and broken links. */\nexport function convexSkillsFolders(\n root: string,\n names: SkillNames,\n): SkillsFolder[] {\n return nodeFs\n .listDir(root)\n .filter((entry) => entry.isDirectory() && entry.name.startsWith(\".\"))\n .flatMap((entry) => skillsFolders(path.join(root, entry.name), 2))\n .map((folder) => {\n const entries = nodeFs.listDir(folder).map((entry) => entry.name);\n const current = entries.filter((name) => names.current.has(name));\n const deleted = entries.filter((name) => names.deleted.has(name));\n // exists follows links, so it's false for a link whose target is gone.\n const brokenLinks = [...current, ...deleted].filter(\n (name) => !nodeFs.exists(path.join(folder, name)),\n ).length;\n return {\n path: folder,\n current: current.length,\n deleted: deleted.length,\n brokenLinks,\n };\n })\n .filter((folder) => folder.current + folder.deleted > 0);\n}\n\n/** Prints each skills folder in a root's hidden folders that holds Convex skills, counting deleted skills and broken links. */\nfunction logSkills(\n title: string,\n root: string,\n label: string,\n names: SkillNames,\n) {\n const folders = convexSkillsFolders(root, names);\n logOutput(title);\n if (folders.length === 0) {\n logOutput(\" No Convex skills found\");\n return;\n }\n for (const folder of folders) {\n logOutput(\n ` ${folder.path.replace(root, label)} ${folder.current} Convex skills, ${folder.deleted} deleted, ${folder.brokenLinks} broken links`,\n );\n }\n}\n\n/** Prints the Convex skills in the hidden folders of the home folder and the current folder. */\nexport async function logConvexSkills() {\n const catalog = await fetchAgentSkillsCatalog();\n if (catalog.kind === \"error\") {\n logOutput(\"Skills: couldn't fetch the list of Convex skills\");\n } else {\n const names = (kind: \"active\" | \"deleted\") =>\n new Set(\n catalog.data.skills\n .filter((skill) => skill.status.kind === kind)\n .map((skill) => skill.skillName),\n );\n const skillNames = {\n current: names(\"active\"),\n deleted: names(\"deleted\"),\n };\n logSkills(\"Global skills\", os.homedir(), \"~\", skillNames);\n logSkills(\"Project skills\", process.cwd(), \".\", skillNames);\n }\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,cAAc;AACvB,SAAS,iBAAiB;AAC1B,SAAS,+BAA+B;AAGxC,SAAS,cAAc,KAAa,OAAyB;AAC3D,MAAI;AACJ,MAAI;AACF,cAAU,OAAO,QAAQ,GAAG;AAAA,EAC9B,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACA,SAAO,QACJ,OAAO,CAAC,UAAU,MAAM,YAAY,CAAC,EACrC,QAAQ,CAAC,UAAU;AAClB,UAAM,QAAQ,KAAK,KAAK,KAAK,MAAM,IAAI;AACvC,QAAI,MAAM,SAAS,SAAU,QAAO,CAAC,KAAK;AAC1C,WAAO,QAAQ,IAAI,cAAc,OAAO,QAAQ,CAAC,IAAI,CAAC;AAAA,EACxD,CAAC;AACL;AAcO,gBAAS,oBACd,MACA,OACgB;AAChB,SAAO,OACJ,QAAQ,IAAI,EACZ,OAAO,CAAC,UAAU,MAAM,YAAY,KAAK,MAAM,KAAK,WAAW,GAAG,CAAC,EACnE,QAAQ,CAAC,UAAU,cAAc,KAAK,KAAK,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,EAChE,IAAI,CAAC,WAAW;AACf,UAAM,UAAU,OAAO,QAAQ,MAAM,EAAE,IAAI,CAAC,UAAU,MAAM,IAAI;AAChE,UAAM,UAAU,QAAQ,OAAO,CAAC,SAAS,MAAM,QAAQ,IAAI,IAAI,CAAC;AAChE,UAAM,UAAU,QAAQ,OAAO,CAAC,SAAS,MAAM,QAAQ,IAAI,IAAI,CAAC;AAEhE,UAAM,cAAc,CAAC,GAAG,SAAS,GAAG,OAAO,EAAE;AAAA,MAC3C,CAAC,SAAS,CAAC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC;AAAA,IAClD,EAAE;AACF,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS,QAAQ;AAAA,MACjB,SAAS,QAAQ;AAAA,MACjB;AAAA,IACF;AAAA,EACF,CAAC,EACA,OAAO,CAAC,WAAW,OAAO,UAAU,OAAO,UAAU,CAAC;AAC3D;AAGA,SAAS,UACP,OACA,MACA,OACA,OACA;AACA,QAAM,UAAU,oBAAoB,MAAM,KAAK;AAC/C,YAAU,KAAK;AACf,MAAI,QAAQ,WAAW,GAAG;AACxB,cAAU,0BAA0B;AACpC;AAAA,EACF;AACA,aAAW,UAAU,SAAS;AAC5B;AAAA,MACE,KAAK,OAAO,KAAK,QAAQ,MAAM,KAAK,CAAC,KAAK,OAAO,OAAO,mBAAmB,OAAO,OAAO,aAAa,OAAO,WAAW;AAAA,IAC1H;AAAA,EACF;AACF;AAGA,sBAAsB,kBAAkB;AACtC,QAAM,UAAU,MAAM,wBAAwB;AAC9C,MAAI,QAAQ,SAAS,SAAS;AAC5B,cAAU,kDAAkD;AAAA,EAC9D,OAAO;AACL,UAAM,QAAQ,CAAC,SACb,IAAI;AAAA,MACF,QAAQ,KAAK,OACV,OAAO,CAAC,UAAU,MAAM,OAAO,SAAS,IAAI,EAC5C,IAAI,CAAC,UAAU,MAAM,SAAS;AAAA,IACnC;AACF,UAAM,aAAa;AAAA,MACjB,SAAS,MAAM,QAAQ;AAAA,MACvB,SAAS,MAAM,SAAS;AAAA,IAC1B;AACA,cAAU,iBAAiB,GAAG,QAAQ,GAAG,KAAK,UAAU;AACxD,cAAU,kBAAkB,QAAQ,IAAI,GAAG,KAAK,UAAU;AAAA,EAC5D;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
import child_process from "child_process";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { promisify } from "util";
|
|
5
|
+
import * as Sentry from "@sentry/node";
|
|
6
|
+
import { nodeFs } from "../../../bundler/fs.js";
|
|
7
|
+
export function onPath(name, pathDirs) {
|
|
8
|
+
const dir = pathDirs.split(path.delimiter).find((d) => nodeFs.exists(path.join(d, name)));
|
|
9
|
+
return dir === void 0 ? [] : [path.join(dir, name)];
|
|
10
|
+
}
|
|
11
|
+
export function subfolders(dir) {
|
|
12
|
+
let entries;
|
|
13
|
+
try {
|
|
14
|
+
entries = nodeFs.listDir(dir);
|
|
15
|
+
} catch {
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
return entries.filter((entry) => entry.isDirectory()).map((entry) => path.join(dir, entry.name)).sort();
|
|
19
|
+
}
|
|
20
|
+
export async function versionOf(cli) {
|
|
21
|
+
const { stdout } = await promisify(child_process.execFile)(cli, [
|
|
22
|
+
"--version"
|
|
23
|
+
]);
|
|
24
|
+
return stdout.split("\n")[0];
|
|
25
|
+
}
|
|
26
|
+
export function run(command, args) {
|
|
27
|
+
return new Promise((resolve) => {
|
|
28
|
+
let output = "";
|
|
29
|
+
const proc = child_process.spawn(command, args, {
|
|
30
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
31
|
+
});
|
|
32
|
+
proc.stdout.on("data", (chunk) => output += chunk);
|
|
33
|
+
proc.stderr.on("data", (chunk) => output += chunk);
|
|
34
|
+
proc.on("error", () => resolve({ ok: false, output }));
|
|
35
|
+
proc.on("close", (code) => resolve({ ok: code === 0, output }));
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
export function capture(command, args) {
|
|
39
|
+
return new Promise((resolve) => {
|
|
40
|
+
let stdout = "";
|
|
41
|
+
const proc = child_process.spawn(command, args, {
|
|
42
|
+
stdio: ["ignore", "pipe", "inherit"]
|
|
43
|
+
});
|
|
44
|
+
proc.stdout.on("data", (chunk) => stdout += chunk);
|
|
45
|
+
proc.on("error", () => resolve(null));
|
|
46
|
+
proc.on("close", () => resolve(stdout));
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
export async function fetchGitHubJson(path2) {
|
|
50
|
+
try {
|
|
51
|
+
const response = await fetch(`https://raw.githubusercontent.com/${path2}`);
|
|
52
|
+
if (!response.ok) {
|
|
53
|
+
Sentry.captureException(
|
|
54
|
+
new Error(`Failed to fetch ${path2}: status = ${response.status}`)
|
|
55
|
+
);
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
return await response.json();
|
|
59
|
+
} catch (error) {
|
|
60
|
+
Sentry.captureException(error);
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export function parseList(schema, list, command) {
|
|
65
|
+
let result;
|
|
66
|
+
try {
|
|
67
|
+
result = schema.safeParse(JSON.parse(list));
|
|
68
|
+
} catch {
|
|
69
|
+
result = void 0;
|
|
70
|
+
}
|
|
71
|
+
if (!result?.success) {
|
|
72
|
+
Sentry.captureMessage(`Unexpected output from \`${command}\``, "error");
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
return result.data;
|
|
76
|
+
}
|
|
77
|
+
export function formatRows(rows, indent = " ") {
|
|
78
|
+
if (rows.length === 0) return [];
|
|
79
|
+
const widths = rows[0].map(
|
|
80
|
+
(_, i) => Math.max(...rows.map((row) => row[i].length))
|
|
81
|
+
);
|
|
82
|
+
return rows.map(
|
|
83
|
+
(row) => `${indent}${row.map((cell, i) => cell.padEnd(widths[i])).join(" ")}`.trimEnd()
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/cli/lib/plugins/utils.ts"],
|
|
4
|
+
"sourcesContent": ["import child_process from \"child_process\";\nimport path from \"path\";\nimport { promisify } from \"util\";\nimport * as Sentry from \"@sentry/node\";\nimport { z } from \"zod\";\nimport { nodeFs } from \"../../../bundler/fs.js\";\n\n/** The file the shell runs for `name`, like `which`. */\nexport function onPath(name: string, pathDirs: string): string[] {\n const dir = pathDirs\n .split(path.delimiter)\n .find((d) => nodeFs.exists(path.join(d, name)));\n return dir === undefined ? [] : [path.join(dir, name)];\n}\n\n/** The folders directly inside `dir`, sorted by name, or none when `dir` doesn't exist. */\nexport function subfolders(dir: string): string[] {\n let entries;\n try {\n entries = nodeFs.listDir(dir);\n } catch {\n return [];\n }\n return entries\n .filter((entry) => entry.isDirectory())\n .map((entry) => path.join(dir, entry.name))\n .sort();\n}\n\n/** The first line a CLI prints for `--version`. */\nexport async function versionOf(cli: string): Promise<string> {\n const { stdout } = await promisify(child_process.execFile)(cli, [\n \"--version\",\n ]);\n return stdout.split(\"\\n\")[0];\n}\n\n/** Runs a command and resolves to whether it succeeded and everything it printed. */\nexport function run(\n command: string,\n args: string[],\n): Promise<{ ok: boolean; output: string }> {\n return new Promise((resolve) => {\n let output = \"\";\n\n const proc = child_process.spawn(command, args, {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n\n proc.stdout.on(\"data\", (chunk) => (output += chunk));\n proc.stderr.on(\"data\", (chunk) => (output += chunk));\n proc.on(\"error\", () => resolve({ ok: false, output }));\n proc.on(\"close\", (code) => resolve({ ok: code === 0, output }));\n });\n}\n\n/** Runs a command and resolves to its stdout, or null when it can't be started. */\nexport function capture(\n command: string,\n args: string[],\n): Promise<string | null> {\n return new Promise((resolve) => {\n let stdout = \"\";\n\n const proc = child_process.spawn(command, args, {\n stdio: [\"ignore\", \"pipe\", \"inherit\"],\n });\n\n proc.stdout.on(\"data\", (chunk) => (stdout += chunk));\n proc.on(\"error\", () => resolve(null));\n proc.on(\"close\", () => resolve(stdout));\n });\n}\n\n/** Fetches a JSON file from GitHub, or resolves to null when it can't, reporting why to Sentry. */\nexport async function fetchGitHubJson<T>(path: string): Promise<T | null> {\n try {\n const response = await fetch(`https://raw.githubusercontent.com/${path}`);\n if (!response.ok) {\n Sentry.captureException(\n new Error(`Failed to fetch ${path}: status = ${response.status}`),\n );\n return null;\n }\n return (await response.json()) as T;\n } catch (error) {\n Sentry.captureException(error);\n return null;\n }\n}\n\n/** Parses a JSON list from a harness CLI, or returns null and reports to Sentry when it isn't JSON or doesn't match. */\nexport function parseList<T>(\n schema: z.ZodType<T, z.ZodTypeDef, unknown>,\n list: string,\n command: string,\n): T | null {\n let result;\n try {\n result = schema.safeParse(JSON.parse(list));\n } catch {\n // A failing CLI can print nothing, which isn't JSON.\n result = undefined;\n }\n if (!result?.success) {\n Sentry.captureMessage(`Unexpected output from \\`${command}\\``, \"error\");\n return null;\n }\n return result.data;\n}\n\n/** Pads each column to its widest cell and indents every row. */\nexport function formatRows(rows: string[][], indent = \" \"): string[] {\n if (rows.length === 0) return [];\n const widths = rows[0].map((_, i) =>\n Math.max(...rows.map((row) => row[i].length)),\n );\n return rows.map((row) =>\n `${indent}${row.map((cell, i) => cell.padEnd(widths[i])).join(\" \")}`.trimEnd(),\n );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["path"]
|
|
7
|
+
}
|
|
@@ -32,13 +32,14 @@ export const CONVEX_DEPLOYMENT_TOKEN_ENV_VAR_NAME = "CONVEX_DEPLOYMENT_TOKEN";
|
|
|
32
32
|
export const CONVEX_DEPLOYMENT_ENV_VAR_NAME = "CONVEX_DEPLOYMENT";
|
|
33
33
|
export const CONVEX_SELF_HOSTED_URL_VAR_NAME = "CONVEX_SELF_HOSTED_URL";
|
|
34
34
|
export const CONVEX_SELF_HOSTED_ADMIN_KEY_VAR_NAME = "CONVEX_SELF_HOSTED_ADMIN_KEY";
|
|
35
|
+
export const IGNORED_DEPLOY_KEY = "<ignore_deploy_key>";
|
|
35
36
|
const MAX_RETRIES = 6;
|
|
36
37
|
const RETRY_LOG_THRESHOLD = 3;
|
|
37
38
|
export async function processDeployKeyValue(ctx, deployKey) {
|
|
38
39
|
if (deployKey === void 0) {
|
|
39
40
|
return void 0;
|
|
40
41
|
}
|
|
41
|
-
if (deployKey ===
|
|
42
|
+
if (deployKey === IGNORED_DEPLOY_KEY) {
|
|
42
43
|
return void 0;
|
|
43
44
|
}
|
|
44
45
|
const missingKeyPattern = /^<missing_deploy_key:(.+)>$/;
|
|
@@ -54,17 +55,23 @@ export async function processDeployKeyValue(ctx, deployKey) {
|
|
|
54
55
|
return deployKey;
|
|
55
56
|
}
|
|
56
57
|
export function readDeployKeyFromEnv(getEnv) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
return readDeployKeyEnvVar(getEnv)?.value;
|
|
59
|
+
}
|
|
60
|
+
export function readDeployKeyEnvVar(getEnv) {
|
|
61
|
+
for (const name of [
|
|
62
|
+
CONVEX_DEPLOY_KEY_ENV_VAR_NAME,
|
|
63
|
+
CONVEX_DEPLOYMENT_TOKEN_ENV_VAR_NAME
|
|
64
|
+
]) {
|
|
65
|
+
const value = getEnv(name);
|
|
66
|
+
if (value) return { name, value };
|
|
67
|
+
}
|
|
68
|
+
return void 0;
|
|
60
69
|
}
|
|
61
70
|
const PERMISSION_DENIED_MESSAGE_PREFIX = "You do not have permission to perform this operation";
|
|
62
71
|
function deployKeyPermissionAdvice() {
|
|
63
|
-
const
|
|
64
|
-
if (
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
return `This is determined by the permissions granted to ${envVarName}.`;
|
|
72
|
+
const envVar = readDeployKeyEnvVar((name) => process.env[name]);
|
|
73
|
+
if (envVar === void 0 || envVar.value === IGNORED_DEPLOY_KEY) return null;
|
|
74
|
+
return `This is determined by the permissions granted to ${envVar.name}.`;
|
|
68
75
|
}
|
|
69
76
|
export function permissionDeniedErrorMessage(errorMessage) {
|
|
70
77
|
const index = errorMessage.indexOf(PERMISSION_DENIED_MESSAGE_PREFIX);
|