convex 1.31.4 → 1.31.6-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 +5 -0
- package/dist/browser.bundle.js +1 -1
- package/dist/browser.bundle.js.map +1 -1
- package/dist/cjs/bundler/debugBundle.js +1 -1
- package/dist/cjs/bundler/debugBundle.js.map +1 -1
- package/dist/cjs/bundler/index.js +1 -1
- package/dist/cjs/bundler/index.js.map +1 -1
- package/dist/cjs/cli/configure.js +2 -10
- package/dist/cjs/cli/configure.js.map +2 -2
- package/dist/cjs/cli/deploy.js +16 -2
- package/dist/cjs/cli/deploy.js.map +2 -2
- package/dist/cjs/cli/dev.js +4 -1
- package/dist/cjs/cli/dev.js.map +2 -2
- package/dist/cjs/cli/generatedApi.js.map +1 -1
- package/dist/cjs/cli/integration.js +198 -10
- package/dist/cjs/cli/integration.js.map +2 -2
- package/dist/cjs/cli/lib/command.js +9 -4
- package/dist/cjs/cli/lib/command.js.map +2 -2
- package/dist/cjs/cli/lib/components/definition/bundle.js +1 -1
- package/dist/cjs/cli/lib/components/definition/bundle.js.map +1 -1
- package/dist/cjs/cli/lib/components.js +2 -1
- package/dist/cjs/cli/lib/components.js.map +2 -2
- package/dist/cjs/cli/lib/config.js +87 -212
- package/dist/cjs/cli/lib/config.js.map +3 -3
- package/dist/cjs/cli/lib/deploy2.js +27 -4
- package/dist/cjs/cli/lib/deploy2.js.map +2 -2
- package/dist/cjs/cli/lib/deploymentSelection.js +0 -12
- package/dist/cjs/cli/lib/deploymentSelection.js.map +2 -2
- package/dist/cjs/cli/lib/dev.js +30 -0
- package/dist/cjs/cli/lib/dev.js.map +2 -2
- package/dist/cjs/cli/lib/mcp/tools/index.js.map +2 -2
- package/dist/cjs/cli/lib/utils/prompts.js +1 -1
- package/dist/cjs/cli/lib/utils/prompts.js.map +2 -2
- package/dist/cjs/cli/lib/workos/environmentApi.js +27 -1
- package/dist/cjs/cli/lib/workos/environmentApi.js.map +2 -2
- package/dist/cjs/cli/lib/workos/platformApi.js +41 -7
- package/dist/cjs/cli/lib/workos/platformApi.js.map +2 -2
- package/dist/cjs/cli/lib/workos/workos.js +532 -93
- package/dist/cjs/cli/lib/workos/workos.js.map +2 -2
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs-types/bundler/debugBundle.d.ts.map +1 -1
- package/dist/cjs-types/bundler/index.d.ts.map +1 -1
- package/dist/cjs-types/cli/configure.d.ts.map +1 -1
- package/dist/cjs-types/cli/deploy.d.ts.map +1 -1
- package/dist/cjs-types/cli/dev.d.ts.map +1 -1
- package/dist/cjs-types/cli/generatedApi.d.ts +260 -1
- package/dist/cjs-types/cli/generatedApi.d.ts.map +1 -1
- package/dist/cjs-types/cli/integration.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/command.d.ts +7 -1
- package/dist/cjs-types/cli/lib/command.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/components/definition/bundle.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/components.d.ts +2 -0
- package/dist/cjs-types/cli/lib/components.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/config.d.ts +38 -26
- package/dist/cjs-types/cli/lib/config.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/deploy2.d.ts +5 -0
- package/dist/cjs-types/cli/lib/deploy2.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/deployment.d.ts +1 -1
- package/dist/cjs-types/cli/lib/deploymentSelection.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/dev.d.ts +2 -0
- package/dist/cjs-types/cli/lib/dev.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/mcp/tools/index.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/utils/prompts.d.ts +1 -0
- package/dist/cjs-types/cli/lib/utils/prompts.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/workos/environmentApi.d.ts +4 -0
- package/dist/cjs-types/cli/lib/workos/environmentApi.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/workos/platformApi.d.ts +9 -1
- package/dist/cjs-types/cli/lib/workos/platformApi.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/workos/workos.d.ts +39 -8
- package/dist/cjs-types/cli/lib/workos/workos.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/workos/workos.test.d.ts +2 -0
- package/dist/cjs-types/cli/lib/workos/workos.test.d.ts.map +1 -0
- package/dist/cjs-types/cli/network_test.d.ts +1 -0
- package/dist/cjs-types/cli/network_test.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/cli.bundle.cjs +3337 -5468
- package/dist/cli.bundle.cjs.map +4 -4
- package/dist/esm/bundler/debugBundle.js +1 -1
- package/dist/esm/bundler/debugBundle.js.map +1 -1
- package/dist/esm/bundler/index.js +1 -1
- package/dist/esm/bundler/index.js.map +1 -1
- package/dist/esm/cli/configure.js +3 -16
- package/dist/esm/cli/configure.js.map +2 -2
- package/dist/esm/cli/deploy.js +16 -2
- package/dist/esm/cli/deploy.js.map +2 -2
- package/dist/esm/cli/dev.js +4 -1
- package/dist/esm/cli/dev.js.map +2 -2
- package/dist/esm/cli/integration.js +209 -12
- package/dist/esm/cli/integration.js.map +2 -2
- package/dist/esm/cli/lib/command.js +9 -4
- package/dist/esm/cli/lib/command.js.map +2 -2
- package/dist/esm/cli/lib/components/definition/bundle.js +1 -1
- package/dist/esm/cli/lib/components/definition/bundle.js.map +1 -1
- package/dist/esm/cli/lib/components.js +2 -1
- package/dist/esm/cli/lib/components.js.map +2 -2
- package/dist/esm/cli/lib/config.js +86 -210
- package/dist/esm/cli/lib/config.js.map +3 -3
- package/dist/esm/cli/lib/deploy2.js +32 -5
- package/dist/esm/cli/lib/deploy2.js.map +2 -2
- package/dist/esm/cli/lib/deploymentSelection.js +0 -12
- package/dist/esm/cli/lib/deploymentSelection.js.map +2 -2
- package/dist/esm/cli/lib/dev.js +33 -0
- package/dist/esm/cli/lib/dev.js.map +2 -2
- package/dist/esm/cli/lib/mcp/tools/index.js.map +2 -2
- package/dist/esm/cli/lib/utils/prompts.js +1 -1
- package/dist/esm/cli/lib/utils/prompts.js.map +2 -2
- package/dist/esm/cli/lib/workos/environmentApi.js +25 -0
- package/dist/esm/cli/lib/workos/environmentApi.js.map +2 -2
- package/dist/esm/cli/lib/workos/platformApi.js +36 -6
- package/dist/esm/cli/lib/workos/platformApi.js.map +2 -2
- package/dist/esm/cli/lib/workos/workos.js +535 -94
- package/dist/esm/cli/lib/workos/workos.js.map +2 -2
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm-types/bundler/debugBundle.d.ts.map +1 -1
- package/dist/esm-types/bundler/index.d.ts.map +1 -1
- package/dist/esm-types/cli/configure.d.ts.map +1 -1
- package/dist/esm-types/cli/deploy.d.ts.map +1 -1
- package/dist/esm-types/cli/dev.d.ts.map +1 -1
- package/dist/esm-types/cli/generatedApi.d.ts +260 -1
- package/dist/esm-types/cli/generatedApi.d.ts.map +1 -1
- package/dist/esm-types/cli/integration.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/command.d.ts +7 -1
- package/dist/esm-types/cli/lib/command.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/components/definition/bundle.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/components.d.ts +2 -0
- package/dist/esm-types/cli/lib/components.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/config.d.ts +38 -26
- package/dist/esm-types/cli/lib/config.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/deploy2.d.ts +5 -0
- package/dist/esm-types/cli/lib/deploy2.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/deployment.d.ts +1 -1
- package/dist/esm-types/cli/lib/deploymentSelection.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/dev.d.ts +2 -0
- package/dist/esm-types/cli/lib/dev.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/mcp/tools/index.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/utils/prompts.d.ts +1 -0
- package/dist/esm-types/cli/lib/utils/prompts.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/workos/environmentApi.d.ts +4 -0
- package/dist/esm-types/cli/lib/workos/environmentApi.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/workos/platformApi.d.ts +9 -1
- package/dist/esm-types/cli/lib/workos/platformApi.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/workos/workos.d.ts +39 -8
- package/dist/esm-types/cli/lib/workos/workos.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/workos/workos.test.d.ts +2 -0
- package/dist/esm-types/cli/lib/workos/workos.test.d.ts.map +1 -0
- package/dist/esm-types/cli/network_test.d.ts +1 -0
- package/dist/esm-types/cli/network_test.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/react.bundle.js +1 -1
- package/dist/react.bundle.js.map +1 -1
- package/package.json +5 -5
- package/schemas/convex.schema.json +2 -1
- package/src/bundler/debugBundle.ts +1 -1
- package/src/bundler/index.ts +1 -1
- package/src/cli/configure.ts +3 -18
- package/src/cli/deploy.ts +23 -1
- package/src/cli/dev.ts +6 -0
- package/src/cli/generatedApi.ts +260 -1
- package/src/cli/integration.ts +289 -15
- package/src/cli/lib/command.ts +19 -6
- package/src/cli/lib/components/definition/bundle.ts +1 -1
- package/src/cli/lib/components.ts +7 -1
- package/src/cli/lib/config.test.ts +444 -547
- package/src/cli/lib/config.ts +166 -309
- package/src/cli/lib/deploy2.ts +47 -4
- package/src/cli/lib/deploymentSelection.ts +0 -14
- package/src/cli/lib/dev.ts +58 -0
- package/src/cli/lib/mcp/tools/index.ts +1 -2
- package/src/cli/lib/utils/prompts.ts +4 -1
- package/src/cli/lib/workos/environmentApi.ts +38 -0
- package/src/cli/lib/workos/platformApi.ts +69 -6
- package/src/cli/lib/workos/workos.test.ts +242 -0
- package/src/cli/lib/workos/workos.ts +807 -134
- package/src/cli/network_test.ts +1 -1
- package/src/index.ts +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/cli/lib/deploymentSelection.ts"],
|
|
4
|
-
"sourcesContent": ["import { BigBrainAuth, Context } from \"../../bundler/context.js\";\nimport { logVerbose } from \"../../bundler/log.js\";\nimport {\n AccountRequiredDeploymentType,\n DeploymentType,\n fetchTeamAndProjectForKey,\n} from \"./api.js\";\nimport { readProjectConfig } from \"./config.js\";\nimport {\n deploymentNameFromAdminKeyOrCrash,\n deploymentTypeFromAdminKey,\n getDeploymentTypeFromConfiguredDeployment,\n isAnonymousDeployment,\n isDeploymentKey,\n isPreviewDeployKey,\n isProjectKey,\n stripDeploymentTypePrefix,\n} from \"./deployment.js\";\nimport { getBuildEnvironment } from \"./envvars.js\";\nimport { readGlobalConfig } from \"./utils/globalConfig.js\";\nimport {\n CONVEX_DEPLOYMENT_ENV_VAR_NAME,\n CONVEX_DEPLOY_KEY_ENV_VAR_NAME,\n CONVEX_SELF_HOSTED_ADMIN_KEY_VAR_NAME,\n CONVEX_SELF_HOSTED_URL_VAR_NAME,\n ENV_VAR_FILE_PATH,\n bigBrainAPI,\n processDeployKeyValue,\n} from \"./utils/utils.js\";\nimport * as dotenv from \"dotenv\";\n\n// ----------------------------------------------------------------------------\n// Big Brain Auth\n// ----------------------------------------------------------------------------\n\n/**\n * The auth header can be a few different things:\n * * An access token (corresponds to device authorization, usually stored in `~/.convex/config.json`)\n * * A preview deploy key (set via the `CONVEX_DEPLOY_KEY` environment variable)\n * * A project key (set via the `CONVEX_DEPLOY_KEY` environment variable)\n * * A deployment key if a deployment key (set via `CONVEX_DEPLOY_KEY` environment variable)\n *\n * Project keys take precedence over the the access token.\n * Deployment keys take precedence over the the access token.\n * This makes using one of these keys while logged in or logged out work the same.\n *\n * We check for the `CONVEX_DEPLOY_KEY` in the `--env-file` if it's provided.\n * Otherwise, we check in the `.env` and `.env.local` files.\n *\n * If we later prompt for log in, we need to call `ctx.setBigBrainAuthHeader` to\n * update the value.\n *\n * @param ctx\n * @param envFile\n * @returns\n */\nexport async function initializeBigBrainAuth(\n ctx: Context,\n initialArgs: {\n url?: string | undefined;\n adminKey?: string | undefined;\n envFile?: string | undefined;\n },\n): Promise<void> {\n if (initialArgs.url !== undefined && initialArgs.adminKey !== undefined) {\n // Do not check any env vars if `url` and `adminKey` are specified via CLI\n ctx._updateBigBrainAuth(\n getBigBrainAuth(ctx, {\n previewDeployKey: null,\n projectKey: null,\n deploymentKey: null,\n }),\n );\n return;\n }\n if (initialArgs.envFile !== undefined) {\n const existingFile = ctx.fs.exists(initialArgs.envFile)\n ? ctx.fs.readUtf8File(initialArgs.envFile)\n : null;\n if (existingFile === null) {\n return ctx.crash({\n exitCode: 1,\n errorType: \"invalid filesystem or env vars\",\n printedMessage: \"env file does not exist\",\n });\n }\n const config = dotenv.parse(existingFile);\n const rawDeployKey = config[CONVEX_DEPLOY_KEY_ENV_VAR_NAME];\n const deployKey = await processDeployKeyValue(ctx, rawDeployKey);\n if (deployKey !== undefined) {\n const bigBrainAuth = getBigBrainAuth(ctx, {\n previewDeployKey: isPreviewDeployKey(deployKey) ? deployKey : null,\n projectKey: isProjectKey(deployKey) ? deployKey : null,\n deploymentKey: isDeploymentKey(deployKey) ? deployKey : null,\n });\n ctx._updateBigBrainAuth(bigBrainAuth);\n }\n return;\n }\n dotenv.config({ path: ENV_VAR_FILE_PATH });\n dotenv.config();\n const rawDeployKey = process.env[CONVEX_DEPLOY_KEY_ENV_VAR_NAME];\n const deployKey = await processDeployKeyValue(ctx, rawDeployKey);\n if (deployKey !== undefined) {\n const bigBrainAuth = getBigBrainAuth(ctx, {\n previewDeployKey: isPreviewDeployKey(deployKey) ? deployKey : null,\n projectKey: isProjectKey(deployKey) ? deployKey : null,\n deploymentKey: isDeploymentKey(deployKey) ? deployKey : null,\n });\n ctx._updateBigBrainAuth(bigBrainAuth);\n return;\n }\n ctx._updateBigBrainAuth(\n getBigBrainAuth(ctx, {\n previewDeployKey: null,\n projectKey: null,\n deploymentKey: null,\n }),\n );\n return;\n}\n\nexport async function updateBigBrainAuthAfterLogin(\n ctx: Context,\n accessToken: string,\n) {\n const existingAuth = ctx.bigBrainAuth();\n if (existingAuth !== null && existingAuth.kind === \"projectKey\") {\n logVerbose(\n `Ignoring update to big brain auth since project key takes precedence`,\n );\n return;\n }\n ctx._updateBigBrainAuth({\n accessToken: accessToken,\n kind: \"accessToken\",\n header: `Bearer ${accessToken}`,\n });\n}\n\nexport async function clearBigBrainAuth(ctx: Context) {\n ctx._updateBigBrainAuth(null);\n}\n\nfunction getBigBrainAuth(\n ctx: Context,\n opts: {\n previewDeployKey: string | null;\n projectKey: string | null;\n deploymentKey: string | null;\n },\n): BigBrainAuth | null {\n if (process.env.CONVEX_OVERRIDE_ACCESS_TOKEN) {\n return {\n accessToken: process.env.CONVEX_OVERRIDE_ACCESS_TOKEN,\n kind: \"accessToken\",\n header: `Bearer ${process.env.CONVEX_OVERRIDE_ACCESS_TOKEN}`,\n };\n }\n if (opts.projectKey !== null) {\n // Project keys take precedence over global config.\n return {\n header: `Bearer ${opts.projectKey}`,\n kind: \"projectKey\",\n projectKey: opts.projectKey,\n };\n }\n if (opts.deploymentKey !== null) {\n // Deployment keys take precedence over global config.\n return {\n header: `Bearer ${opts.deploymentKey}`,\n kind: \"deploymentKey\",\n deploymentKey: opts.deploymentKey,\n };\n }\n const globalConfig = readGlobalConfig(ctx);\n if (globalConfig) {\n return {\n kind: \"accessToken\",\n header: `Bearer ${globalConfig.accessToken}`,\n accessToken: globalConfig.accessToken,\n };\n }\n if (opts.previewDeployKey !== null) {\n return {\n header: `Bearer ${opts.previewDeployKey}`,\n kind: \"previewDeployKey\",\n previewDeployKey: opts.previewDeployKey,\n };\n }\n return null;\n}\n\n// ----------------------------------------------------------------------------\n// Deployment Selection\n// ----------------------------------------------------------------------------\n/**\n * Our CLI has logic to select which deployment to act on.\n *\n * We first check whether we're targeting a deployment within a project, or if we\n * know exactly which deployment to act on (e.g. in the case of self-hosting).\n *\n * We also special case preview deploys since the presence of a preview deploy key\n * triggers different behavior in `npx convex deploy`.\n *\n * Most commands will immediately compute the deployment selection, and then combine\n * that with any relevant CLI flags to figure out which deployment to talk to.\n *\n * Different commands do different things (e.g. `dev` will allow you to create a new project,\n * `deploy` has different behavior for preview deploys)\n *\n * This should be kept in sync with `initializeBigBrainAuth` since environment variables\n * like `CONVEX_DEPLOY_KEY` are used for both deployment selection and auth.\n */\nexport type DeploymentSelection =\n | {\n kind: \"existingDeployment\";\n deploymentToActOn: {\n url: string;\n adminKey: string;\n deploymentFields: {\n deploymentName: string;\n deploymentType: DeploymentType;\n projectSlug: string;\n teamSlug: string;\n } | null;\n source: \"selfHosted\" | \"deployKey\" | \"cliArgs\";\n };\n }\n | {\n kind: \"deploymentWithinProject\";\n targetProject: ProjectSelection;\n }\n | {\n kind: \"preview\";\n previewDeployKey: string;\n }\n | {\n kind: \"chooseProject\";\n }\n | {\n kind: \"anonymous\";\n deploymentName: string | null;\n };\n\nexport type ProjectSelection =\n | {\n kind: \"teamAndProjectSlugs\";\n teamSlug: string;\n projectSlug: string;\n }\n | {\n kind: \"deploymentName\";\n deploymentName: string;\n deploymentType: AccountRequiredDeploymentType | null;\n }\n | {\n kind: \"projectDeployKey\";\n projectDeployKey: string;\n };\n\nexport async function getDeploymentSelection(\n ctx: Context,\n cliArgs: {\n url?: string | undefined;\n adminKey?: string | undefined;\n envFile?: string | undefined;\n },\n): Promise<DeploymentSelection> {\n const metadata = await _getDeploymentSelection(ctx, cliArgs);\n logDeploymentSelection(ctx, metadata);\n return metadata;\n}\n\nfunction logDeploymentSelection(_ctx: Context, selection: DeploymentSelection) {\n switch (selection.kind) {\n case \"existingDeployment\": {\n logVerbose(\n `Existing deployment: ${selection.deploymentToActOn.url} ${selection.deploymentToActOn.source}`,\n );\n break;\n }\n case \"deploymentWithinProject\": {\n logVerbose(\n `Deployment within project: ${prettyProjectSelection(selection.targetProject)}`,\n );\n break;\n }\n case \"preview\": {\n logVerbose(`Preview deploy key`);\n break;\n }\n case \"chooseProject\": {\n logVerbose(`Choose project`);\n break;\n }\n case \"anonymous\": {\n logVerbose(\n `Anonymous, has selected deployment?: ${selection.deploymentName !== null}`,\n );\n break;\n }\n default: {\n selection satisfies never;\n logVerbose(`Unknown deployment selection`);\n }\n }\n return null;\n}\n\nfunction prettyProjectSelection(selection: ProjectSelection) {\n switch (selection.kind) {\n case \"teamAndProjectSlugs\": {\n return `Team and project slugs: ${selection.teamSlug} ${selection.projectSlug}`;\n }\n case \"deploymentName\": {\n return `Deployment name: ${selection.deploymentName}`;\n }\n case \"projectDeployKey\": {\n return `Project deploy key`;\n }\n default: {\n selection satisfies never;\n return `Unknown`;\n }\n }\n}\n\nasync function _getDeploymentSelection(\n ctx: Context,\n cliArgs: {\n url?: string | undefined;\n adminKey?: string | undefined;\n envFile?: string | undefined;\n },\n): Promise<DeploymentSelection> {\n /*\n - url + adminKey specified via CLI\n - Do not check any env vars (including ones relevant for auth)\n */\n if (cliArgs.url !== undefined && cliArgs.adminKey !== undefined) {\n return {\n kind: \"existingDeployment\",\n deploymentToActOn: {\n url: cliArgs.url,\n adminKey: cliArgs.adminKey,\n deploymentFields: null,\n source: \"cliArgs\",\n },\n };\n }\n\n if (cliArgs.envFile !== undefined) {\n // If an `--env-file` is specified, it must contain enough information for both auth and deployment selection.\n logVerbose(`Checking env file: ${cliArgs.envFile}`);\n const existingFile = ctx.fs.exists(cliArgs.envFile)\n ? ctx.fs.readUtf8File(cliArgs.envFile)\n : null;\n if (existingFile === null) {\n return ctx.crash({\n exitCode: 1,\n errorType: \"invalid filesystem or env vars\",\n printedMessage: \"env file does not exist\",\n });\n }\n const config = dotenv.parse(existingFile);\n const result = await getDeploymentSelectionFromEnv(ctx, (name) =>\n config[name] === undefined || config[name] === \"\" ? null : config[name],\n );\n if (result.kind === \"unknown\") {\n return ctx.crash({\n exitCode: 1,\n errorType: \"invalid filesystem or env vars\",\n printedMessage:\n `env file \\`${cliArgs.envFile}\\` did not contain environment variables for a Convex deployment. ` +\n `Expected \\`${CONVEX_DEPLOY_KEY_ENV_VAR_NAME}\\`, \\`${CONVEX_DEPLOYMENT_ENV_VAR_NAME}\\`, or both \\`${CONVEX_SELF_HOSTED_URL_VAR_NAME}\\` and \\`${CONVEX_SELF_HOSTED_ADMIN_KEY_VAR_NAME}\\` to be set.`,\n });\n }\n return result.metadata;\n }\n // start with .env.local (but doesn't override existing)\n dotenv.config({ path: ENV_VAR_FILE_PATH });\n // for variables not already set, use .env values\n dotenv.config();\n const result = await getDeploymentSelectionFromEnv(ctx, (name) => {\n const value = process.env[name];\n if (value === undefined || value === \"\") {\n return null;\n }\n return value;\n });\n if (result.kind !== \"unknown\") {\n return result.metadata;\n }\n // none of these?\n\n // Check the `convex.json` for a configured team and project\n const { projectConfig } = await readProjectConfig(ctx);\n if (projectConfig.team !== undefined && projectConfig.project !== undefined) {\n return {\n kind: \"deploymentWithinProject\",\n targetProject: {\n kind: \"teamAndProjectSlugs\",\n teamSlug: projectConfig.team,\n projectSlug: projectConfig.project,\n },\n };\n }\n\n // Check if they're logged in\n const isLoggedIn = ctx.bigBrainAuth() !== null;\n if (\n (!isLoggedIn || process.env.CONVEX_AGENT_MODE === \"anonymous\") &&\n shouldAllowAnonymousDevelopment()\n ) {\n return {\n kind: \"anonymous\",\n deploymentName: null,\n };\n }\n\n // Choose a project interactively later\n return {\n kind: \"chooseProject\",\n };\n}\n\nasync function getDeploymentSelectionFromEnv(\n ctx: Context,\n getEnv: (name: string) => string | null,\n): Promise<\n { kind: \"success\"; metadata: DeploymentSelection } | { kind: \"unknown\" }\n> {\n const rawDeployKey = getEnv(CONVEX_DEPLOY_KEY_ENV_VAR_NAME);\n const deployKey = await processDeployKeyValue(\n ctx,\n rawDeployKey === null ? undefined : rawDeployKey,\n );\n if (deployKey !== undefined) {\n const deployKeyType = isPreviewDeployKey(deployKey)\n ? \"preview\"\n : isProjectKey(deployKey)\n ? \"project\"\n : \"deployment\";\n switch (deployKeyType) {\n case \"preview\": {\n // `CONVEX_DEPLOY_KEY` is set to a preview deploy key so this takes precedence over anything else.\n // At the moment, we don't verify that there aren't other env vars that would also be used for deployment selection (e.g. `CONVEX_DEPLOYMENT`)\n return {\n kind: \"success\",\n metadata: {\n kind: \"preview\",\n previewDeployKey: deployKey,\n },\n };\n }\n case \"project\": {\n // `CONVEX_DEPLOY_KEY` is set to a project deploy key.\n // Commands can select any deployment within the project. At the moment we don't check for other env vars (e.g. `CONVEX_DEPLOYMENT`)\n return {\n kind: \"success\",\n metadata: {\n kind: \"deploymentWithinProject\",\n targetProject: {\n kind: \"projectDeployKey\",\n projectDeployKey: deployKey,\n },\n },\n };\n }\n case \"deployment\": {\n // `CONVEX_DEPLOY_KEY` is set to a deployment's deploy key.\n // Deploy to this deployment -- selectors like `--prod` / `--preview-name` will be ignored.\n // At the moment, we don't verify that there aren't other env vars that would also be used for deployment selection (e.g. `CONVEX_DEPLOYMENT`)\n const deploymentName = await deploymentNameFromAdminKeyOrCrash(\n ctx,\n deployKey,\n );\n const deploymentType = deploymentTypeFromAdminKey(deployKey);\n // We cannot derive the deployment URL from the deploy key, because it\n // might be a custom domain. Ask big brain for the URL.\n const url = await bigBrainAPI({\n ctx,\n method: \"POST\",\n url: \"deployment/url_for_key\",\n data: {\n deployKey: deployKey,\n },\n });\n const slugs = await fetchTeamAndProjectForKey(ctx, deployKey);\n return {\n kind: \"success\",\n metadata: {\n kind: \"existingDeployment\",\n deploymentToActOn: {\n url: url,\n adminKey: deployKey,\n deploymentFields: {\n deploymentName: deploymentName,\n deploymentType: deploymentType,\n teamSlug: slugs.team,\n projectSlug: slugs.project,\n },\n source: \"deployKey\",\n },\n },\n };\n }\n default: {\n deployKeyType satisfies never;\n return ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: `Unexpected deploy key type: ${deployKeyType as any}`,\n });\n }\n }\n }\n\n const convexDeployment = getEnv(CONVEX_DEPLOYMENT_ENV_VAR_NAME);\n const selfHostedUrl = getEnv(CONVEX_SELF_HOSTED_URL_VAR_NAME);\n const selfHostedAdminKey = getEnv(CONVEX_SELF_HOSTED_ADMIN_KEY_VAR_NAME);\n\n if (selfHostedUrl !== null && selfHostedAdminKey !== null) {\n if (convexDeployment !== null) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"invalid filesystem or env vars\",\n printedMessage: `${CONVEX_DEPLOYMENT_ENV_VAR_NAME} must not be set when ${CONVEX_SELF_HOSTED_URL_VAR_NAME} and ${CONVEX_SELF_HOSTED_ADMIN_KEY_VAR_NAME} are set`,\n });\n }\n return {\n kind: \"success\",\n metadata: {\n kind: \"existingDeployment\",\n deploymentToActOn: {\n url: selfHostedUrl,\n adminKey: selfHostedAdminKey,\n deploymentFields: null,\n source: \"selfHosted\",\n },\n },\n };\n }\n\n if (convexDeployment !== null) {\n if (selfHostedUrl !== null || selfHostedAdminKey !== null) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"invalid filesystem or env vars\",\n printedMessage: `${CONVEX_SELF_HOSTED_URL_VAR_NAME} and ${CONVEX_SELF_HOSTED_ADMIN_KEY_VAR_NAME} must not be set when ${CONVEX_DEPLOYMENT_ENV_VAR_NAME} is set`,\n });\n }\n const targetDeploymentType =\n getDeploymentTypeFromConfiguredDeployment(convexDeployment);\n const targetDeploymentName = stripDeploymentTypePrefix(convexDeployment);\n const isAnonymous = isAnonymousDeployment(targetDeploymentName);\n if (isAnonymous) {\n if (!shouldAllowAnonymousDevelopment()) {\n return {\n kind: \"unknown\",\n };\n }\n return {\n kind: \"success\",\n metadata: {\n kind: \"anonymous\",\n deploymentName: targetDeploymentName,\n },\n };\n }\n // Commands can select a deployment within the project that this deployment belongs to.\n return {\n kind: \"success\",\n metadata: {\n kind: \"deploymentWithinProject\",\n targetProject: {\n kind: \"deploymentName\",\n deploymentName: targetDeploymentName,\n deploymentType: targetDeploymentType,\n },\n },\n };\n }\n\n // Throw a nice error if we're in something like a CI environment where we need a valid deployment configuration\n await checkIfBuildEnvironmentRequiresDeploymentConfig(ctx);\n\n return { kind: \"unknown\" };\n}\n\nasync function checkIfBuildEnvironmentRequiresDeploymentConfig(ctx: Context) {\n const buildEnvironment = getBuildEnvironment();\n if (buildEnvironment) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage:\n `${buildEnvironment} build environment detected but no Convex deployment configuration found.\\n` +\n `Set one of:\\n` +\n ` \u2022 ${CONVEX_DEPLOY_KEY_ENV_VAR_NAME} for Convex Cloud deployments\\n` +\n ` \u2022 ${CONVEX_SELF_HOSTED_URL_VAR_NAME} and ${CONVEX_SELF_HOSTED_ADMIN_KEY_VAR_NAME} for self-hosted deployments\\n` +\n `See https://docs.convex.dev/production/hosting or https://docs.convex.dev/self-hosting`,\n });\n }\n}\n\n/**\n * Used for things like `npx convex docs` where we want to best effort extract a deployment name\n * but don't do the full deployment selection logic.\n */\nexport const deploymentNameFromSelection = (\n selection: DeploymentSelection,\n): string | null => {\n return deploymentNameAndTypeFromSelection(selection)?.name ?? null;\n};\n\nexport const deploymentNameAndTypeFromSelection = (\n selection: DeploymentSelection,\n): { name: string | null; type: string | null } | null => {\n switch (selection.kind) {\n case \"existingDeployment\": {\n return {\n name:\n selection.deploymentToActOn.deploymentFields?.deploymentName ?? null,\n type:\n selection.deploymentToActOn.deploymentFields?.deploymentType ?? null,\n };\n }\n case \"deploymentWithinProject\": {\n return selection.targetProject.kind === \"deploymentName\"\n ? {\n name: selection.targetProject.deploymentName,\n type: selection.targetProject.deploymentType,\n }\n : null;\n }\n case \"preview\": {\n return null;\n }\n case \"chooseProject\": {\n return null;\n }\n case \"anonymous\": {\n return null;\n }\n default: {\n selection satisfies never;\n }\n }\n return null;\n};\n\nexport const shouldAllowAnonymousDevelopment = (): boolean => {\n // Kill switch / temporary opt out\n if (process.env.CONVEX_ALLOW_ANONYMOUS === \"false\") {\n return false;\n }\n return true;\n};\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,iBAA2B;AAC3B,iBAIO;AACP,
|
|
4
|
+
"sourcesContent": ["import { BigBrainAuth, Context } from \"../../bundler/context.js\";\nimport { logVerbose } from \"../../bundler/log.js\";\nimport {\n AccountRequiredDeploymentType,\n DeploymentType,\n fetchTeamAndProjectForKey,\n} from \"./api.js\";\nimport {\n deploymentNameFromAdminKeyOrCrash,\n deploymentTypeFromAdminKey,\n getDeploymentTypeFromConfiguredDeployment,\n isAnonymousDeployment,\n isDeploymentKey,\n isPreviewDeployKey,\n isProjectKey,\n stripDeploymentTypePrefix,\n} from \"./deployment.js\";\nimport { getBuildEnvironment } from \"./envvars.js\";\nimport { readGlobalConfig } from \"./utils/globalConfig.js\";\nimport {\n CONVEX_DEPLOYMENT_ENV_VAR_NAME,\n CONVEX_DEPLOY_KEY_ENV_VAR_NAME,\n CONVEX_SELF_HOSTED_ADMIN_KEY_VAR_NAME,\n CONVEX_SELF_HOSTED_URL_VAR_NAME,\n ENV_VAR_FILE_PATH,\n bigBrainAPI,\n processDeployKeyValue,\n} from \"./utils/utils.js\";\nimport * as dotenv from \"dotenv\";\n\n// ----------------------------------------------------------------------------\n// Big Brain Auth\n// ----------------------------------------------------------------------------\n\n/**\n * The auth header can be a few different things:\n * * An access token (corresponds to device authorization, usually stored in `~/.convex/config.json`)\n * * A preview deploy key (set via the `CONVEX_DEPLOY_KEY` environment variable)\n * * A project key (set via the `CONVEX_DEPLOY_KEY` environment variable)\n * * A deployment key if a deployment key (set via `CONVEX_DEPLOY_KEY` environment variable)\n *\n * Project keys take precedence over the the access token.\n * Deployment keys take precedence over the the access token.\n * This makes using one of these keys while logged in or logged out work the same.\n *\n * We check for the `CONVEX_DEPLOY_KEY` in the `--env-file` if it's provided.\n * Otherwise, we check in the `.env` and `.env.local` files.\n *\n * If we later prompt for log in, we need to call `ctx.setBigBrainAuthHeader` to\n * update the value.\n *\n * @param ctx\n * @param envFile\n * @returns\n */\nexport async function initializeBigBrainAuth(\n ctx: Context,\n initialArgs: {\n url?: string | undefined;\n adminKey?: string | undefined;\n envFile?: string | undefined;\n },\n): Promise<void> {\n if (initialArgs.url !== undefined && initialArgs.adminKey !== undefined) {\n // Do not check any env vars if `url` and `adminKey` are specified via CLI\n ctx._updateBigBrainAuth(\n getBigBrainAuth(ctx, {\n previewDeployKey: null,\n projectKey: null,\n deploymentKey: null,\n }),\n );\n return;\n }\n if (initialArgs.envFile !== undefined) {\n const existingFile = ctx.fs.exists(initialArgs.envFile)\n ? ctx.fs.readUtf8File(initialArgs.envFile)\n : null;\n if (existingFile === null) {\n return ctx.crash({\n exitCode: 1,\n errorType: \"invalid filesystem or env vars\",\n printedMessage: \"env file does not exist\",\n });\n }\n const config = dotenv.parse(existingFile);\n const rawDeployKey = config[CONVEX_DEPLOY_KEY_ENV_VAR_NAME];\n const deployKey = await processDeployKeyValue(ctx, rawDeployKey);\n if (deployKey !== undefined) {\n const bigBrainAuth = getBigBrainAuth(ctx, {\n previewDeployKey: isPreviewDeployKey(deployKey) ? deployKey : null,\n projectKey: isProjectKey(deployKey) ? deployKey : null,\n deploymentKey: isDeploymentKey(deployKey) ? deployKey : null,\n });\n ctx._updateBigBrainAuth(bigBrainAuth);\n }\n return;\n }\n dotenv.config({ path: ENV_VAR_FILE_PATH });\n dotenv.config();\n const rawDeployKey = process.env[CONVEX_DEPLOY_KEY_ENV_VAR_NAME];\n const deployKey = await processDeployKeyValue(ctx, rawDeployKey);\n if (deployKey !== undefined) {\n const bigBrainAuth = getBigBrainAuth(ctx, {\n previewDeployKey: isPreviewDeployKey(deployKey) ? deployKey : null,\n projectKey: isProjectKey(deployKey) ? deployKey : null,\n deploymentKey: isDeploymentKey(deployKey) ? deployKey : null,\n });\n ctx._updateBigBrainAuth(bigBrainAuth);\n return;\n }\n ctx._updateBigBrainAuth(\n getBigBrainAuth(ctx, {\n previewDeployKey: null,\n projectKey: null,\n deploymentKey: null,\n }),\n );\n return;\n}\n\nexport async function updateBigBrainAuthAfterLogin(\n ctx: Context,\n accessToken: string,\n) {\n const existingAuth = ctx.bigBrainAuth();\n if (existingAuth !== null && existingAuth.kind === \"projectKey\") {\n logVerbose(\n `Ignoring update to big brain auth since project key takes precedence`,\n );\n return;\n }\n ctx._updateBigBrainAuth({\n accessToken: accessToken,\n kind: \"accessToken\",\n header: `Bearer ${accessToken}`,\n });\n}\n\nexport async function clearBigBrainAuth(ctx: Context) {\n ctx._updateBigBrainAuth(null);\n}\n\nfunction getBigBrainAuth(\n ctx: Context,\n opts: {\n previewDeployKey: string | null;\n projectKey: string | null;\n deploymentKey: string | null;\n },\n): BigBrainAuth | null {\n if (process.env.CONVEX_OVERRIDE_ACCESS_TOKEN) {\n return {\n accessToken: process.env.CONVEX_OVERRIDE_ACCESS_TOKEN,\n kind: \"accessToken\",\n header: `Bearer ${process.env.CONVEX_OVERRIDE_ACCESS_TOKEN}`,\n };\n }\n if (opts.projectKey !== null) {\n // Project keys take precedence over global config.\n return {\n header: `Bearer ${opts.projectKey}`,\n kind: \"projectKey\",\n projectKey: opts.projectKey,\n };\n }\n if (opts.deploymentKey !== null) {\n // Deployment keys take precedence over global config.\n return {\n header: `Bearer ${opts.deploymentKey}`,\n kind: \"deploymentKey\",\n deploymentKey: opts.deploymentKey,\n };\n }\n const globalConfig = readGlobalConfig(ctx);\n if (globalConfig) {\n return {\n kind: \"accessToken\",\n header: `Bearer ${globalConfig.accessToken}`,\n accessToken: globalConfig.accessToken,\n };\n }\n if (opts.previewDeployKey !== null) {\n return {\n header: `Bearer ${opts.previewDeployKey}`,\n kind: \"previewDeployKey\",\n previewDeployKey: opts.previewDeployKey,\n };\n }\n return null;\n}\n\n// ----------------------------------------------------------------------------\n// Deployment Selection\n// ----------------------------------------------------------------------------\n/**\n * Our CLI has logic to select which deployment to act on.\n *\n * We first check whether we're targeting a deployment within a project, or if we\n * know exactly which deployment to act on (e.g. in the case of self-hosting).\n *\n * We also special case preview deploys since the presence of a preview deploy key\n * triggers different behavior in `npx convex deploy`.\n *\n * Most commands will immediately compute the deployment selection, and then combine\n * that with any relevant CLI flags to figure out which deployment to talk to.\n *\n * Different commands do different things (e.g. `dev` will allow you to create a new project,\n * `deploy` has different behavior for preview deploys)\n *\n * This should be kept in sync with `initializeBigBrainAuth` since environment variables\n * like `CONVEX_DEPLOY_KEY` are used for both deployment selection and auth.\n */\nexport type DeploymentSelection =\n | {\n kind: \"existingDeployment\";\n deploymentToActOn: {\n url: string;\n adminKey: string;\n deploymentFields: {\n deploymentName: string;\n deploymentType: DeploymentType;\n projectSlug: string;\n teamSlug: string;\n } | null;\n source: \"selfHosted\" | \"deployKey\" | \"cliArgs\";\n };\n }\n | {\n kind: \"deploymentWithinProject\";\n targetProject: ProjectSelection;\n }\n | {\n kind: \"preview\";\n previewDeployKey: string;\n }\n | {\n kind: \"chooseProject\";\n }\n | {\n kind: \"anonymous\";\n deploymentName: string | null;\n };\n\nexport type ProjectSelection =\n | {\n kind: \"teamAndProjectSlugs\";\n teamSlug: string;\n projectSlug: string;\n }\n | {\n kind: \"deploymentName\";\n deploymentName: string;\n deploymentType: AccountRequiredDeploymentType | null;\n }\n | {\n kind: \"projectDeployKey\";\n projectDeployKey: string;\n };\n\nexport async function getDeploymentSelection(\n ctx: Context,\n cliArgs: {\n url?: string | undefined;\n adminKey?: string | undefined;\n envFile?: string | undefined;\n },\n): Promise<DeploymentSelection> {\n const metadata = await _getDeploymentSelection(ctx, cliArgs);\n logDeploymentSelection(ctx, metadata);\n return metadata;\n}\n\nfunction logDeploymentSelection(_ctx: Context, selection: DeploymentSelection) {\n switch (selection.kind) {\n case \"existingDeployment\": {\n logVerbose(\n `Existing deployment: ${selection.deploymentToActOn.url} ${selection.deploymentToActOn.source}`,\n );\n break;\n }\n case \"deploymentWithinProject\": {\n logVerbose(\n `Deployment within project: ${prettyProjectSelection(selection.targetProject)}`,\n );\n break;\n }\n case \"preview\": {\n logVerbose(`Preview deploy key`);\n break;\n }\n case \"chooseProject\": {\n logVerbose(`Choose project`);\n break;\n }\n case \"anonymous\": {\n logVerbose(\n `Anonymous, has selected deployment?: ${selection.deploymentName !== null}`,\n );\n break;\n }\n default: {\n selection satisfies never;\n logVerbose(`Unknown deployment selection`);\n }\n }\n return null;\n}\n\nfunction prettyProjectSelection(selection: ProjectSelection) {\n switch (selection.kind) {\n case \"teamAndProjectSlugs\": {\n return `Team and project slugs: ${selection.teamSlug} ${selection.projectSlug}`;\n }\n case \"deploymentName\": {\n return `Deployment name: ${selection.deploymentName}`;\n }\n case \"projectDeployKey\": {\n return `Project deploy key`;\n }\n default: {\n selection satisfies never;\n return `Unknown`;\n }\n }\n}\n\nasync function _getDeploymentSelection(\n ctx: Context,\n cliArgs: {\n url?: string | undefined;\n adminKey?: string | undefined;\n envFile?: string | undefined;\n },\n): Promise<DeploymentSelection> {\n /*\n - url + adminKey specified via CLI\n - Do not check any env vars (including ones relevant for auth)\n */\n if (cliArgs.url !== undefined && cliArgs.adminKey !== undefined) {\n return {\n kind: \"existingDeployment\",\n deploymentToActOn: {\n url: cliArgs.url,\n adminKey: cliArgs.adminKey,\n deploymentFields: null,\n source: \"cliArgs\",\n },\n };\n }\n\n if (cliArgs.envFile !== undefined) {\n // If an `--env-file` is specified, it must contain enough information for both auth and deployment selection.\n logVerbose(`Checking env file: ${cliArgs.envFile}`);\n const existingFile = ctx.fs.exists(cliArgs.envFile)\n ? ctx.fs.readUtf8File(cliArgs.envFile)\n : null;\n if (existingFile === null) {\n return ctx.crash({\n exitCode: 1,\n errorType: \"invalid filesystem or env vars\",\n printedMessage: \"env file does not exist\",\n });\n }\n const config = dotenv.parse(existingFile);\n const result = await getDeploymentSelectionFromEnv(ctx, (name) =>\n config[name] === undefined || config[name] === \"\" ? null : config[name],\n );\n if (result.kind === \"unknown\") {\n return ctx.crash({\n exitCode: 1,\n errorType: \"invalid filesystem or env vars\",\n printedMessage:\n `env file \\`${cliArgs.envFile}\\` did not contain environment variables for a Convex deployment. ` +\n `Expected \\`${CONVEX_DEPLOY_KEY_ENV_VAR_NAME}\\`, \\`${CONVEX_DEPLOYMENT_ENV_VAR_NAME}\\`, or both \\`${CONVEX_SELF_HOSTED_URL_VAR_NAME}\\` and \\`${CONVEX_SELF_HOSTED_ADMIN_KEY_VAR_NAME}\\` to be set.`,\n });\n }\n return result.metadata;\n }\n // start with .env.local (but doesn't override existing)\n dotenv.config({ path: ENV_VAR_FILE_PATH });\n // for variables not already set, use .env values\n dotenv.config();\n const result = await getDeploymentSelectionFromEnv(ctx, (name) => {\n const value = process.env[name];\n if (value === undefined || value === \"\") {\n return null;\n }\n return value;\n });\n if (result.kind !== \"unknown\") {\n return result.metadata;\n }\n // none of these?\n\n // Check if they're logged in\n const isLoggedIn = ctx.bigBrainAuth() !== null;\n if (\n (!isLoggedIn || process.env.CONVEX_AGENT_MODE === \"anonymous\") &&\n shouldAllowAnonymousDevelopment()\n ) {\n return {\n kind: \"anonymous\",\n deploymentName: null,\n };\n }\n\n // Choose a project interactively later\n return {\n kind: \"chooseProject\",\n };\n}\n\nasync function getDeploymentSelectionFromEnv(\n ctx: Context,\n getEnv: (name: string) => string | null,\n): Promise<\n { kind: \"success\"; metadata: DeploymentSelection } | { kind: \"unknown\" }\n> {\n const rawDeployKey = getEnv(CONVEX_DEPLOY_KEY_ENV_VAR_NAME);\n const deployKey = await processDeployKeyValue(\n ctx,\n rawDeployKey === null ? undefined : rawDeployKey,\n );\n if (deployKey !== undefined) {\n const deployKeyType = isPreviewDeployKey(deployKey)\n ? \"preview\"\n : isProjectKey(deployKey)\n ? \"project\"\n : \"deployment\";\n switch (deployKeyType) {\n case \"preview\": {\n // `CONVEX_DEPLOY_KEY` is set to a preview deploy key so this takes precedence over anything else.\n // At the moment, we don't verify that there aren't other env vars that would also be used for deployment selection (e.g. `CONVEX_DEPLOYMENT`)\n return {\n kind: \"success\",\n metadata: {\n kind: \"preview\",\n previewDeployKey: deployKey,\n },\n };\n }\n case \"project\": {\n // `CONVEX_DEPLOY_KEY` is set to a project deploy key.\n // Commands can select any deployment within the project. At the moment we don't check for other env vars (e.g. `CONVEX_DEPLOYMENT`)\n return {\n kind: \"success\",\n metadata: {\n kind: \"deploymentWithinProject\",\n targetProject: {\n kind: \"projectDeployKey\",\n projectDeployKey: deployKey,\n },\n },\n };\n }\n case \"deployment\": {\n // `CONVEX_DEPLOY_KEY` is set to a deployment's deploy key.\n // Deploy to this deployment -- selectors like `--prod` / `--preview-name` will be ignored.\n // At the moment, we don't verify that there aren't other env vars that would also be used for deployment selection (e.g. `CONVEX_DEPLOYMENT`)\n const deploymentName = await deploymentNameFromAdminKeyOrCrash(\n ctx,\n deployKey,\n );\n const deploymentType = deploymentTypeFromAdminKey(deployKey);\n // We cannot derive the deployment URL from the deploy key, because it\n // might be a custom domain. Ask big brain for the URL.\n const url = await bigBrainAPI({\n ctx,\n method: \"POST\",\n url: \"deployment/url_for_key\",\n data: {\n deployKey: deployKey,\n },\n });\n const slugs = await fetchTeamAndProjectForKey(ctx, deployKey);\n return {\n kind: \"success\",\n metadata: {\n kind: \"existingDeployment\",\n deploymentToActOn: {\n url: url,\n adminKey: deployKey,\n deploymentFields: {\n deploymentName: deploymentName,\n deploymentType: deploymentType,\n teamSlug: slugs.team,\n projectSlug: slugs.project,\n },\n source: \"deployKey\",\n },\n },\n };\n }\n default: {\n deployKeyType satisfies never;\n return ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: `Unexpected deploy key type: ${deployKeyType as any}`,\n });\n }\n }\n }\n\n const convexDeployment = getEnv(CONVEX_DEPLOYMENT_ENV_VAR_NAME);\n const selfHostedUrl = getEnv(CONVEX_SELF_HOSTED_URL_VAR_NAME);\n const selfHostedAdminKey = getEnv(CONVEX_SELF_HOSTED_ADMIN_KEY_VAR_NAME);\n\n if (selfHostedUrl !== null && selfHostedAdminKey !== null) {\n if (convexDeployment !== null) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"invalid filesystem or env vars\",\n printedMessage: `${CONVEX_DEPLOYMENT_ENV_VAR_NAME} must not be set when ${CONVEX_SELF_HOSTED_URL_VAR_NAME} and ${CONVEX_SELF_HOSTED_ADMIN_KEY_VAR_NAME} are set`,\n });\n }\n return {\n kind: \"success\",\n metadata: {\n kind: \"existingDeployment\",\n deploymentToActOn: {\n url: selfHostedUrl,\n adminKey: selfHostedAdminKey,\n deploymentFields: null,\n source: \"selfHosted\",\n },\n },\n };\n }\n\n if (convexDeployment !== null) {\n if (selfHostedUrl !== null || selfHostedAdminKey !== null) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"invalid filesystem or env vars\",\n printedMessage: `${CONVEX_SELF_HOSTED_URL_VAR_NAME} and ${CONVEX_SELF_HOSTED_ADMIN_KEY_VAR_NAME} must not be set when ${CONVEX_DEPLOYMENT_ENV_VAR_NAME} is set`,\n });\n }\n const targetDeploymentType =\n getDeploymentTypeFromConfiguredDeployment(convexDeployment);\n const targetDeploymentName = stripDeploymentTypePrefix(convexDeployment);\n const isAnonymous = isAnonymousDeployment(targetDeploymentName);\n if (isAnonymous) {\n if (!shouldAllowAnonymousDevelopment()) {\n return {\n kind: \"unknown\",\n };\n }\n return {\n kind: \"success\",\n metadata: {\n kind: \"anonymous\",\n deploymentName: targetDeploymentName,\n },\n };\n }\n // Commands can select a deployment within the project that this deployment belongs to.\n return {\n kind: \"success\",\n metadata: {\n kind: \"deploymentWithinProject\",\n targetProject: {\n kind: \"deploymentName\",\n deploymentName: targetDeploymentName,\n deploymentType: targetDeploymentType,\n },\n },\n };\n }\n\n // Throw a nice error if we're in something like a CI environment where we need a valid deployment configuration\n await checkIfBuildEnvironmentRequiresDeploymentConfig(ctx);\n\n return { kind: \"unknown\" };\n}\n\nasync function checkIfBuildEnvironmentRequiresDeploymentConfig(ctx: Context) {\n const buildEnvironment = getBuildEnvironment();\n if (buildEnvironment) {\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage:\n `${buildEnvironment} build environment detected but no Convex deployment configuration found.\\n` +\n `Set one of:\\n` +\n ` \u2022 ${CONVEX_DEPLOY_KEY_ENV_VAR_NAME} for Convex Cloud deployments\\n` +\n ` \u2022 ${CONVEX_SELF_HOSTED_URL_VAR_NAME} and ${CONVEX_SELF_HOSTED_ADMIN_KEY_VAR_NAME} for self-hosted deployments\\n` +\n `See https://docs.convex.dev/production/hosting or https://docs.convex.dev/self-hosting`,\n });\n }\n}\n\n/**\n * Used for things like `npx convex docs` where we want to best effort extract a deployment name\n * but don't do the full deployment selection logic.\n */\nexport const deploymentNameFromSelection = (\n selection: DeploymentSelection,\n): string | null => {\n return deploymentNameAndTypeFromSelection(selection)?.name ?? null;\n};\n\nexport const deploymentNameAndTypeFromSelection = (\n selection: DeploymentSelection,\n): { name: string | null; type: string | null } | null => {\n switch (selection.kind) {\n case \"existingDeployment\": {\n return {\n name:\n selection.deploymentToActOn.deploymentFields?.deploymentName ?? null,\n type:\n selection.deploymentToActOn.deploymentFields?.deploymentType ?? null,\n };\n }\n case \"deploymentWithinProject\": {\n return selection.targetProject.kind === \"deploymentName\"\n ? {\n name: selection.targetProject.deploymentName,\n type: selection.targetProject.deploymentType,\n }\n : null;\n }\n case \"preview\": {\n return null;\n }\n case \"chooseProject\": {\n return null;\n }\n case \"anonymous\": {\n return null;\n }\n default: {\n selection satisfies never;\n }\n }\n return null;\n};\n\nexport const shouldAllowAnonymousDevelopment = (): boolean => {\n // Kill switch / temporary opt out\n if (process.env.CONVEX_ALLOW_ANONYMOUS === \"false\") {\n return false;\n }\n return true;\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["rawDeployKey", "deployKey", "result"]
|
|
7
7
|
}
|
package/dist/cjs/cli/lib/dev.js
CHANGED
|
@@ -42,8 +42,23 @@ var import_logs = require("./logs.js");
|
|
|
42
42
|
var import_utils = require("./utils/utils.js");
|
|
43
43
|
var import_watch = require("./watch.js");
|
|
44
44
|
var import_run = require("./run.js");
|
|
45
|
+
var import_config = require("./config.js");
|
|
46
|
+
var import_workos = require("./workos/workos.js");
|
|
45
47
|
async function devAgainstDeployment(ctx, credentials, devOptions) {
|
|
46
48
|
const logManager = new import_logs.LogManager(devOptions.tailLogs);
|
|
49
|
+
const { projectConfig } = await (0, import_config.readProjectConfig)(ctx);
|
|
50
|
+
const authKitConfig = await (0, import_config.getAuthKitConfig)(ctx, projectConfig);
|
|
51
|
+
if (authKitConfig && credentials.deploymentName) {
|
|
52
|
+
const deploymentType = credentials.deploymentType;
|
|
53
|
+
if (deploymentType === "dev" || deploymentType === "preview" || deploymentType === "prod") {
|
|
54
|
+
await (0, import_workos.ensureAuthKitProvisionedBeforeBuild)(
|
|
55
|
+
ctx,
|
|
56
|
+
credentials.deploymentName,
|
|
57
|
+
{ deploymentUrl: credentials.url, adminKey: credentials.adminKey },
|
|
58
|
+
deploymentType
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
47
62
|
const promises = [];
|
|
48
63
|
if (devOptions.tailLogs !== "disable") {
|
|
49
64
|
promises.push(
|
|
@@ -80,11 +95,15 @@ async function devAgainstDeployment(ctx, credentials, devOptions) {
|
|
|
80
95
|
}
|
|
81
96
|
async function watchAndPush(outerCtx, options, cmdOptions) {
|
|
82
97
|
const watch = { watcher: void 0 };
|
|
98
|
+
const authKitCache = {
|
|
99
|
+
lastAppliedConfig: void 0
|
|
100
|
+
};
|
|
83
101
|
let numFailures = 0;
|
|
84
102
|
let ran = false;
|
|
85
103
|
let pushed = false;
|
|
86
104
|
let tableNameTriggeringRetry;
|
|
87
105
|
let shouldRetryOnDeploymentEnvVarChange;
|
|
106
|
+
let isFirstPush = true;
|
|
88
107
|
while (true) {
|
|
89
108
|
const start = import_perf_hooks.performance.now();
|
|
90
109
|
tableNameTriggeringRetry = null;
|
|
@@ -105,6 +124,17 @@ async function watchAndPush(outerCtx, options, cmdOptions) {
|
|
|
105
124
|
end - start
|
|
106
125
|
)})`
|
|
107
126
|
);
|
|
127
|
+
const { projectConfig } = await (0, import_config.readProjectConfig)(ctx);
|
|
128
|
+
const authKitConfig = await (0, import_config.getAuthKitConfig)(ctx, projectConfig);
|
|
129
|
+
const currentConfigString = authKitConfig ? JSON.stringify(authKitConfig) : void 0;
|
|
130
|
+
if (!isFirstPush && currentConfigString !== authKitCache.lastAppliedConfig) {
|
|
131
|
+
await (0, import_workos.syncAuthKitConfigAfterPush)(ctx, projectConfig, {
|
|
132
|
+
deploymentUrl: options.url,
|
|
133
|
+
adminKey: options.adminKey
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
authKitCache.lastAppliedConfig = currentConfigString;
|
|
137
|
+
isFirstPush = false;
|
|
108
138
|
if (cmdOptions.run !== void 0 && !ran) {
|
|
109
139
|
switch (cmdOptions.run.kind) {
|
|
110
140
|
case "function":
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/cli/lib/dev.ts"],
|
|
4
|
-
"sourcesContent": ["import { chalkStderr } from \"chalk\";\nimport { OneoffCtx } from \"../../bundler/context.js\";\nimport {\n logError,\n logFinishedStep,\n logMessage,\n logWarning,\n showSpinner,\n showSpinnerIfSlow,\n stopSpinner,\n} from \"../../bundler/log.js\";\nimport { runPush } from \"./components.js\";\nimport { performance } from \"perf_hooks\";\nimport path from \"path\";\nimport { LogManager, LogMode, watchLogs } from \"./logs.js\";\nimport { PushOptions } from \"./components.js\";\nimport {\n formatDuration,\n getCurrentTimeString,\n spawnAsync,\n waitForever,\n waitUntilCalled,\n} from \"./utils/utils.js\";\nimport { Crash, WatchContext, Watcher } from \"./watch.js\";\nimport { runFunctionAndLog, subscribe } from \"./run.js\";\nimport { Value } from \"../../values/index.js\";\n\nexport async function devAgainstDeployment(\n ctx: OneoffCtx,\n credentials: {\n url: string;\n adminKey: string;\n deploymentName: string | null;\n },\n devOptions: {\n verbose: boolean;\n typecheck: \"enable\" | \"try\" | \"disable\";\n typecheckComponents: boolean;\n codegen: boolean;\n once: boolean;\n untilSuccess: boolean;\n run?:\n | { kind: \"function\"; name: string; component?: string | undefined }\n | { kind: \"shell\"; command: string }\n | undefined;\n tailLogs: LogMode;\n traceEvents: boolean;\n debugBundlePath?: string | undefined;\n debugNodeApis: boolean;\n liveComponentSources: boolean;\n },\n) {\n const logManager = new LogManager(devOptions.tailLogs);\n\n const promises = [];\n if (devOptions.tailLogs !== \"disable\") {\n promises.push(\n watchLogs(ctx, credentials.url, credentials.adminKey, \"stderr\", {\n logManager,\n success: false,\n }),\n );\n }\n\n promises.push(\n watchAndPush(\n ctx,\n {\n ...credentials,\n verbose: devOptions.verbose,\n dryRun: false,\n typecheck: devOptions.typecheck,\n typecheckComponents: devOptions.typecheckComponents,\n debug: false,\n debugBundlePath: devOptions.debugBundlePath,\n debugNodeApis: devOptions.debugNodeApis,\n codegen: devOptions.codegen,\n liveComponentSources: devOptions.liveComponentSources,\n logManager, // Pass logManager to control logs during deploy\n largeIndexDeletionCheck: \"no verification\", // `convex dev` can\u2019t push to prod\n },\n devOptions,\n ),\n );\n await Promise.race(promises);\n await ctx.flushAndExit(0);\n}\n\nexport async function watchAndPush(\n outerCtx: OneoffCtx,\n options: PushOptions,\n cmdOptions: {\n run?:\n | { kind: \"function\"; name: string; component?: string | undefined }\n | { kind: \"shell\"; command: string }\n | undefined;\n once: boolean;\n untilSuccess: boolean;\n traceEvents: boolean;\n },\n) {\n const watch: { watcher: Watcher | undefined } = { watcher: undefined };\n let numFailures = 0;\n let ran = false;\n let pushed = false;\n let tableNameTriggeringRetry;\n let shouldRetryOnDeploymentEnvVarChange;\n\n while (true) {\n const start = performance.now();\n tableNameTriggeringRetry = null;\n shouldRetryOnDeploymentEnvVarChange = false;\n\n const ctx = new WatchContext(\n cmdOptions.traceEvents,\n outerCtx.bigBrainAuth(),\n );\n options.logManager?.beginDeploy();\n showSpinner(\"Preparing Convex functions...\");\n try {\n await runPush(ctx, options);\n const end = performance.now();\n // NOTE: If `runPush` throws, `endDeploy` will not be called.\n // This allows you to see the output from the failed deploy without\n // logs getting in the way.\n options.logManager?.endDeploy();\n numFailures = 0;\n logFinishedStep(\n `${getCurrentTimeString()} Convex functions ready! (${formatDuration(\n end - start,\n )})`,\n );\n if (cmdOptions.run !== undefined && !ran) {\n switch (cmdOptions.run.kind) {\n case \"function\":\n await runFunctionInDev(\n ctx,\n options,\n cmdOptions.run.name,\n cmdOptions.run.component,\n );\n break;\n case \"shell\":\n try {\n await spawnAsync(ctx, cmdOptions.run.command, [], {\n stdio: \"inherit\",\n shell: true,\n });\n } catch (e) {\n // `spawnAsync` throws an error like `{ status: 1, error: Error }`\n // when the command fails.\n const errorMessage =\n e === null || e === undefined\n ? null\n : (e as any).error instanceof Error\n ? ((e as any).error.message ?? null)\n : null;\n const printedMessage = `Failed to run command \\`${cmdOptions.run.command}\\`: ${errorMessage ?? \"Unknown error\"}`;\n // Don't return this since it'll bypass the `catch` below.\n await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage,\n });\n }\n break;\n default: {\n cmdOptions.run satisfies never;\n // Don't return this since it'll bypass the `catch` below.\n await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: `Unexpected arguments for --run`,\n errForSentry: `Unexpected arguments for --run: ${JSON.stringify(\n cmdOptions.run,\n )}`,\n });\n }\n }\n ran = true;\n }\n pushed = true;\n } catch (e: any) {\n // Crash the app on unexpected errors.\n if (!(e instanceof Crash) || !e.errorType) {\n // eslint-disable-next-line no-restricted-syntax\n throw e;\n }\n if (e.errorType === \"fatal\") {\n break;\n }\n // Retry after an exponential backoff if we hit a transient error.\n if (e.errorType === \"transient\" || e.errorType === \"already handled\") {\n const delay = nextBackoff(numFailures);\n numFailures += 1;\n if (e.errorType === \"transient\") {\n logWarning(\n chalkStderr.yellow(\n `Failed due to network error, retrying in ${formatDuration(\n delay,\n )}...`,\n ),\n );\n }\n await new Promise((resolve) => setTimeout(resolve, delay));\n continue;\n }\n\n // Fall through if we had a filesystem-based error.\n // TODO(sarah): Replace this with `logError`.\n // eslint-disable-next-line no-console\n console.assert(\n e.errorType === \"invalid filesystem data\" ||\n e.errorType === \"invalid filesystem or env vars\" ||\n e.errorType[\"invalid filesystem or db data\"] !== undefined,\n );\n if (e.errorType === \"invalid filesystem or env vars\") {\n shouldRetryOnDeploymentEnvVarChange = true;\n } else if (\n e.errorType !== \"invalid filesystem data\" &&\n e.errorType[\"invalid filesystem or db data\"] !== undefined\n ) {\n tableNameTriggeringRetry = e.errorType[\"invalid filesystem or db data\"];\n }\n if (cmdOptions.once) {\n await outerCtx.flushAndExit(1, e.errorType);\n }\n // Make sure that we don't spin if this push failed\n // in any edge cases that didn't call `logFailure`\n // before throwing.\n stopSpinner();\n }\n if (cmdOptions.once) {\n return;\n }\n if (pushed && cmdOptions.untilSuccess) {\n return;\n }\n const fileSystemWatch = getFileSystemWatch(ctx, watch, cmdOptions);\n const tableWatch = getTableWatch(\n ctx,\n options,\n tableNameTriggeringRetry?.tableName ?? null,\n tableNameTriggeringRetry?.componentPath,\n );\n const envVarWatch = getDeplymentEnvVarWatch(\n ctx,\n options,\n shouldRetryOnDeploymentEnvVarChange,\n );\n await Promise.race([\n fileSystemWatch.watch(),\n tableWatch.watch(),\n envVarWatch.watch(),\n ]);\n fileSystemWatch.stop();\n void tableWatch.stop();\n void envVarWatch.stop();\n }\n}\n\nasync function runFunctionInDev(\n ctx: WatchContext,\n credentials: {\n url: string;\n adminKey: string;\n },\n functionName: string,\n componentPath: string | undefined,\n) {\n await runFunctionAndLog(ctx, {\n deploymentUrl: credentials.url,\n adminKey: credentials.adminKey,\n functionName,\n argsString: \"{}\",\n componentPath,\n callbacks: {\n onSuccess: () => {\n logFinishedStep(`Finished running function \"${functionName}\"`);\n },\n },\n });\n}\n\nfunction getTableWatch(\n ctx: WatchContext,\n credentials: {\n url: string;\n adminKey: string;\n },\n tableName: string | null,\n componentPath: string | undefined,\n) {\n return getFunctionWatch(ctx, {\n deploymentUrl: credentials.url,\n adminKey: credentials.adminKey,\n parsedFunctionName: \"_system/cli/queryTable\",\n getArgs: () => (tableName !== null ? { tableName } : null),\n componentPath,\n });\n}\n\nfunction getDeplymentEnvVarWatch(\n ctx: WatchContext,\n credentials: {\n url: string;\n adminKey: string;\n },\n shouldRetryOnDeploymentEnvVarChange: boolean,\n) {\n return getFunctionWatch(ctx, {\n deploymentUrl: credentials.url,\n adminKey: credentials.adminKey,\n parsedFunctionName: \"_system/cli/queryEnvironmentVariables\",\n getArgs: () => (shouldRetryOnDeploymentEnvVarChange ? {} : null),\n componentPath: undefined,\n });\n}\n\nfunction getFunctionWatch(\n ctx: WatchContext,\n args: {\n deploymentUrl: string;\n adminKey: string;\n parsedFunctionName: string;\n getArgs: () => Record<string, Value> | null;\n componentPath: string | undefined;\n },\n) {\n const [stopPromise, stop] = waitUntilCalled();\n return {\n watch: async () => {\n const functionArgs = args.getArgs();\n if (functionArgs === null) {\n return waitForever();\n }\n let changes = 0;\n return subscribe(ctx, {\n deploymentUrl: args.deploymentUrl,\n adminKey: args.adminKey,\n parsedFunctionName: args.parsedFunctionName,\n parsedFunctionArgs: functionArgs,\n componentPath: args.componentPath,\n until: stopPromise,\n callbacks: {\n onChange: () => {\n changes++;\n // First bump is just the initial results reporting\n if (changes > 1) {\n stop();\n }\n },\n },\n });\n },\n stop: () => {\n stop();\n },\n };\n}\n\nfunction getFileSystemWatch(\n ctx: WatchContext,\n watch: { watcher: Watcher | undefined },\n cmdOptions: { traceEvents: boolean },\n) {\n let hasStopped = false;\n return {\n watch: async () => {\n const observations = ctx.fs.finalize();\n if (observations === \"invalidated\") {\n logMessage(\"Filesystem changed during push, retrying...\");\n return;\n }\n // Initialize the watcher if we haven't done it already. Chokidar expects to have a\n // nonempty watch set at initialization, so we can't do it before running our first\n // push.\n if (!watch.watcher) {\n watch.watcher = new Watcher(observations);\n await showSpinnerIfSlow(\n \"Preparing to watch files...\",\n 500,\n async () => {\n await watch.watcher!.ready();\n },\n );\n stopSpinner();\n }\n // Watch new directories if needed.\n watch.watcher.update(observations);\n\n // Process events until we find one that overlaps with our previous observations.\n let anyChanges = false;\n do {\n await watch.watcher.waitForEvent();\n if (hasStopped) {\n return;\n }\n for (const event of watch.watcher.drainEvents()) {\n if (cmdOptions.traceEvents) {\n logMessage(\n \"Processing\",\n event.name,\n path.relative(\"\", event.absPath),\n );\n }\n const result = observations.overlaps(event);\n if (result.overlaps) {\n const relPath = path.relative(\"\", event.absPath);\n if (cmdOptions.traceEvents) {\n logMessage(`${relPath} ${result.reason}, rebuilding...`);\n }\n anyChanges = true;\n break;\n }\n }\n } while (!anyChanges);\n\n // Wait for the filesystem to quiesce before starting a new push. It's okay to\n // drop filesystem events at this stage since we're already committed to doing\n // a push and resubscribing based on that push's observations.\n let deadline = performance.now() + quiescenceDelay;\n while (true) {\n const now = performance.now();\n if (now >= deadline) {\n break;\n }\n const remaining = deadline - now;\n if (cmdOptions.traceEvents) {\n logMessage(`Waiting for ${formatDuration(remaining)} to quiesce...`);\n }\n const remainingWait = new Promise<\"timeout\">((resolve) =>\n setTimeout(() => resolve(\"timeout\"), deadline - now),\n );\n const result = await Promise.race([\n remainingWait,\n watch.watcher.waitForEvent().then<\"newEvents\">(() => \"newEvents\"),\n ]);\n if (result === \"newEvents\") {\n for (const event of watch.watcher.drainEvents()) {\n const result = observations.overlaps(event);\n // Delay another `quiescenceDelay` since we had an overlapping event.\n if (result.overlaps) {\n if (cmdOptions.traceEvents) {\n logMessage(\n `Received an overlapping event at ${event.absPath}, delaying push.`,\n );\n }\n deadline = performance.now() + quiescenceDelay;\n }\n }\n } else {\n // Let the check above `break` from the loop if we're past our deadlne.\n if (result !== \"timeout\") {\n logError(\n \"Assertion failed: Unexpected result from watcher: \" + result,\n );\n }\n }\n }\n },\n stop: () => {\n hasStopped = true;\n },\n };\n}\n\nconst initialBackoff = 500;\nconst maxBackoff = 16000;\nconst quiescenceDelay = 500;\n\nexport function nextBackoff(prevFailures: number): number {\n const baseBackoff = initialBackoff * Math.pow(2, prevFailures);\n const actualBackoff = Math.min(baseBackoff, maxBackoff);\n const jitter = actualBackoff * (Math.random() - 0.5);\n return actualBackoff + jitter;\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA4B;AAE5B,iBAQO;AACP,wBAAwB;AACxB,wBAA4B;AAC5B,kBAAiB;AACjB,kBAA+C;AAE/C,mBAMO;AACP,mBAA6C;AAC7C,iBAA6C;AAG7C,eAAsB,qBACpB,KACA,
|
|
4
|
+
"sourcesContent": ["import { chalkStderr } from \"chalk\";\nimport { OneoffCtx } from \"../../bundler/context.js\";\nimport {\n logError,\n logFinishedStep,\n logMessage,\n logWarning,\n showSpinner,\n showSpinnerIfSlow,\n stopSpinner,\n} from \"../../bundler/log.js\";\nimport { runPush } from \"./components.js\";\nimport { performance } from \"perf_hooks\";\nimport path from \"path\";\nimport { LogManager, LogMode, watchLogs } from \"./logs.js\";\nimport { PushOptions } from \"./components.js\";\nimport {\n formatDuration,\n getCurrentTimeString,\n spawnAsync,\n waitForever,\n waitUntilCalled,\n} from \"./utils/utils.js\";\nimport { Crash, WatchContext, Watcher } from \"./watch.js\";\nimport { runFunctionAndLog, subscribe } from \"./run.js\";\nimport { Value } from \"../../values/index.js\";\nimport { DeploymentType } from \"./api.js\";\nimport { readProjectConfig, getAuthKitConfig } from \"./config.js\";\nimport {\n syncAuthKitConfigAfterPush,\n ensureAuthKitProvisionedBeforeBuild,\n} from \"./workos/workos.js\";\n\nexport async function devAgainstDeployment(\n ctx: OneoffCtx,\n credentials: {\n url: string;\n adminKey: string;\n deploymentName: string | null;\n deploymentType?: DeploymentType;\n },\n devOptions: {\n verbose: boolean;\n typecheck: \"enable\" | \"try\" | \"disable\";\n typecheckComponents: boolean;\n codegen: boolean;\n once: boolean;\n untilSuccess: boolean;\n run?:\n | { kind: \"function\"; name: string; component?: string | undefined }\n | { kind: \"shell\"; command: string }\n | undefined;\n tailLogs: LogMode;\n traceEvents: boolean;\n debugBundlePath?: string | undefined;\n debugNodeApis: boolean;\n liveComponentSources: boolean;\n },\n) {\n const logManager = new LogManager(devOptions.tailLogs);\n\n // Pre-flight check: Ensure AuthKit is provisioned before starting dev\n const { projectConfig } = await readProjectConfig(ctx);\n const authKitConfig = await getAuthKitConfig(ctx, projectConfig);\n\n if (authKitConfig && credentials.deploymentName) {\n // Only provision for cloud deployments (dev/preview/prod)\n // Skip for local and anonymous deployments\n const deploymentType = credentials.deploymentType;\n if (\n deploymentType === \"dev\" ||\n deploymentType === \"preview\" ||\n deploymentType === \"prod\"\n ) {\n await ensureAuthKitProvisionedBeforeBuild(\n ctx,\n credentials.deploymentName,\n { deploymentUrl: credentials.url, adminKey: credentials.adminKey },\n deploymentType,\n );\n }\n }\n\n const promises = [];\n if (devOptions.tailLogs !== \"disable\") {\n promises.push(\n watchLogs(ctx, credentials.url, credentials.adminKey, \"stderr\", {\n logManager,\n success: false,\n }),\n );\n }\n\n promises.push(\n watchAndPush(\n ctx,\n {\n ...credentials,\n verbose: devOptions.verbose,\n dryRun: false,\n typecheck: devOptions.typecheck,\n typecheckComponents: devOptions.typecheckComponents,\n debug: false,\n debugBundlePath: devOptions.debugBundlePath,\n debugNodeApis: devOptions.debugNodeApis,\n codegen: devOptions.codegen,\n liveComponentSources: devOptions.liveComponentSources,\n logManager, // Pass logManager to control logs during deploy\n largeIndexDeletionCheck: \"no verification\", // `convex dev` can\u2019t push to prod\n },\n devOptions,\n ),\n );\n await Promise.race(promises);\n await ctx.flushAndExit(0);\n}\n\nexport async function watchAndPush(\n outerCtx: OneoffCtx,\n options: PushOptions,\n cmdOptions: {\n run?:\n | { kind: \"function\"; name: string; component?: string | undefined }\n | { kind: \"shell\"; command: string }\n | undefined;\n once: boolean;\n untilSuccess: boolean;\n traceEvents: boolean;\n },\n) {\n const watch: { watcher: Watcher | undefined } = { watcher: undefined };\n const authKitCache: { lastAppliedConfig: string | undefined } = {\n lastAppliedConfig: undefined,\n };\n let numFailures = 0;\n let ran = false;\n let pushed = false;\n let tableNameTriggeringRetry;\n let shouldRetryOnDeploymentEnvVarChange;\n let isFirstPush = true; // Track if this is the first push in the session\n\n while (true) {\n const start = performance.now();\n tableNameTriggeringRetry = null;\n shouldRetryOnDeploymentEnvVarChange = false;\n\n const ctx = new WatchContext(\n cmdOptions.traceEvents,\n outerCtx.bigBrainAuth(),\n );\n options.logManager?.beginDeploy();\n showSpinner(\"Preparing Convex functions...\");\n try {\n await runPush(ctx, options);\n const end = performance.now();\n // NOTE: If `runPush` throws, `endDeploy` will not be called.\n // This allows you to see the output from the failed deploy without\n // logs getting in the way.\n options.logManager?.endDeploy();\n numFailures = 0;\n logFinishedStep(\n `${getCurrentTimeString()} Convex functions ready! (${formatDuration(\n end - start,\n )})`,\n );\n\n // Sync AuthKit configuration if it has changed\n const { projectConfig } = await readProjectConfig(ctx);\n const authKitConfig = await getAuthKitConfig(ctx, projectConfig);\n\n // Check if config has changed by comparing stringified versions\n const currentConfigString = authKitConfig\n ? JSON.stringify(authKitConfig)\n : undefined;\n\n // Skip sync on first push since ensureAuthKitProvisionedBeforeBuild already configured WorkOS\n if (\n !isFirstPush &&\n currentConfigString !== authKitCache.lastAppliedConfig\n ) {\n // Config has changed, sync it\n await syncAuthKitConfigAfterPush(ctx, projectConfig, {\n deploymentUrl: options.url,\n adminKey: options.adminKey,\n });\n }\n\n // Always update cache after push (even if we skipped sync)\n authKitCache.lastAppliedConfig = currentConfigString;\n isFirstPush = false;\n if (cmdOptions.run !== undefined && !ran) {\n switch (cmdOptions.run.kind) {\n case \"function\":\n await runFunctionInDev(\n ctx,\n options,\n cmdOptions.run.name,\n cmdOptions.run.component,\n );\n break;\n case \"shell\":\n try {\n await spawnAsync(ctx, cmdOptions.run.command, [], {\n stdio: \"inherit\",\n shell: true,\n });\n } catch (e) {\n // `spawnAsync` throws an error like `{ status: 1, error: Error }`\n // when the command fails.\n const errorMessage =\n e === null || e === undefined\n ? null\n : (e as any).error instanceof Error\n ? ((e as any).error.message ?? null)\n : null;\n const printedMessage = `Failed to run command \\`${cmdOptions.run.command}\\`: ${errorMessage ?? \"Unknown error\"}`;\n // Don't return this since it'll bypass the `catch` below.\n await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage,\n });\n }\n break;\n default: {\n cmdOptions.run satisfies never;\n // Don't return this since it'll bypass the `catch` below.\n await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: `Unexpected arguments for --run`,\n errForSentry: `Unexpected arguments for --run: ${JSON.stringify(\n cmdOptions.run,\n )}`,\n });\n }\n }\n ran = true;\n }\n pushed = true;\n } catch (e: any) {\n // Crash the app on unexpected errors.\n if (!(e instanceof Crash) || !e.errorType) {\n // eslint-disable-next-line no-restricted-syntax\n throw e;\n }\n if (e.errorType === \"fatal\") {\n break;\n }\n // Retry after an exponential backoff if we hit a transient error.\n if (e.errorType === \"transient\" || e.errorType === \"already handled\") {\n const delay = nextBackoff(numFailures);\n numFailures += 1;\n if (e.errorType === \"transient\") {\n logWarning(\n chalkStderr.yellow(\n `Failed due to network error, retrying in ${formatDuration(\n delay,\n )}...`,\n ),\n );\n }\n await new Promise((resolve) => setTimeout(resolve, delay));\n continue;\n }\n\n // Fall through if we had a filesystem-based error.\n // TODO(sarah): Replace this with `logError`.\n // eslint-disable-next-line no-console\n console.assert(\n e.errorType === \"invalid filesystem data\" ||\n e.errorType === \"invalid filesystem or env vars\" ||\n e.errorType[\"invalid filesystem or db data\"] !== undefined,\n );\n if (e.errorType === \"invalid filesystem or env vars\") {\n shouldRetryOnDeploymentEnvVarChange = true;\n } else if (\n e.errorType !== \"invalid filesystem data\" &&\n e.errorType[\"invalid filesystem or db data\"] !== undefined\n ) {\n tableNameTriggeringRetry = e.errorType[\"invalid filesystem or db data\"];\n }\n if (cmdOptions.once) {\n await outerCtx.flushAndExit(1, e.errorType);\n }\n // Make sure that we don't spin if this push failed\n // in any edge cases that didn't call `logFailure`\n // before throwing.\n stopSpinner();\n }\n if (cmdOptions.once) {\n return;\n }\n if (pushed && cmdOptions.untilSuccess) {\n return;\n }\n const fileSystemWatch = getFileSystemWatch(ctx, watch, cmdOptions);\n const tableWatch = getTableWatch(\n ctx,\n options,\n tableNameTriggeringRetry?.tableName ?? null,\n tableNameTriggeringRetry?.componentPath,\n );\n const envVarWatch = getDeplymentEnvVarWatch(\n ctx,\n options,\n shouldRetryOnDeploymentEnvVarChange,\n );\n await Promise.race([\n fileSystemWatch.watch(),\n tableWatch.watch(),\n envVarWatch.watch(),\n ]);\n fileSystemWatch.stop();\n void tableWatch.stop();\n void envVarWatch.stop();\n }\n}\n\nasync function runFunctionInDev(\n ctx: WatchContext,\n credentials: {\n url: string;\n adminKey: string;\n },\n functionName: string,\n componentPath: string | undefined,\n) {\n await runFunctionAndLog(ctx, {\n deploymentUrl: credentials.url,\n adminKey: credentials.adminKey,\n functionName,\n argsString: \"{}\",\n componentPath,\n callbacks: {\n onSuccess: () => {\n logFinishedStep(`Finished running function \"${functionName}\"`);\n },\n },\n });\n}\n\nfunction getTableWatch(\n ctx: WatchContext,\n credentials: {\n url: string;\n adminKey: string;\n },\n tableName: string | null,\n componentPath: string | undefined,\n) {\n return getFunctionWatch(ctx, {\n deploymentUrl: credentials.url,\n adminKey: credentials.adminKey,\n parsedFunctionName: \"_system/cli/queryTable\",\n getArgs: () => (tableName !== null ? { tableName } : null),\n componentPath,\n });\n}\n\nfunction getDeplymentEnvVarWatch(\n ctx: WatchContext,\n credentials: {\n url: string;\n adminKey: string;\n },\n shouldRetryOnDeploymentEnvVarChange: boolean,\n) {\n return getFunctionWatch(ctx, {\n deploymentUrl: credentials.url,\n adminKey: credentials.adminKey,\n parsedFunctionName: \"_system/cli/queryEnvironmentVariables\",\n getArgs: () => (shouldRetryOnDeploymentEnvVarChange ? {} : null),\n componentPath: undefined,\n });\n}\n\nfunction getFunctionWatch(\n ctx: WatchContext,\n args: {\n deploymentUrl: string;\n adminKey: string;\n parsedFunctionName: string;\n getArgs: () => Record<string, Value> | null;\n componentPath: string | undefined;\n },\n) {\n const [stopPromise, stop] = waitUntilCalled();\n return {\n watch: async () => {\n const functionArgs = args.getArgs();\n if (functionArgs === null) {\n return waitForever();\n }\n let changes = 0;\n return subscribe(ctx, {\n deploymentUrl: args.deploymentUrl,\n adminKey: args.adminKey,\n parsedFunctionName: args.parsedFunctionName,\n parsedFunctionArgs: functionArgs,\n componentPath: args.componentPath,\n until: stopPromise,\n callbacks: {\n onChange: () => {\n changes++;\n // First bump is just the initial results reporting\n if (changes > 1) {\n stop();\n }\n },\n },\n });\n },\n stop: () => {\n stop();\n },\n };\n}\n\nfunction getFileSystemWatch(\n ctx: WatchContext,\n watch: { watcher: Watcher | undefined },\n cmdOptions: { traceEvents: boolean },\n) {\n let hasStopped = false;\n return {\n watch: async () => {\n const observations = ctx.fs.finalize();\n if (observations === \"invalidated\") {\n logMessage(\"Filesystem changed during push, retrying...\");\n return;\n }\n // Initialize the watcher if we haven't done it already. Chokidar expects to have a\n // nonempty watch set at initialization, so we can't do it before running our first\n // push.\n if (!watch.watcher) {\n watch.watcher = new Watcher(observations);\n await showSpinnerIfSlow(\n \"Preparing to watch files...\",\n 500,\n async () => {\n await watch.watcher!.ready();\n },\n );\n stopSpinner();\n }\n // Watch new directories if needed.\n watch.watcher.update(observations);\n\n // Process events until we find one that overlaps with our previous observations.\n let anyChanges = false;\n do {\n await watch.watcher.waitForEvent();\n if (hasStopped) {\n return;\n }\n for (const event of watch.watcher.drainEvents()) {\n if (cmdOptions.traceEvents) {\n logMessage(\n \"Processing\",\n event.name,\n path.relative(\"\", event.absPath),\n );\n }\n const result = observations.overlaps(event);\n if (result.overlaps) {\n const relPath = path.relative(\"\", event.absPath);\n if (cmdOptions.traceEvents) {\n logMessage(`${relPath} ${result.reason}, rebuilding...`);\n }\n anyChanges = true;\n break;\n }\n }\n } while (!anyChanges);\n\n // Wait for the filesystem to quiesce before starting a new push. It's okay to\n // drop filesystem events at this stage since we're already committed to doing\n // a push and resubscribing based on that push's observations.\n let deadline = performance.now() + quiescenceDelay;\n while (true) {\n const now = performance.now();\n if (now >= deadline) {\n break;\n }\n const remaining = deadline - now;\n if (cmdOptions.traceEvents) {\n logMessage(`Waiting for ${formatDuration(remaining)} to quiesce...`);\n }\n const remainingWait = new Promise<\"timeout\">((resolve) =>\n setTimeout(() => resolve(\"timeout\"), deadline - now),\n );\n const result = await Promise.race([\n remainingWait,\n watch.watcher.waitForEvent().then<\"newEvents\">(() => \"newEvents\"),\n ]);\n if (result === \"newEvents\") {\n for (const event of watch.watcher.drainEvents()) {\n const result = observations.overlaps(event);\n // Delay another `quiescenceDelay` since we had an overlapping event.\n if (result.overlaps) {\n if (cmdOptions.traceEvents) {\n logMessage(\n `Received an overlapping event at ${event.absPath}, delaying push.`,\n );\n }\n deadline = performance.now() + quiescenceDelay;\n }\n }\n } else {\n // Let the check above `break` from the loop if we're past our deadlne.\n if (result !== \"timeout\") {\n logError(\n \"Assertion failed: Unexpected result from watcher: \" + result,\n );\n }\n }\n }\n },\n stop: () => {\n hasStopped = true;\n },\n };\n}\n\nconst initialBackoff = 500;\nconst maxBackoff = 16000;\nconst quiescenceDelay = 500;\n\nexport function nextBackoff(prevFailures: number): number {\n const baseBackoff = initialBackoff * Math.pow(2, prevFailures);\n const actualBackoff = Math.min(baseBackoff, maxBackoff);\n const jitter = actualBackoff * (Math.random() - 0.5);\n return actualBackoff + jitter;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["path", "result"]
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/cli/lib/mcp/tools/index.ts"],
|
|
4
|
-
"sourcesContent": ["import {
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["import { Tool } from \"@modelcontextprotocol/sdk/types\";\nimport { RequestContext } from \"../requestContext.js\";\nimport { ZodTypeAny, z } from \"zod\";\nimport zodToJsonSchema from \"zod-to-json-schema\";\nimport { TablesTool } from \"./tables.js\";\nimport { DataTool } from \"./data.js\";\nimport { StatusTool } from \"./status.js\";\nimport { FunctionSpecTool } from \"./functionSpec.js\";\nimport { RunTool } from \"./run.js\";\nimport { EnvListTool, EnvGetTool, EnvSetTool, EnvRemoveTool } from \"./env.js\";\nimport { RunOneoffQueryTool } from \"./runOneoffQuery.js\";\nimport { LogsTool } from \"./logs.js\";\n\nexport type ConvexTool<Input extends ZodTypeAny, Output extends ZodTypeAny> = {\n name: string;\n description: string;\n inputSchema: Input;\n outputSchema: Output;\n handler: (\n ctx: RequestContext,\n input: z.infer<Input>,\n ) => Promise<z.infer<Output>>;\n};\n\ntype ToolInput = Tool[\"inputSchema\"];\n\nexport function mcpTool(tool: ConvexTool<ZodTypeAny, ZodTypeAny>): Tool {\n return {\n name: tool.name,\n description: tool.description,\n inputSchema: zodToJsonSchema(tool.inputSchema) as ToolInput,\n };\n}\n\nexport const convexTools: ConvexTool<any, any>[] = [\n StatusTool,\n DataTool,\n TablesTool,\n FunctionSpecTool,\n RunTool,\n EnvListTool,\n EnvGetTool,\n EnvSetTool,\n EnvRemoveTool,\n RunOneoffQueryTool,\n LogsTool,\n];\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,gCAA4B;AAC5B,oBAA2B;AAC3B,kBAAyB;AACzB,oBAA2B;AAC3B,0BAAiC;AACjC,iBAAwB;AACxB,iBAAmE;AACnE,4BAAmC;AACnC,kBAAyB;AAelB,SAAS,QAAQ,MAAgD;AACtE,SAAO;AAAA,IACL,MAAM,KAAK;AAAA,IACX,aAAa,KAAK;AAAA,IAClB,iBAAa,0BAAAA,SAAgB,KAAK,WAAW;AAAA,EAC/C;AACF;AAEO,MAAM,cAAsC;AAAA,EACjD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;",
|
|
6
6
|
"names": ["zodToJsonSchema"]
|
|
7
7
|
}
|
|
@@ -116,7 +116,7 @@ const promptYesNo = async (ctx, options) => {
|
|
|
116
116
|
return ctx.crash({
|
|
117
117
|
exitCode: 1,
|
|
118
118
|
errorType: "fatal",
|
|
119
|
-
printedMessage: `Cannot prompt for input in non-interactive terminals. (${options.message})`
|
|
119
|
+
printedMessage: options.nonInteractiveError ?? `Cannot prompt for input in non-interactive terminals. (${options.message})`
|
|
120
120
|
});
|
|
121
121
|
}
|
|
122
122
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/cli/lib/utils/prompts.ts"],
|
|
4
|
-
"sourcesContent": ["import inquirer from \"inquirer\";\nimport { Context } from \"../../../bundler/context.js\";\nimport { logOutput } from \"../../../bundler/log.js\";\nexport const promptString = async (\n ctx: Context,\n options: {\n message: string;\n default?: string;\n },\n): Promise<string> => {\n if (process.stdin.isTTY) {\n const result = (\n await inquirer.prompt([\n {\n type: \"input\",\n name: \"result\",\n message: options.message,\n default: options.default,\n },\n ])\n ).result;\n return result;\n } else {\n return ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: `Cannot prompt for input in non-interactive terminals. (${options.message})`,\n });\n }\n};\n\nexport const promptOptions = async <V>(\n ctx: Context,\n options: {\n message: string;\n choices: Array<{ name: string; value: V }>;\n default?: V;\n prefix?: string;\n suffix?: string;\n },\n): Promise<V> => {\n if (process.stdin.isTTY) {\n const result = (\n await inquirer.prompt([\n {\n // In the Convex mono-repo, `list` seems to cause the command to not\n // respond to CTRL+C while `search-list` does not.\n type: process.env.CONVEX_RUNNING_LIVE_IN_MONOREPO\n ? \"search-list\"\n : \"list\",\n name: \"result\",\n message: options.message,\n ...(options.prefix ? { prefix: options.prefix } : {}),\n ...(options.suffix ? { suffix: options.suffix } : {}),\n choices: options.choices,\n default: options.default,\n },\n ])\n ).result;\n return result;\n } else {\n return ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: `Cannot prompt for input in non-interactive terminals. (${options.message})`,\n });\n }\n};\n\nexport const promptSearch = async <V>(\n ctx: Context,\n options: {\n message: string;\n choices: Array<{ name: string; value: V }>;\n default?: V;\n },\n): Promise<V> => {\n if (process.stdin.isTTY) {\n const result = (\n await inquirer.prompt([\n {\n type: \"search-list\",\n name: \"result\",\n message: options.message,\n choices: options.choices,\n default: options.default,\n },\n ])\n ).result;\n return result;\n } else {\n return ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: `Cannot prompt for input in non-interactive terminals. (${options.message})`,\n });\n }\n};\n\nexport const promptYesNo = async (\n ctx: Context,\n options: {\n message: string;\n default?: boolean;\n prefix?: string;\n },\n): Promise<boolean> => {\n if (process.stdin.isTTY) {\n const { result } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"result\",\n message: options.message,\n default: options.default,\n ...(options.prefix ? { prefix: options.prefix } : {}),\n },\n ]);\n return result;\n } else {\n logOutput(options.message);\n return ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAqB;AAErB,iBAA0B;AACnB,MAAM,eAAe,OAC1B,KACA,YAIoB;AACpB,MAAI,QAAQ,MAAM,OAAO;AACvB,UAAM,UACJ,MAAM,gBAAAA,QAAS,OAAO;AAAA,MACpB;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,QAAQ;AAAA,QACjB,SAAS,QAAQ;AAAA,MACnB;AAAA,IACF,CAAC,GACD;AACF,WAAO;AAAA,EACT,OAAO;AACL,WAAO,IAAI,MAAM;AAAA,MACf,UAAU;AAAA,MACV,WAAW;AAAA,MACX,gBAAgB,0DAA0D,QAAQ,OAAO;AAAA,IAC3F,CAAC;AAAA,EACH;AACF;AAEO,MAAM,gBAAgB,OAC3B,KACA,YAOe;AACf,MAAI,QAAQ,MAAM,OAAO;AACvB,UAAM,UACJ,MAAM,gBAAAA,QAAS,OAAO;AAAA,MACpB;AAAA;AAAA;AAAA,QAGE,MAAM,QAAQ,IAAI,kCACd,gBACA;AAAA,QACJ,MAAM;AAAA,QACN,SAAS,QAAQ;AAAA,QACjB,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,QACnD,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,QACnD,SAAS,QAAQ;AAAA,QACjB,SAAS,QAAQ;AAAA,MACnB;AAAA,IACF,CAAC,GACD;AACF,WAAO;AAAA,EACT,OAAO;AACL,WAAO,IAAI,MAAM;AAAA,MACf,UAAU;AAAA,MACV,WAAW;AAAA,MACX,gBAAgB,0DAA0D,QAAQ,OAAO;AAAA,IAC3F,CAAC;AAAA,EACH;AACF;AAEO,MAAM,eAAe,OAC1B,KACA,YAKe;AACf,MAAI,QAAQ,MAAM,OAAO;AACvB,UAAM,UACJ,MAAM,gBAAAA,QAAS,OAAO;AAAA,MACpB;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,QAAQ;AAAA,QACjB,SAAS,QAAQ;AAAA,QACjB,SAAS,QAAQ;AAAA,MACnB;AAAA,IACF,CAAC,GACD;AACF,WAAO;AAAA,EACT,OAAO;AACL,WAAO,IAAI,MAAM;AAAA,MACf,UAAU;AAAA,MACV,WAAW;AAAA,MACX,gBAAgB,0DAA0D,QAAQ,OAAO;AAAA,IAC3F,CAAC;AAAA,EACH;AACF;AAEO,MAAM,cAAc,OACzB,KACA,
|
|
4
|
+
"sourcesContent": ["import inquirer from \"inquirer\";\nimport { Context } from \"../../../bundler/context.js\";\nimport { logOutput } from \"../../../bundler/log.js\";\nexport const promptString = async (\n ctx: Context,\n options: {\n message: string;\n default?: string;\n },\n): Promise<string> => {\n if (process.stdin.isTTY) {\n const result = (\n await inquirer.prompt([\n {\n type: \"input\",\n name: \"result\",\n message: options.message,\n default: options.default,\n },\n ])\n ).result;\n return result;\n } else {\n return ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: `Cannot prompt for input in non-interactive terminals. (${options.message})`,\n });\n }\n};\n\nexport const promptOptions = async <V>(\n ctx: Context,\n options: {\n message: string;\n choices: Array<{ name: string; value: V }>;\n default?: V;\n prefix?: string;\n suffix?: string;\n },\n): Promise<V> => {\n if (process.stdin.isTTY) {\n const result = (\n await inquirer.prompt([\n {\n // In the Convex mono-repo, `list` seems to cause the command to not\n // respond to CTRL+C while `search-list` does not.\n type: process.env.CONVEX_RUNNING_LIVE_IN_MONOREPO\n ? \"search-list\"\n : \"list\",\n name: \"result\",\n message: options.message,\n ...(options.prefix ? { prefix: options.prefix } : {}),\n ...(options.suffix ? { suffix: options.suffix } : {}),\n choices: options.choices,\n default: options.default,\n },\n ])\n ).result;\n return result;\n } else {\n return ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: `Cannot prompt for input in non-interactive terminals. (${options.message})`,\n });\n }\n};\n\nexport const promptSearch = async <V>(\n ctx: Context,\n options: {\n message: string;\n choices: Array<{ name: string; value: V }>;\n default?: V;\n },\n): Promise<V> => {\n if (process.stdin.isTTY) {\n const result = (\n await inquirer.prompt([\n {\n type: \"search-list\",\n name: \"result\",\n message: options.message,\n choices: options.choices,\n default: options.default,\n },\n ])\n ).result;\n return result;\n } else {\n return ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: `Cannot prompt for input in non-interactive terminals. (${options.message})`,\n });\n }\n};\n\nexport const promptYesNo = async (\n ctx: Context,\n options: {\n message: string;\n default?: boolean;\n prefix?: string;\n nonInteractiveError?: string;\n },\n): Promise<boolean> => {\n if (process.stdin.isTTY) {\n const { result } = await inquirer.prompt([\n {\n type: \"confirm\",\n name: \"result\",\n message: options.message,\n default: options.default,\n ...(options.prefix ? { prefix: options.prefix } : {}),\n },\n ]);\n return result;\n } else {\n logOutput(options.message);\n return ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage:\n options.nonInteractiveError ??\n `Cannot prompt for input in non-interactive terminals. (${options.message})`,\n });\n }\n};\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAqB;AAErB,iBAA0B;AACnB,MAAM,eAAe,OAC1B,KACA,YAIoB;AACpB,MAAI,QAAQ,MAAM,OAAO;AACvB,UAAM,UACJ,MAAM,gBAAAA,QAAS,OAAO;AAAA,MACpB;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,QAAQ;AAAA,QACjB,SAAS,QAAQ;AAAA,MACnB;AAAA,IACF,CAAC,GACD;AACF,WAAO;AAAA,EACT,OAAO;AACL,WAAO,IAAI,MAAM;AAAA,MACf,UAAU;AAAA,MACV,WAAW;AAAA,MACX,gBAAgB,0DAA0D,QAAQ,OAAO;AAAA,IAC3F,CAAC;AAAA,EACH;AACF;AAEO,MAAM,gBAAgB,OAC3B,KACA,YAOe;AACf,MAAI,QAAQ,MAAM,OAAO;AACvB,UAAM,UACJ,MAAM,gBAAAA,QAAS,OAAO;AAAA,MACpB;AAAA;AAAA;AAAA,QAGE,MAAM,QAAQ,IAAI,kCACd,gBACA;AAAA,QACJ,MAAM;AAAA,QACN,SAAS,QAAQ;AAAA,QACjB,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,QACnD,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,QACnD,SAAS,QAAQ;AAAA,QACjB,SAAS,QAAQ;AAAA,MACnB;AAAA,IACF,CAAC,GACD;AACF,WAAO;AAAA,EACT,OAAO;AACL,WAAO,IAAI,MAAM;AAAA,MACf,UAAU;AAAA,MACV,WAAW;AAAA,MACX,gBAAgB,0DAA0D,QAAQ,OAAO;AAAA,IAC3F,CAAC;AAAA,EACH;AACF;AAEO,MAAM,eAAe,OAC1B,KACA,YAKe;AACf,MAAI,QAAQ,MAAM,OAAO;AACvB,UAAM,UACJ,MAAM,gBAAAA,QAAS,OAAO;AAAA,MACpB;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,QAAQ;AAAA,QACjB,SAAS,QAAQ;AAAA,QACjB,SAAS,QAAQ;AAAA,MACnB;AAAA,IACF,CAAC,GACD;AACF,WAAO;AAAA,EACT,OAAO;AACL,WAAO,IAAI,MAAM;AAAA,MACf,UAAU;AAAA,MACV,WAAW;AAAA,MACX,gBAAgB,0DAA0D,QAAQ,OAAO;AAAA,IAC3F,CAAC;AAAA,EACH;AACF;AAEO,MAAM,cAAc,OACzB,KACA,YAMqB;AACrB,MAAI,QAAQ,MAAM,OAAO;AACvB,UAAM,EAAE,OAAO,IAAI,MAAM,gBAAAA,QAAS,OAAO;AAAA,MACvC;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,QAAQ;AAAA,QACjB,SAAS,QAAQ;AAAA,QACjB,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,MACrD;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT,OAAO;AACL,8BAAU,QAAQ,OAAO;AACzB,WAAO,IAAI,MAAM;AAAA,MACf,UAAU;AAAA,MACV,WAAW;AAAA,MACX,gBACE,QAAQ,uBACR,0DAA0D,QAAQ,OAAO;AAAA,IAC7E,CAAC;AAAA,EACH;AACF;",
|
|
6
6
|
"names": ["inquirer"]
|
|
7
7
|
}
|
|
@@ -19,7 +19,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
19
19
|
var environmentApi_exports = {};
|
|
20
20
|
__export(environmentApi_exports, {
|
|
21
21
|
createCORSOrigin: () => createCORSOrigin,
|
|
22
|
-
createRedirectURI: () => createRedirectURI
|
|
22
|
+
createRedirectURI: () => createRedirectURI,
|
|
23
|
+
updateAppHomepageUrl: () => updateAppHomepageUrl
|
|
23
24
|
});
|
|
24
25
|
module.exports = __toCommonJS(environmentApi_exports);
|
|
25
26
|
async function createRedirectURI(ctx, apiKey, uri) {
|
|
@@ -50,6 +51,31 @@ async function createRedirectURI(ctx, apiKey, uri) {
|
|
|
50
51
|
}
|
|
51
52
|
return { modified: true };
|
|
52
53
|
}
|
|
54
|
+
async function updateAppHomepageUrl(ctx, apiKey, url) {
|
|
55
|
+
const response = await fetch(
|
|
56
|
+
"https://api.workos.com/user_management/app_homepage_url",
|
|
57
|
+
{
|
|
58
|
+
method: "PUT",
|
|
59
|
+
headers: {
|
|
60
|
+
"Content-Type": "application/json",
|
|
61
|
+
Authorization: `Bearer ${apiKey}`
|
|
62
|
+
},
|
|
63
|
+
body: JSON.stringify({ url })
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
if (!response.ok) {
|
|
67
|
+
const errorText = await response.text();
|
|
68
|
+
if (response.status === 422) {
|
|
69
|
+
return { modified: false };
|
|
70
|
+
}
|
|
71
|
+
return await ctx.crash({
|
|
72
|
+
exitCode: 1,
|
|
73
|
+
errorType: "fatal",
|
|
74
|
+
printedMessage: `Failed to update app homepage URL: ${response.status} ${errorText}`
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return { modified: true };
|
|
78
|
+
}
|
|
53
79
|
async function createCORSOrigin(ctx, apiKey, origin) {
|
|
54
80
|
const response = await fetch(
|
|
55
81
|
"https://api.workos.com/user_management/cors_origins",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/cli/lib/workos/environmentApi.ts"],
|
|
4
|
-
"sourcesContent": ["import { Context } from \"../../../bundler/context.js\";\n\nexport interface RedirectUriResponse {\n object: \"redirect_uri\";\n id: string;\n uri: string;\n default: boolean;\n created_at: string;\n updated_at: string;\n}\n\nexport interface CorsOriginResponse {\n object: \"cors_origin\";\n id: string;\n origin: string;\n created_at: string;\n updated_at: string;\n}\n\nexport async function createRedirectURI(\n ctx: Context,\n apiKey: string,\n uri: string,\n): Promise<{ modified: boolean }> {\n const response = await fetch(\n \"https://api.workos.com/user_management/redirect_uris\",\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({ uri }),\n },\n );\n\n if (!response.ok) {\n if (response.status === 422) {\n const errorText = await response.text();\n if (errorText.includes(\"already exists\")) {\n // This redirect URI already exists.\n return { modified: false };\n }\n }\n\n const errorText = await response.text();\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: `Failed to create redirect URI: ${response.status} ${errorText}`,\n });\n }\n return { modified: true };\n}\n\nexport async function createCORSOrigin(\n ctx: Context,\n apiKey: string,\n origin: string,\n): Promise<{ modified: boolean }> {\n const response = await fetch(\n \"https://api.workos.com/user_management/cors_origins\",\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({ origin }),\n },\n );\n\n if (!response.ok) {\n if (response.status === 409) {\n const errorText = await response.text();\n if (\n errorText.includes(\"duplicate_cors_origin\") ||\n errorText.includes(\"already exists\")\n ) {\n // This CORS origin already exists.\n return { modified: false };\n }\n }\n\n const errorText = await response.text();\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: `Failed to create CORS origin: ${response.status} ${errorText}`,\n });\n }\n return { modified: true };\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmBA,eAAsB,kBACpB,KACA,QACA,KACgC;AAChC,QAAM,WAAW,MAAM;AAAA,IACrB;AAAA,IACA;AAAA,MACE,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,eAAe,UAAU,MAAM;AAAA,MACjC;AAAA,MACA,MAAM,KAAK,UAAU,EAAE,IAAI,CAAC;AAAA,IAC9B;AAAA,EACF;AAEA,MAAI,CAAC,SAAS,IAAI;AAChB,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAMA,aAAY,MAAM,SAAS,KAAK;AACtC,UAAIA,WAAU,SAAS,gBAAgB,GAAG;AAExC,eAAO,EAAE,UAAU,MAAM;AAAA,MAC3B;AAAA,IACF;AAEA,UAAM,YAAY,MAAM,SAAS,KAAK;AACtC,WAAO,MAAM,IAAI,MAAM;AAAA,MACrB,UAAU;AAAA,MACV,WAAW;AAAA,MACX,gBAAgB,kCAAkC,SAAS,MAAM,IAAI,SAAS;AAAA,IAChF,CAAC;AAAA,EACH;
|
|
4
|
+
"sourcesContent": ["import { Context } from \"../../../bundler/context.js\";\n\nexport interface RedirectUriResponse {\n object: \"redirect_uri\";\n id: string;\n uri: string;\n default: boolean;\n created_at: string;\n updated_at: string;\n}\n\nexport interface CorsOriginResponse {\n object: \"cors_origin\";\n id: string;\n origin: string;\n created_at: string;\n updated_at: string;\n}\n\nexport async function createRedirectURI(\n ctx: Context,\n apiKey: string,\n uri: string,\n): Promise<{ modified: boolean }> {\n const response = await fetch(\n \"https://api.workos.com/user_management/redirect_uris\",\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({ uri }),\n },\n );\n\n if (!response.ok) {\n if (response.status === 422) {\n const errorText = await response.text();\n if (errorText.includes(\"already exists\")) {\n // This redirect URI already exists.\n return { modified: false };\n }\n }\n\n const errorText = await response.text();\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: `Failed to create redirect URI: ${response.status} ${errorText}`,\n });\n }\n\n return { modified: true };\n}\n\nexport async function updateAppHomepageUrl(\n ctx: Context,\n apiKey: string,\n url: string,\n): Promise<{ modified: boolean; previousUrl?: string }> {\n const response = await fetch(\n \"https://api.workos.com/user_management/app_homepage_url\",\n {\n method: \"PUT\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({ url }),\n },\n );\n\n if (!response.ok) {\n const errorText = await response.text();\n\n if (response.status === 422) {\n // Validation error - likely localhost URL or other invalid format\n // Don't crash, just return that we couldn't modify it\n return { modified: false };\n }\n\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: `Failed to update app homepage URL: ${response.status} ${errorText}`,\n });\n }\n\n // Always returns modified: true since PUT always updates (or sets the same value)\n return { modified: true };\n}\n\nexport async function createCORSOrigin(\n ctx: Context,\n apiKey: string,\n origin: string,\n): Promise<{ modified: boolean }> {\n const response = await fetch(\n \"https://api.workos.com/user_management/cors_origins\",\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({ origin }),\n },\n );\n\n if (!response.ok) {\n if (response.status === 409) {\n const errorText = await response.text();\n if (\n errorText.includes(\"duplicate_cors_origin\") ||\n errorText.includes(\"already exists\")\n ) {\n // This CORS origin already exists.\n return { modified: false };\n }\n }\n\n const errorText = await response.text();\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: `Failed to create CORS origin: ${response.status} ${errorText}`,\n });\n }\n return { modified: true };\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAmBA,eAAsB,kBACpB,KACA,QACA,KACgC;AAChC,QAAM,WAAW,MAAM;AAAA,IACrB;AAAA,IACA;AAAA,MACE,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,eAAe,UAAU,MAAM;AAAA,MACjC;AAAA,MACA,MAAM,KAAK,UAAU,EAAE,IAAI,CAAC;AAAA,IAC9B;AAAA,EACF;AAEA,MAAI,CAAC,SAAS,IAAI;AAChB,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAMA,aAAY,MAAM,SAAS,KAAK;AACtC,UAAIA,WAAU,SAAS,gBAAgB,GAAG;AAExC,eAAO,EAAE,UAAU,MAAM;AAAA,MAC3B;AAAA,IACF;AAEA,UAAM,YAAY,MAAM,SAAS,KAAK;AACtC,WAAO,MAAM,IAAI,MAAM;AAAA,MACrB,UAAU;AAAA,MACV,WAAW;AAAA,MACX,gBAAgB,kCAAkC,SAAS,MAAM,IAAI,SAAS;AAAA,IAChF,CAAC;AAAA,EACH;AAEA,SAAO,EAAE,UAAU,KAAK;AAC1B;AAEA,eAAsB,qBACpB,KACA,QACA,KACsD;AACtD,QAAM,WAAW,MAAM;AAAA,IACrB;AAAA,IACA;AAAA,MACE,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,eAAe,UAAU,MAAM;AAAA,MACjC;AAAA,MACA,MAAM,KAAK,UAAU,EAAE,IAAI,CAAC;AAAA,IAC9B;AAAA,EACF;AAEA,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,YAAY,MAAM,SAAS,KAAK;AAEtC,QAAI,SAAS,WAAW,KAAK;AAG3B,aAAO,EAAE,UAAU,MAAM;AAAA,IAC3B;AAEA,WAAO,MAAM,IAAI,MAAM;AAAA,MACrB,UAAU;AAAA,MACV,WAAW;AAAA,MACX,gBAAgB,sCAAsC,SAAS,MAAM,IAAI,SAAS;AAAA,IACpF,CAAC;AAAA,EACH;AAGA,SAAO,EAAE,UAAU,KAAK;AAC1B;AAEA,eAAsB,iBACpB,KACA,QACA,QACgC;AAChC,QAAM,WAAW,MAAM;AAAA,IACrB;AAAA,IACA;AAAA,MACE,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,eAAe,UAAU,MAAM;AAAA,MACjC;AAAA,MACA,MAAM,KAAK,UAAU,EAAE,OAAO,CAAC;AAAA,IACjC;AAAA,EACF;AAEA,MAAI,CAAC,SAAS,IAAI;AAChB,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAMA,aAAY,MAAM,SAAS,KAAK;AACtC,UACEA,WAAU,SAAS,uBAAuB,KAC1CA,WAAU,SAAS,gBAAgB,GACnC;AAEA,eAAO,EAAE,UAAU,MAAM;AAAA,MAC3B;AAAA,IACF;AAEA,UAAM,YAAY,MAAM,SAAS,KAAK;AACtC,WAAO,MAAM,IAAI,MAAM;AAAA,MACrB,UAAU;AAAA,MACV,WAAW;AAAA,MACX,gBAAgB,iCAAiC,SAAS,MAAM,IAAI,SAAS;AAAA,IAC/E,CAAC;AAAA,EACH;AACA,SAAO,EAAE,UAAU,KAAK;AAC1B;",
|
|
6
6
|
"names": ["errorText"]
|
|
7
7
|
}
|
|
@@ -20,13 +20,17 @@ var platformApi_exports = {};
|
|
|
20
20
|
__export(platformApi_exports, {
|
|
21
21
|
createAssociatedWorkosTeam: () => createAssociatedWorkosTeam,
|
|
22
22
|
createEnvironmentAndAPIKey: () => createEnvironmentAndAPIKey,
|
|
23
|
+
createProjectWorkOSEnvironment: () => createProjectWorkOSEnvironment,
|
|
24
|
+
deleteProjectWorkOSEnvironment: () => deleteProjectWorkOSEnvironment,
|
|
23
25
|
disconnectWorkOSTeam: () => disconnectWorkOSTeam,
|
|
24
26
|
getCandidateEmailsForWorkIntegration: () => getCandidateEmailsForWorkIntegration,
|
|
25
27
|
getDeploymentCanProvisionWorkOSEnvironments: () => getDeploymentCanProvisionWorkOSEnvironments,
|
|
26
28
|
getInvitationEligibleEmails: () => getInvitationEligibleEmails,
|
|
29
|
+
getProjectWorkOSEnvironment: () => getProjectWorkOSEnvironment,
|
|
27
30
|
getWorkosEnvironmentHealth: () => getWorkosEnvironmentHealth,
|
|
28
31
|
getWorkosTeamHealth: () => getWorkosTeamHealth,
|
|
29
|
-
inviteToWorkosTeam: () => inviteToWorkosTeam
|
|
32
|
+
inviteToWorkosTeam: () => inviteToWorkosTeam,
|
|
33
|
+
listProjectWorkOSEnvironments: () => listProjectWorkOSEnvironments
|
|
30
34
|
});
|
|
31
35
|
module.exports = __toCommonJS(platformApi_exports);
|
|
32
36
|
var import_utils = require("../utils/utils.js");
|
|
@@ -55,17 +59,16 @@ async function getDeploymentCanProvisionWorkOSEnvironments(ctx, deploymentName)
|
|
|
55
59
|
data: request
|
|
56
60
|
});
|
|
57
61
|
}
|
|
58
|
-
async function createEnvironmentAndAPIKey(ctx, deploymentName,
|
|
62
|
+
async function createEnvironmentAndAPIKey(ctx, deploymentName, environmentType) {
|
|
59
63
|
try {
|
|
60
|
-
const request = {
|
|
61
|
-
deploymentName,
|
|
62
|
-
environmentName: environmentName ?? null
|
|
63
|
-
};
|
|
64
64
|
const data = await (0, import_utils.bigBrainAPI)({
|
|
65
65
|
ctx,
|
|
66
66
|
method: "POST",
|
|
67
67
|
url: "workos/get_or_provision_workos_environment",
|
|
68
|
-
data:
|
|
68
|
+
data: {
|
|
69
|
+
deploymentName,
|
|
70
|
+
environmentType
|
|
71
|
+
}
|
|
69
72
|
});
|
|
70
73
|
return {
|
|
71
74
|
success: true,
|
|
@@ -205,4 +208,35 @@ async function inviteToWorkosTeam(ctx, teamId, email) {
|
|
|
205
208
|
return await (0, import_utils.logAndHandleFetchError)(ctx, error);
|
|
206
209
|
}
|
|
207
210
|
}
|
|
211
|
+
async function listProjectWorkOSEnvironments(ctx, projectId) {
|
|
212
|
+
const response = await (0, import_utils.bigBrainAPI)({
|
|
213
|
+
ctx,
|
|
214
|
+
method: "GET",
|
|
215
|
+
url: `projects/${projectId}/workos_environments`
|
|
216
|
+
});
|
|
217
|
+
return response.environments;
|
|
218
|
+
}
|
|
219
|
+
async function createProjectWorkOSEnvironment(ctx, projectId, environmentName, isProduction) {
|
|
220
|
+
return (0, import_utils.bigBrainAPI)({
|
|
221
|
+
ctx,
|
|
222
|
+
method: "POST",
|
|
223
|
+
url: `projects/${projectId}/workos_environments`,
|
|
224
|
+
data: { environmentName, isProduction }
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
async function getProjectWorkOSEnvironment(ctx, projectId, clientId) {
|
|
228
|
+
return (0, import_utils.bigBrainAPI)({
|
|
229
|
+
ctx,
|
|
230
|
+
method: "GET",
|
|
231
|
+
url: `projects/${projectId}/workos_environments/${clientId}`
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
async function deleteProjectWorkOSEnvironment(ctx, projectId, clientId) {
|
|
235
|
+
return (0, import_utils.bigBrainAPI)({
|
|
236
|
+
ctx,
|
|
237
|
+
method: "POST",
|
|
238
|
+
url: "workos/delete_project_environment",
|
|
239
|
+
data: { projectId, clientId }
|
|
240
|
+
});
|
|
241
|
+
}
|
|
208
242
|
//# sourceMappingURL=platformApi.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/cli/lib/workos/platformApi.ts"],
|
|
4
|
-
"sourcesContent": ["import { Context } from \"../../../bundler/context.js\";\nimport {\n bigBrainAPI,\n bigBrainAPIMaybeThrows,\n ErrorData,\n logAndHandleFetchError,\n ThrowingFetchError,\n} from \"../utils/utils.js\";\nimport { components } from \"../../generatedApi.js\";\n\n/**\n * Verified emails for a user that aren't known to be an admin email for\n * another WorkOS integration.\n */\nexport async function getCandidateEmailsForWorkIntegration(\n ctx: Context,\n): Promise<components[\"schemas\"][\"AvailableWorkOSTeamEmailsResponse\"]> {\n return bigBrainAPI<\n components[\"schemas\"][\"AvailableWorkOSTeamEmailsResponse\"]\n >({\n ctx,\n method: \"GET\",\n url: \"workos/available_workos_team_emails\",\n });\n}\n\nexport async function getInvitationEligibleEmails(\n ctx: Context,\n teamId: number,\n): Promise<{\n eligibleEmails: string[];\n adminEmail?: string;\n}> {\n return bigBrainAPI<{ eligibleEmails: string[]; adminEmail?: string }>({\n ctx,\n method: \"GET\",\n url: `teams/${teamId}/workos_invitation_eligible_emails`,\n });\n}\n\nexport async function getDeploymentCanProvisionWorkOSEnvironments(\n ctx: Context,\n deploymentName: string,\n): Promise<components[\"schemas\"][\"HasAssociatedWorkOSTeamResponse\"]> {\n const request: components[\"schemas\"][\"HasAssociatedWorkOSTeamRequest\"] = {\n deploymentName,\n };\n return bigBrainAPI<components[\"schemas\"][\"HasAssociatedWorkOSTeamResponse\"]>({\n ctx,\n method: \"POST\",\n url: \"workos/has_associated_workos_team\",\n data: request,\n });\n}\n\nexport async function createEnvironmentAndAPIKey(\n ctx: Context,\n deploymentName: string,\n environmentName?: string,\n): Promise<\n | {\n success: true;\n data: components[\"schemas\"][\"ProvisionEnvironmentResponse\"];\n }\n | {\n success: false;\n error: \"team_not_provisioned\";\n message: string;\n }\n> {\n try {\n const request: components[\"schemas\"][\"GetOrProvisionEnvironmentRequest\"] = {\n deploymentName,\n environmentName: environmentName ?? null,\n };\n const data = await bigBrainAPI<\n components[\"schemas\"][\"ProvisionEnvironmentResponse\"]\n >({\n ctx,\n method: \"POST\",\n url: \"workos/get_or_provision_workos_environment\",\n data: request,\n });\n return {\n success: true,\n data,\n };\n } catch (error: any) {\n if (error?.message?.includes(\"WorkOSTeamNotProvisioned\")) {\n return {\n success: false,\n error: \"team_not_provisioned\",\n message: error.message,\n };\n }\n\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: `Error provisioning WorkOS environment: ${error}`,\n });\n }\n}\n\nexport async function createAssociatedWorkosTeam(\n ctx: Context,\n teamId: number,\n email: string,\n): Promise<\n | {\n result: \"success\";\n workosTeamId: string;\n workosTeamName: string;\n }\n | {\n result: \"emailAlreadyUsed\";\n message: string;\n }\n> {\n try {\n const request: components[\"schemas\"][\"ProvisionWorkOSTeamRequest\"] = {\n teamId,\n email,\n };\n const result = (await bigBrainAPIMaybeThrows({\n ctx,\n method: \"POST\",\n url: \"workos/provision_associated_workos_team\",\n data: JSON.stringify(request),\n })) as components[\"schemas\"][\"ProvisionWorkOSTeamResponse\"];\n return {\n result: \"success\",\n ...result,\n };\n } catch (error) {\n const data: ErrorData | undefined =\n error instanceof ThrowingFetchError ? error.serverErrorData : undefined;\n if (data?.code === \"WorkosAccountAlreadyExistsWithThisEmail\") {\n return {\n result: \"emailAlreadyUsed\",\n message:\n data?.message || \"WorkOS account with this email already exists\",\n };\n }\n return await logAndHandleFetchError(ctx, error);\n }\n}\n\n/**\n * Check if the WorkOS team associated with a Convex team is still accessible.\n * Returns the team info if provisioned, or null if not provisioned.\n */\nexport async function getWorkosTeamHealth(\n ctx: Context,\n teamId: number,\n): Promise<components[\"schemas\"][\"WorkOSTeamInfo\"] | null> {\n const response = await bigBrainAPI<\n components[\"schemas\"][\"WorkOSTeamHealthResponse\"]\n >({\n ctx,\n method: \"GET\",\n url: `teams/${teamId}/workos_team_health`,\n });\n\n // Return the team info if provisioned, otherwise null\n return response.teamProvisioned ? (response.teamInfo ?? null) : null;\n}\n\n/**\n * Check if the WorkOS environment associated with a deployment is still accessible.\n * Returns null if the environment is not provisioned or cannot be accessed.\n */\nexport async function getWorkosEnvironmentHealth(\n ctx: Context,\n deploymentName: string,\n): Promise<components[\"schemas\"][\"WorkOSEnvironmentHealthResponse\"] | null> {\n try {\n return (await bigBrainAPIMaybeThrows({\n ctx,\n method: \"GET\",\n url: `deployments/${deploymentName}/workos_environment_health`,\n })) as components[\"schemas\"][\"WorkOSEnvironmentHealthResponse\"];\n } catch (error: any) {\n if (error?.serverErrorData?.code === \"WorkOSEnvironmentNotProvisioned\") {\n return null;\n }\n return await logAndHandleFetchError(ctx, error);\n }\n}\n\nexport async function disconnectWorkOSTeam(\n ctx: Context,\n teamId: number,\n): Promise<\n | {\n success: true;\n workosTeamId: string;\n workosTeamName: string;\n }\n | {\n success: false;\n error: \"not_associated\" | \"other\";\n message: string;\n }\n> {\n try {\n const request: components[\"schemas\"][\"DisconnectWorkOSTeamRequest\"] = {\n teamId,\n };\n const result = (await bigBrainAPIMaybeThrows({\n ctx,\n method: \"POST\",\n url: \"workos/disconnect_workos_team\",\n data: JSON.stringify(request),\n })) as components[\"schemas\"][\"DisconnectWorkOSTeamResponse\"];\n return {\n success: true,\n ...result,\n };\n } catch (error) {\n const data: ErrorData | undefined =\n error instanceof ThrowingFetchError ? error.serverErrorData : undefined;\n if (data?.code === \"WorkOSTeamNotAssociated\") {\n return {\n success: false,\n error: \"not_associated\",\n message: data?.message || \"No WorkOS team is associated\",\n };\n }\n return {\n success: false,\n error: \"other\",\n message:\n data?.message ||\n (error instanceof Error ? error.message : String(error)),\n };\n }\n}\n\nexport async function inviteToWorkosTeam(\n ctx: Context,\n teamId: number,\n email: string,\n): Promise<\n | {\n result: \"success\";\n email: string;\n roleSlug: string;\n }\n | {\n result: \"teamNotProvisioned\";\n message: string;\n }\n | {\n result: \"alreadyInWorkspace\";\n message: string;\n }\n> {\n try {\n const result = await bigBrainAPIMaybeThrows({\n ctx,\n method: \"POST\",\n url: \"workos/invite_team_member\",\n data: JSON.stringify({ teamId, email }),\n });\n return { result: \"success\", ...result };\n } catch (error) {\n const data: ErrorData | undefined =\n error instanceof ThrowingFetchError ? error.serverErrorData : undefined;\n if (data?.code === \"WorkOSTeamNotProvisioned\") {\n return {\n result: \"teamNotProvisioned\",\n message: data?.message || \"This team doesn't have a WorkOS team yet\",\n };\n }\n if (data?.code === \"WorkosUserAlreadyInWorkspace\") {\n return {\n result: \"alreadyInWorkspace\",\n message:\n data?.message ||\n \"This email is already a member of another WorkOS workspace\",\n };\n }\n if (data?.code === \"WorkosUserAlreadyInvited\") {\n return {\n result: \"alreadyInWorkspace\", // Reuse same result type for UI consistency\n message:\n data?.message ||\n \"This email has already been invited to the WorkOS team\",\n };\n }\n if (data?.code === \"WorkosUserAlreadyInThisTeam\") {\n return {\n result: \"alreadyInWorkspace\",\n message:\n data?.message || \"This email is already a member of this WorkOS team\",\n };\n }\n return await logAndHandleFetchError(ctx, error);\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAMO;
|
|
4
|
+
"sourcesContent": ["import { Context } from \"../../../bundler/context.js\";\nimport {\n bigBrainAPI,\n bigBrainAPIMaybeThrows,\n ErrorData,\n logAndHandleFetchError,\n ThrowingFetchError,\n} from \"../utils/utils.js\";\nimport { components } from \"../../generatedApi.js\";\n\n// Re-export generated types for convenience\nexport type ProjectEnvironmentSummary =\n components[\"schemas\"][\"ProjectEnvironmentSummary\"];\nexport type ProvisionProjectEnvironmentResponse =\n components[\"schemas\"][\"ProvisionProjectEnvironmentResponse\"];\nexport type GetProjectEnvironmentResponse =\n components[\"schemas\"][\"GetProjectEnvironmentResponse\"];\nexport type DeleteProjectEnvironmentResponse =\n components[\"schemas\"][\"DeleteProjectEnvironmentResponse\"];\n\n/**\n * Verified emails for a user that aren't known to be an admin email for\n * another WorkOS integration.\n */\nexport async function getCandidateEmailsForWorkIntegration(\n ctx: Context,\n): Promise<components[\"schemas\"][\"AvailableWorkOSTeamEmailsResponse\"]> {\n return bigBrainAPI<\n components[\"schemas\"][\"AvailableWorkOSTeamEmailsResponse\"]\n >({\n ctx,\n method: \"GET\",\n url: \"workos/available_workos_team_emails\",\n });\n}\n\nexport async function getInvitationEligibleEmails(\n ctx: Context,\n teamId: number,\n): Promise<{\n eligibleEmails: string[];\n adminEmail?: string;\n}> {\n return bigBrainAPI<{ eligibleEmails: string[]; adminEmail?: string }>({\n ctx,\n method: \"GET\",\n url: `teams/${teamId}/workos_invitation_eligible_emails`,\n });\n}\n\nexport async function getDeploymentCanProvisionWorkOSEnvironments(\n ctx: Context,\n deploymentName: string,\n): Promise<components[\"schemas\"][\"HasAssociatedWorkOSTeamResponse\"]> {\n const request: components[\"schemas\"][\"HasAssociatedWorkOSTeamRequest\"] = {\n deploymentName,\n };\n return bigBrainAPI<components[\"schemas\"][\"HasAssociatedWorkOSTeamResponse\"]>({\n ctx,\n method: \"POST\",\n url: \"workos/has_associated_workos_team\",\n data: request,\n });\n}\n\nexport async function createEnvironmentAndAPIKey(\n ctx: Context,\n deploymentName: string,\n environmentType?: \"production\" | \"nonproduction\",\n): Promise<\n | {\n success: true;\n data: components[\"schemas\"][\"ProvisionEnvironmentResponse\"];\n }\n | {\n success: false;\n error: \"team_not_provisioned\";\n message: string;\n }\n> {\n try {\n const data = await bigBrainAPI<\n components[\"schemas\"][\"ProvisionEnvironmentResponse\"]\n >({\n ctx,\n method: \"POST\",\n url: \"workos/get_or_provision_workos_environment\",\n data: {\n deploymentName,\n environmentType,\n },\n });\n return {\n success: true,\n data,\n };\n } catch (error: any) {\n if (error?.message?.includes(\"WorkOSTeamNotProvisioned\")) {\n return {\n success: false,\n error: \"team_not_provisioned\",\n message: error.message,\n };\n }\n\n return await ctx.crash({\n exitCode: 1,\n errorType: \"fatal\",\n printedMessage: `Error provisioning WorkOS environment: ${error}`,\n });\n }\n}\n\nexport async function createAssociatedWorkosTeam(\n ctx: Context,\n teamId: number,\n email: string,\n): Promise<\n | {\n result: \"success\";\n workosTeamId: string;\n workosTeamName: string;\n }\n | {\n result: \"emailAlreadyUsed\";\n message: string;\n }\n> {\n try {\n const request: components[\"schemas\"][\"ProvisionWorkOSTeamRequest\"] = {\n teamId,\n email,\n };\n const result = (await bigBrainAPIMaybeThrows({\n ctx,\n method: \"POST\",\n url: \"workos/provision_associated_workos_team\",\n data: JSON.stringify(request),\n })) as components[\"schemas\"][\"ProvisionWorkOSTeamResponse\"];\n return {\n result: \"success\",\n ...result,\n };\n } catch (error) {\n const data: ErrorData | undefined =\n error instanceof ThrowingFetchError ? error.serverErrorData : undefined;\n if (data?.code === \"WorkosAccountAlreadyExistsWithThisEmail\") {\n return {\n result: \"emailAlreadyUsed\",\n message:\n data?.message || \"WorkOS account with this email already exists\",\n };\n }\n return await logAndHandleFetchError(ctx, error);\n }\n}\n\n/**\n * Check if the WorkOS team associated with a Convex team is still accessible.\n * Returns the team info if provisioned, or null if not provisioned.\n */\nexport async function getWorkosTeamHealth(\n ctx: Context,\n teamId: number,\n): Promise<components[\"schemas\"][\"WorkOSTeamInfo\"] | null> {\n const response = await bigBrainAPI<\n components[\"schemas\"][\"WorkOSTeamHealthResponse\"]\n >({\n ctx,\n method: \"GET\",\n url: `teams/${teamId}/workos_team_health`,\n });\n\n // Return the team info if provisioned, otherwise null\n return response.teamProvisioned ? (response.teamInfo ?? null) : null;\n}\n\n/**\n * Check if the WorkOS environment associated with a deployment is still accessible.\n * Returns null if the environment is not provisioned or cannot be accessed.\n */\nexport async function getWorkosEnvironmentHealth(\n ctx: Context,\n deploymentName: string,\n): Promise<components[\"schemas\"][\"WorkOSEnvironmentHealthResponse\"] | null> {\n try {\n return (await bigBrainAPIMaybeThrows({\n ctx,\n method: \"GET\",\n url: `deployments/${deploymentName}/workos_environment_health`,\n })) as components[\"schemas\"][\"WorkOSEnvironmentHealthResponse\"];\n } catch (error: any) {\n if (error?.serverErrorData?.code === \"WorkOSEnvironmentNotProvisioned\") {\n return null;\n }\n return await logAndHandleFetchError(ctx, error);\n }\n}\n\nexport async function disconnectWorkOSTeam(\n ctx: Context,\n teamId: number,\n): Promise<\n | {\n success: true;\n workosTeamId: string;\n workosTeamName: string;\n }\n | {\n success: false;\n error: \"not_associated\" | \"other\";\n message: string;\n }\n> {\n try {\n const request: components[\"schemas\"][\"DisconnectWorkOSTeamRequest\"] = {\n teamId,\n };\n const result = (await bigBrainAPIMaybeThrows({\n ctx,\n method: \"POST\",\n url: \"workos/disconnect_workos_team\",\n data: JSON.stringify(request),\n })) as components[\"schemas\"][\"DisconnectWorkOSTeamResponse\"];\n return {\n success: true,\n ...result,\n };\n } catch (error) {\n const data: ErrorData | undefined =\n error instanceof ThrowingFetchError ? error.serverErrorData : undefined;\n if (data?.code === \"WorkOSTeamNotAssociated\") {\n return {\n success: false,\n error: \"not_associated\",\n message: data?.message || \"No WorkOS team is associated\",\n };\n }\n return {\n success: false,\n error: \"other\",\n message:\n data?.message ||\n (error instanceof Error ? error.message : String(error)),\n };\n }\n}\n\nexport async function inviteToWorkosTeam(\n ctx: Context,\n teamId: number,\n email: string,\n): Promise<\n | {\n result: \"success\";\n email: string;\n roleSlug: string;\n }\n | {\n result: \"teamNotProvisioned\";\n message: string;\n }\n | {\n result: \"alreadyInWorkspace\";\n message: string;\n }\n> {\n try {\n const result = await bigBrainAPIMaybeThrows({\n ctx,\n method: \"POST\",\n url: \"workos/invite_team_member\",\n data: JSON.stringify({ teamId, email }),\n });\n return { result: \"success\", ...result };\n } catch (error) {\n const data: ErrorData | undefined =\n error instanceof ThrowingFetchError ? error.serverErrorData : undefined;\n if (data?.code === \"WorkOSTeamNotProvisioned\") {\n return {\n result: \"teamNotProvisioned\",\n message: data?.message || \"This team doesn't have a WorkOS team yet\",\n };\n }\n if (data?.code === \"WorkosUserAlreadyInWorkspace\") {\n return {\n result: \"alreadyInWorkspace\",\n message:\n data?.message ||\n \"This email is already a member of another WorkOS workspace\",\n };\n }\n if (data?.code === \"WorkosUserAlreadyInvited\") {\n return {\n result: \"alreadyInWorkspace\", // Reuse same result type for UI consistency\n message:\n data?.message ||\n \"This email has already been invited to the WorkOS team\",\n };\n }\n if (data?.code === \"WorkosUserAlreadyInThisTeam\") {\n return {\n result: \"alreadyInWorkspace\",\n message:\n data?.message || \"This email is already a member of this WorkOS team\",\n };\n }\n return await logAndHandleFetchError(ctx, error);\n }\n}\n\n// Project environment API functions\nexport async function listProjectWorkOSEnvironments(\n ctx: Context,\n projectId: number,\n): Promise<ProjectEnvironmentSummary[]> {\n const response = await bigBrainAPI<\n components[\"schemas\"][\"GetProjectEnvironmentsResponse\"]\n >({\n ctx,\n method: \"GET\",\n url: `projects/${projectId}/workos_environments`,\n });\n return response.environments;\n}\n\nexport async function createProjectWorkOSEnvironment(\n ctx: Context,\n projectId: number,\n environmentName: string,\n isProduction?: boolean,\n): Promise<ProvisionProjectEnvironmentResponse> {\n return bigBrainAPI<ProvisionProjectEnvironmentResponse>({\n ctx,\n method: \"POST\",\n url: `projects/${projectId}/workos_environments`,\n data: { environmentName, isProduction },\n });\n}\n\nexport async function getProjectWorkOSEnvironment(\n ctx: Context,\n projectId: number,\n clientId: string,\n): Promise<GetProjectEnvironmentResponse> {\n return bigBrainAPI<GetProjectEnvironmentResponse>({\n ctx,\n method: \"GET\",\n url: `projects/${projectId}/workos_environments/${clientId}`,\n });\n}\n\nexport async function deleteProjectWorkOSEnvironment(\n ctx: Context,\n projectId: number,\n clientId: string,\n): Promise<DeleteProjectEnvironmentResponse> {\n return bigBrainAPI<DeleteProjectEnvironmentResponse>({\n ctx,\n method: \"POST\",\n url: \"workos/delete_project_environment\",\n data: { projectId, clientId },\n });\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|