From 012d819557e0323dfde72db226ab453a4162c1e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Sat, 28 Feb 2026 14:07:49 +0100 Subject: [PATCH] =?UTF-8?q?OAuth=20Client=20=E2=80=94=20Unified=20Applicat?= =?UTF-8?q?ionRegistration,=20OAuth=20server,=20and=20frontend=20(#18267)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Consolidates three separate PRs (#18260, #18261, #18262) into a single unified branch with all review feedback addressed: ### New features - **ApplicationRegistration entity** — server-level registration for OAuth apps with encrypted server variables - **OAuth 2.0 server** — authorization code, client credentials, refresh token grants with PKCE support - **OAuth discovery endpoint** — `.well-known/oauth-authorization-server` metadata - **Frontend UI** — app registration details page with credential management, redirect URI editing, and server variable configuration - **CLI integration** — `twenty dev` auto-registers apps and stores OAuth credentials locally - **Authorize consent screen** — OAuth consent page at `/authorize` showing requested scopes ### Review feedback addressed **Renames (PR #18260):** - `appRegistration` → `applicationRegistration` (entity, tables, files, imports, GraphQL types) - `appRegistrationVariable` → `applicationRegistrationVariable` - `clientId` → `oAuthClientId`, `clientSecretHash` → `oAuthClientSecretHash`, `redirectUris` → `oAuthRedirectUris`, `scopes` → `oAuthScopes` **Security fixes (PR #18261):** - Fixed redirect URI validation bypass when `oAuthRedirectUris` is an empty array - Fixed workspace isolation in `clientCredentialsGrant` — now uses `find()` with explicit handling for multiple installations - Added error logging in refresh token `catch` block instead of silently swallowing **Code quality (PR #18262):** - Split `VersionDistributionEntry` into its own file (one export per file) - Split GraphQL queries and mutations into individual files with a shared fragment - Removed unused `OAuth` entry from `AuthProviderEnum` - Added loading state to `handleRotateSecret` - Removed 27 narration-style comments from test files - Added proper guards (`PublicEndpointGuard`, `NoPermissionGuard`) to controllers and resolvers ## Test plan - [ ] Verify `twenty dev` registers an app and stores OAuth credentials - [ ] Test OAuth authorization code flow end-to-end (authorize → token → API call) - [ ] Test client credentials grant - [ ] Verify redirect URI validation rejects requests when no URIs are registered - [ ] Verify app registration detail page renders correctly - [ ] Test secret rotation with loading state - [ ] Verify server variable editing and saving - [ ] Run `npx nx database:reset twenty-server` to validate migration Closes #18260, #18261, #18262 Made with [Cursor](https://cursor.com) --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> --- npm-app-distribution-plan.md | 283 +++++ npm-app-distribution-plan.pdf | Bin 0 -> 194061 bytes .../src/utils/__tests__/app-template.spec.ts | 26 - .../src/generated-metadata/graphql.ts | 1023 +++++++++++++---- .../twenty-front/src/generated/graphql.ts | 44 +- .../modules/app/components/SettingsRoutes.tsx | 12 + .../availableSSOIdentityProvidersFragment.ts | 2 +- .../auth/graphql/mutations/authorizeApp.ts | 2 +- .../__tests__/useHandleResetPassword.test.ts | 4 +- .../auth/states/workspacePublicDataState.ts | 4 +- .../components/SettingsAdminTableCard.tsx | 12 +- .../applicationRegistrationFragment.ts | 19 + .../deleteApplicationRegistration.ts | 7 + ...tateApplicationRegistrationClientSecret.ts | 9 + .../updateApplicationRegistration.ts | 14 + .../updateApplicationRegistrationVariable.ts | 18 + .../findApplicationRegistrationByClientId.ts | 13 + .../findApplicationRegistrationStats.ts | 14 + .../findApplicationRegistrationVariables.ts | 20 + .../findManyApplicationRegistrations.ts | 12 + .../queries/findOneApplicationRegistration.ts | 12 + .../hooks/useSettingsNavigationItems.tsx | 4 +- ...entUserWorkspaceTwoFactorAuthentication.ts | 4 +- .../twenty-front/src/pages/auth/Authorize.tsx | 114 +- .../twenty-front/src/pages/auth/SignInUp.tsx | 4 +- .../__stories__/PasswordReset.stories.tsx | 2 +- ...SettingsApplicationRegistrationDetails.tsx | 626 ++++++++++ .../applications/SettingsApplications.tsx | 22 +- ...tionRegistrationClientSecretFamilyState.ts | 7 + .../tabs/SettingsApplicationsCreateTab.tsx | 68 -- .../tabs/SettingsApplicationsDeveloperTab.tsx | 118 ++ .../src/testing/mock-data/billing-plans.ts | 4 +- .../publicWorkspaceDataBySubdomain.ts | 2 +- .../src/testing/mock-data/users.ts | 6 +- .../app-dev/app-dev.integration.spec.ts | 12 +- .../app-dev/expected-manifest.ts | 12 + .../apps/rich-app/application.config.ts | 12 + .../app-dev/app-dev.integration.spec.ts | 12 +- .../utils/run-app-dev-in-process.util.ts | 18 +- .../integration/utils/setup-app-dev-mocks.ts | 17 + .../src/cli/commands/app/app-dev.ts | 4 + .../src/cli/utilities/api/api-service.ts | 140 ++- .../cli/utilities/config/config-service.ts | 2 + .../dev/orchestrator/dev-mode-orchestrator.ts | 11 + .../steps/register-app-orchestrator-step.ts | 120 ++ .../resolve-application-orchestrator-step.ts | 2 + ...7875868-create-application-registration.ts | 143 +++ .../admin-panel/admin-panel.resolver.ts | 12 +- .../admin-panel/admin-panel.service.ts | 4 +- ...bles.output.ts => config-variables.dto.ts} | 4 +- ...personate.output.ts => impersonate.dto.ts} | 4 +- .../admin-panel/dtos/user-lookup.dto.ts | 6 +- .../core-modules/api-key/api-key.resolver.ts | 8 +- .../api-key/controllers/api-key.controller.ts | 4 +- ...api-key.dto.ts => create-api-key.input.ts} | 0 ...et-api-key.dto.ts => get-api-key.input.ts} | 0 ...api-key.dto.ts => revoke-api-key.input.ts} | 0 ...api-key.dto.ts => update-api-key.input.ts} | 0 .../app-token/app-token.entity.ts | 2 +- .../__tests__/oauth-scopes.spec.ts | 25 + ...pplication-registration-variable.entity.ts | 74 ++ ...plication-registration-variable.service.ts | 165 +++ .../application-registration.entity.ts | 113 ++ .../application-registration.exception.ts | 45 + .../application-registration.module.ts | 46 + .../application-registration.resolver.ts | 181 +++ .../application-registration.service.ts | 264 +++++ .../constants/oauth-scopes.ts | 16 + .../controllers/oauth-discovery.controller.ts | 32 + .../controllers/oauth-token.controller.ts | 75 ++ .../application-registration-stats.dto.ts | 22 + ...application-registration-variable.input.ts | 37 + .../create-application-registration.dto.ts | 12 + .../create-application-registration.input.ts | 69 ++ .../dtos/oauth-token.input.ts | 37 + .../dtos/rotate-client-secret.dto.ts | 7 + ...application-registration-variable.input.ts | 39 + .../update-application-registration.input.ts | 81 ++ .../application-registration/oauth.service.ts | 395 +++++++ .../types/oauth-error-response.type.ts | 4 + .../types/oauth-token-response.type.ts | 7 + .../application/application-sync.module.ts | 2 + .../application/application.entity.ts | 12 + ...ion-entity-relation-properties.constant.ts | 1 + .../dtos/create-application.input.ts | 7 +- .../dtos/workspace-migration.dto.ts | 2 +- .../services/application-sync.service.ts | 72 +- .../services/marketplace.service.ts | 19 +- .../engine/core-modules/auth/auth.module.ts | 2 + .../core-modules/auth/auth.resolver.spec.ts | 5 - .../engine/core-modules/auth/auth.resolver.ts | 89 +- .../auth/dto/authorize-app.dto.ts | 4 +- ...lable-workspaces-and-access-tokens.dto.ts} | 6 +- ....output.ts => available-workspaces.dto.ts} | 0 .../auth/dto/email-password-reset-link.dto.ts | 4 +- .../auth/dto/exchange-auth-code.dto.ts | 4 +- .../auth/dto/exchange-auth-code.entity.ts | 15 - ...s => get-authorization-url-for-sso.dto.ts} | 4 +- .../auth/dto/invalidate-password.dto.ts | 4 +- .../core-modules/auth/dto/login-token.dto.ts | 4 +- .../dto/{sign-up.output.ts => sign-up.dto.ts} | 4 +- .../auth/dto/transient-token.dto.ts | 4 +- .../auth/dto/update-password.dto.ts | 4 +- .../core-modules/auth/dto/user-exists.dto.ts | 4 +- .../dto/validate-password-reset-token.dto.ts | 4 +- ...> verify-email-and-get-login-token.dto.ts} | 4 +- .../dto/workspace-invite-hash-valid.dto.ts | 4 +- .../auth/services/auth.service.spec.ts | 5 + .../auth/services/auth.service.ts | 75 +- .../auth/services/oauth.service.ts | 157 --- .../auth/services/reset-password.service.ts | 12 +- .../auth/strategies/jwt.auth.strategy.spec.ts | 22 +- .../auth/strategies/jwt.auth.strategy.ts | 87 +- .../application-token.service.spec.ts | 11 +- .../services/application-token.service.ts | 59 +- .../auth/utils/validate-redirect-uri.util.ts | 31 + .../core-modules/billing/billing.resolver.ts | 38 +- ...put.ts => billing-end-trial-period.dto.ts} | 4 +- ...s => billing-metered-product-usage.dto.ts} | 4 +- ...ing-plan.output.ts => billing-plan.dto.ts} | 4 +- ...g-price.output.ts => billing-price.dto.ts} | 4 +- ...ssion.output.ts => billing-session.dto.ts} | 4 +- ...ut.ts => billing-subscription-item.dto.ts} | 2 +- ...update.output.ts => billing-update.dto.ts} | 4 +- .../entities/billing-subscription.entity.ts | 2 +- .../billing/services/billing-usage.service.ts | 6 +- ...at-database-product-to-graphql-dto.util.ts | 4 +- .../client-config/client-config.entity.ts | 6 +- .../engine/core-modules/core-engine.module.ts | 2 + ...=> resend-email-verification-token.dto.ts} | 4 +- .../email-verification.resolver.ts | 6 +- .../dtos/emailing-domain.dto.ts | 2 +- .../emailing-domain.resolver.ts | 16 +- ...sult.output.ts => event-log-result.dto.ts} | 0 .../event-logs/event-logs.resolver.ts | 2 +- .../event-logs/event-logs.service.ts | 2 +- ...eature-flag-dto.ts => feature-flag.dto.ts} | 2 +- .../feature-flag/feature-flag.entity.ts | 8 +- .../feature-flag/feature-flag.module.ts | 10 +- .../services/feature-flag.service.ts | 2 +- .../file/dtos/file-with-sign-url.dto.ts | 2 +- .../resolvers/file-core-picture.resolver.ts | 10 +- .../services/file-core-picture.service.ts | 10 +- .../resolvers/file-workflow.resolver.ts | 6 +- .../services/file-workflow.service.ts | 4 +- .../resolvers/files-field.resolver.ts | 10 +- .../services/files-field.service.ts | 4 +- .../dtos/imap-smtp-caldav-connection.dto.ts | 14 +- .../impersonation/impersonation.resolver.ts | 6 +- .../engine/core-modules/lab/lab.resolver.ts | 2 +- .../logic-function-executor.service.ts | 12 +- .../marketplace/mocks/mock-manifest.json | 26 +- ...delete-sso.output.ts => delete-sso.dto.ts} | 4 +- .../{setup-sso.output.ts => edit-sso.dto.ts} | 4 +- ...utput.ts => find-available-SSO-IDP.dto.ts} | 4 +- .../{edit-sso.output.ts => setup-sso.dto.ts} | 4 +- .../engine/core-modules/sso/sso.resolver.ts | 22 +- .../twenty-config/config-variables.ts | 20 +- ...e-two-factor-authentication-method.dto.ts} | 4 +- ...-factor-authentication-provisioning.dto.ts | 7 + ...ctor-authentication-provisioning.output.ts | 7 - .../two-factor-authentication-method.dto.ts | 4 +- ...fy-two-factor-authentication-method.dto.ts | 7 + ...two-factor-authentication-method.output.ts | 7 - ...two-factor-authentication-method.entity.ts | 10 - .../two-factor-authentication.resolver.ts | 22 +- ...-factor-authentication-method.presenter.ts | 4 +- .../user-workspace/user-workspace.entity.ts | 6 +- .../user-workspace/user-workspace.service.ts | 2 +- .../engine/core-modules/user/user.resolver.ts | 2 +- ...ts => compute-step-output-schema.input.ts} | 0 ...eate-draft-from-workflow-version.input.ts} | 0 ... => create-workflow-version-edge.input.ts} | 0 ... => create-workflow-version-step.input.ts} | 2 +- ... => delete-workflow-version-step.input.ts} | 0 ... duplicate-workflow-version-step.input.ts} | 0 ...put.dto.ts => duplicate-workflow.input.ts} | 0 ...put.dto.ts => run-workflow-version.dto.ts} | 4 +- ...t.dto.ts => run-workflow-version.input.ts} | 0 ...input.dto.ts => submit-form-step.input.ts} | 0 ...output.dto.ts => test-http-request.dto.ts} | 4 +- ...nput.dto.ts => test-http-request.input.ts} | 0 ...o.ts => update-workflow-run-step.input.ts} | 0 ...te-workflow-step-position-update.input.ts} | 2 +- ...=> update-workflow-step-position.input.ts} | 0 ...pdate-workflow-version-positions.input.ts} | 2 +- ... => update-workflow-version-step.input.ts} | 0 ... update-workflow-version-trigger.input.ts} | 0 .../resolvers/workflow-builder.resolver.ts | 2 +- .../resolvers/workflow-trigger.resolver.ts | 6 +- .../workflow-version-edge.resolver.ts | 2 +- .../workflow-version-step.resolver.ts | 20 +- .../resolvers/workflow-version.resolver.ts | 6 +- ...ions.output.ts => send-invitations.dto.ts} | 4 +- .../services/workspace-invitation.service.ts | 4 +- .../workspace-invitation.resolver.ts | 8 +- ...output.ts => public-workspace-data.dto.ts} | 4 +- ...auth-bypass-providers-by-workspace.util.ts | 2 +- .../get-auth-providers-by-workspace.util.ts | 2 +- .../workspace/workspace.resolver.ts | 10 +- ...-to-flat-field-metadatas-to-create.spec.ts | 1 + ...-relation-flat-field-metadata-pair.spec.ts | 1 + ...-role-input-to-flat-role-to-create.util.ts | 2 +- ...ut-to-flat-role-to-update-or-throw.util.ts | 2 +- ...role-input.dto.ts => create-role.input.ts} | 0 ...role-input.dto.ts => update-role.input.ts} | 0 .../metadata-modules/role/role.resolver.ts | 4 +- .../metadata-modules/role/role.service.ts | 4 +- ...ta-output.dto.ts => bar-chart-data.dto.ts} | 6 +- .../{outputs => }/bar-chart-series.dto.ts | 0 .../line-chart-data-point.dto.ts | 0 ...a-output.dto.ts => line-chart-data.dto.ts} | 6 +- .../{outputs => }/line-chart-series.dto.ts | 2 +- .../{outputs => }/pie-chart-data-item.dto.ts | 0 ...ta-output.dto.ts => pie-chart-data.dto.ts} | 6 +- .../resolvers/bar-chart-data.resolver.ts | 6 +- .../resolvers/line-chart-data.resolver.ts | 6 +- .../resolvers/pie-chart-data.resolver.ts | 6 +- .../services/bar-chart-data.service.ts | 8 +- .../services/line-chart-data.service.ts | 8 +- .../services/pie-chart-data.service.ts | 6 +- ...version-step-creation.workspace-service.ts | 2 +- ...rsion-step-operations.workspace-service.ts | 2 +- ...workflow-version-step.workspace-service.ts | 2 +- .../workflow-version.workspace-service.ts | 2 +- .../create-workflow-version-step.tool.ts | 2 +- .../update-workflow-version-positions.tool.ts | 2 +- .../update-workflow-version-step.tool.ts | 2 +- .../update-workflow-version-trigger.tool.ts | 2 +- .../utils/sign-up-in-new-workspace.util.ts | 4 +- .../integration/graphql/utils/sign-up.util.ts | 4 +- .../failing-role-creation.integration-spec.ts | 2 +- .../failing-role-update.integration-spec.ts | 2 +- .../create-one-role-query-factory.util.ts | 2 +- .../update-one-role-query-factory.util.ts | 2 +- .../oauth/suites/oauth.integration-spec.ts | 630 ++++++++++ .../src/application/applicationType.ts | 22 +- .../twenty-shared/src/application/index.ts | 6 +- .../src/application/server-variables.type.ts | 7 + .../twenty-shared/src/types/SettingsPath.ts | 1 + .../src/utils/base64UrlEncode.ts | 7 + packages/twenty-shared/src/utils/index.ts | 1 + 242 files changed, 5717 insertions(+), 1100 deletions(-) create mode 100644 npm-app-distribution-plan.md create mode 100644 npm-app-distribution-plan.pdf create mode 100644 packages/twenty-front/src/modules/settings/application-registrations/graphql/fragments/applicationRegistrationFragment.ts create mode 100644 packages/twenty-front/src/modules/settings/application-registrations/graphql/mutations/deleteApplicationRegistration.ts create mode 100644 packages/twenty-front/src/modules/settings/application-registrations/graphql/mutations/rotateApplicationRegistrationClientSecret.ts create mode 100644 packages/twenty-front/src/modules/settings/application-registrations/graphql/mutations/updateApplicationRegistration.ts create mode 100644 packages/twenty-front/src/modules/settings/application-registrations/graphql/mutations/updateApplicationRegistrationVariable.ts create mode 100644 packages/twenty-front/src/modules/settings/application-registrations/graphql/queries/findApplicationRegistrationByClientId.ts create mode 100644 packages/twenty-front/src/modules/settings/application-registrations/graphql/queries/findApplicationRegistrationStats.ts create mode 100644 packages/twenty-front/src/modules/settings/application-registrations/graphql/queries/findApplicationRegistrationVariables.ts create mode 100644 packages/twenty-front/src/modules/settings/application-registrations/graphql/queries/findManyApplicationRegistrations.ts create mode 100644 packages/twenty-front/src/modules/settings/application-registrations/graphql/queries/findOneApplicationRegistration.ts create mode 100644 packages/twenty-front/src/pages/settings/applications/SettingsApplicationRegistrationDetails.tsx create mode 100644 packages/twenty-front/src/pages/settings/applications/states/applicationRegistrationClientSecretFamilyState.ts delete mode 100644 packages/twenty-front/src/pages/settings/applications/tabs/SettingsApplicationsCreateTab.tsx create mode 100644 packages/twenty-front/src/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab.tsx create mode 100644 packages/twenty-sdk/src/cli/utilities/dev/orchestrator/steps/register-app-orchestrator-step.ts create mode 100644 packages/twenty-server/src/database/typeorm/core/migrations/common/1772267875868-create-application-registration.ts rename packages/twenty-server/src/engine/core-modules/admin-panel/dtos/{config-variables.output.ts => config-variables.dto.ts} (77%) rename packages/twenty-server/src/engine/core-modules/admin-panel/dtos/{impersonate.output.ts => impersonate.dto.ts} (84%) rename packages/twenty-server/src/engine/core-modules/api-key/dtos/{create-api-key.dto.ts => create-api-key.input.ts} (100%) rename packages/twenty-server/src/engine/core-modules/api-key/dtos/{get-api-key.dto.ts => get-api-key.input.ts} (100%) rename packages/twenty-server/src/engine/core-modules/api-key/dtos/{revoke-api-key.dto.ts => revoke-api-key.input.ts} (100%) rename packages/twenty-server/src/engine/core-modules/api-key/dtos/{update-api-key.dto.ts => update-api-key.input.ts} (100%) create mode 100644 packages/twenty-server/src/engine/core-modules/application-registration/__tests__/oauth-scopes.spec.ts create mode 100644 packages/twenty-server/src/engine/core-modules/application-registration/application-registration-variable.entity.ts create mode 100644 packages/twenty-server/src/engine/core-modules/application-registration/application-registration-variable.service.ts create mode 100644 packages/twenty-server/src/engine/core-modules/application-registration/application-registration.entity.ts create mode 100644 packages/twenty-server/src/engine/core-modules/application-registration/application-registration.exception.ts create mode 100644 packages/twenty-server/src/engine/core-modules/application-registration/application-registration.module.ts create mode 100644 packages/twenty-server/src/engine/core-modules/application-registration/application-registration.resolver.ts create mode 100644 packages/twenty-server/src/engine/core-modules/application-registration/application-registration.service.ts create mode 100644 packages/twenty-server/src/engine/core-modules/application-registration/constants/oauth-scopes.ts create mode 100644 packages/twenty-server/src/engine/core-modules/application-registration/controllers/oauth-discovery.controller.ts create mode 100644 packages/twenty-server/src/engine/core-modules/application-registration/controllers/oauth-token.controller.ts create mode 100644 packages/twenty-server/src/engine/core-modules/application-registration/dtos/application-registration-stats.dto.ts create mode 100644 packages/twenty-server/src/engine/core-modules/application-registration/dtos/create-application-registration-variable.input.ts create mode 100644 packages/twenty-server/src/engine/core-modules/application-registration/dtos/create-application-registration.dto.ts create mode 100644 packages/twenty-server/src/engine/core-modules/application-registration/dtos/create-application-registration.input.ts create mode 100644 packages/twenty-server/src/engine/core-modules/application-registration/dtos/oauth-token.input.ts create mode 100644 packages/twenty-server/src/engine/core-modules/application-registration/dtos/rotate-client-secret.dto.ts create mode 100644 packages/twenty-server/src/engine/core-modules/application-registration/dtos/update-application-registration-variable.input.ts create mode 100644 packages/twenty-server/src/engine/core-modules/application-registration/dtos/update-application-registration.input.ts create mode 100644 packages/twenty-server/src/engine/core-modules/application-registration/oauth.service.ts create mode 100644 packages/twenty-server/src/engine/core-modules/application-registration/types/oauth-error-response.type.ts create mode 100644 packages/twenty-server/src/engine/core-modules/application-registration/types/oauth-token-response.type.ts rename packages/twenty-server/src/engine/core-modules/auth/dto/{available-workspaces-and-access-tokens.output.ts => available-workspaces-and-access-tokens.dto.ts} (69%) rename packages/twenty-server/src/engine/core-modules/auth/dto/{available-workspaces.output.ts => available-workspaces.dto.ts} (100%) delete mode 100644 packages/twenty-server/src/engine/core-modules/auth/dto/exchange-auth-code.entity.ts rename packages/twenty-server/src/engine/core-modules/auth/dto/{get-authorization-url-for-sso.output.ts => get-authorization-url-for-sso.dto.ts} (83%) rename packages/twenty-server/src/engine/core-modules/auth/dto/{sign-up.output.ts => sign-up.dto.ts} (85%) rename packages/twenty-server/src/engine/core-modules/auth/dto/{verify-email-and-get-login-token.output.ts => verify-email-and-get-login-token.dto.ts} (76%) delete mode 100644 packages/twenty-server/src/engine/core-modules/auth/services/oauth.service.ts create mode 100644 packages/twenty-server/src/engine/core-modules/auth/utils/validate-redirect-uri.util.ts rename packages/twenty-server/src/engine/core-modules/billing/dtos/{outputs/billing-end-trial-period.output.ts => billing-end-trial-period.dto.ts} (89%) rename packages/twenty-server/src/engine/core-modules/billing/dtos/{outputs/billing-metered-product-usage.output.ts => billing-metered-product-usage.dto.ts} (86%) rename packages/twenty-server/src/engine/core-modules/billing/dtos/{outputs/billing-plan.output.ts => billing-plan.dto.ts} (90%) rename packages/twenty-server/src/engine/core-modules/billing/dtos/{outputs/billing-price.output.ts => billing-price.dto.ts} (87%) rename packages/twenty-server/src/engine/core-modules/billing/dtos/{outputs/billing-session.output.ts => billing-session.dto.ts} (69%) rename packages/twenty-server/src/engine/core-modules/billing/dtos/{outputs/billing-subscription-item.output.ts => billing-subscription-item.dto.ts} (94%) rename packages/twenty-server/src/engine/core-modules/billing/dtos/{outputs/billing-update.output.ts => billing-update.dto.ts} (89%) rename packages/twenty-server/src/engine/core-modules/email-verification/dtos/{resend-email-verification-token.output.ts => resend-email-verification-token.dto.ts} (63%) rename packages/twenty-server/src/engine/core-modules/event-logs/dtos/{event-log-result.output.ts => event-log-result.dto.ts} (100%) rename packages/twenty-server/src/engine/core-modules/feature-flag/dtos/{feature-flag-dto.ts => feature-flag.dto.ts} (92%) rename packages/twenty-server/src/engine/core-modules/sso/dtos/{delete-sso.output.ts => delete-sso.dto.ts} (82%) rename packages/twenty-server/src/engine/core-modules/sso/dtos/{setup-sso.output.ts => edit-sso.dto.ts} (93%) rename packages/twenty-server/src/engine/core-modules/sso/dtos/{find-available-SSO-IDP.output.ts => find-available-SSO-IDP.dto.ts} (92%) rename packages/twenty-server/src/engine/core-modules/sso/dtos/{edit-sso.output.ts => setup-sso.dto.ts} (93%) rename packages/twenty-server/src/engine/core-modules/two-factor-authentication/dto/{delete-two-factor-authentication-method.output.ts => delete-two-factor-authentication-method.dto.ts} (61%) create mode 100644 packages/twenty-server/src/engine/core-modules/two-factor-authentication/dto/initiate-two-factor-authentication-provisioning.dto.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/two-factor-authentication/dto/initiate-two-factor-authentication-provisioning.output.ts create mode 100644 packages/twenty-server/src/engine/core-modules/two-factor-authentication/dto/verify-two-factor-authentication-method.dto.ts delete mode 100644 packages/twenty-server/src/engine/core-modules/two-factor-authentication/dto/verify-two-factor-authentication-method.output.ts rename packages/twenty-server/src/engine/core-modules/workflow/dtos/{compute-step-output-schema-input.dto.ts => compute-step-output-schema.input.ts} (100%) rename packages/twenty-server/src/engine/core-modules/workflow/dtos/{create-draft-from-workflow-version-input.dto.ts => create-draft-from-workflow-version.input.ts} (100%) rename packages/twenty-server/src/engine/core-modules/workflow/dtos/{create-workflow-version-edge-input.dto.ts => create-workflow-version-edge.input.ts} (100%) rename packages/twenty-server/src/engine/core-modules/workflow/dtos/{create-workflow-version-step-input.dto.ts => create-workflow-version-step.input.ts} (96%) rename packages/twenty-server/src/engine/core-modules/workflow/dtos/{delete-workflow-version-step-input.dto.ts => delete-workflow-version-step.input.ts} (100%) rename packages/twenty-server/src/engine/core-modules/workflow/dtos/{duplicate-workflow-version-step-input.dto.ts => duplicate-workflow-version-step.input.ts} (100%) rename packages/twenty-server/src/engine/core-modules/workflow/dtos/{duplicate-workflow-input.dto.ts => duplicate-workflow.input.ts} (100%) rename packages/twenty-server/src/engine/core-modules/workflow/dtos/{run-workflow-version-output.dto.ts => run-workflow-version.dto.ts} (73%) rename packages/twenty-server/src/engine/core-modules/workflow/dtos/{run-workflow-version-input.dto.ts => run-workflow-version.input.ts} (100%) rename packages/twenty-server/src/engine/core-modules/workflow/dtos/{submit-form-step-input.dto.ts => submit-form-step.input.ts} (100%) rename packages/twenty-server/src/engine/core-modules/workflow/dtos/{test-http-request-output.dto.ts => test-http-request.dto.ts} (93%) rename packages/twenty-server/src/engine/core-modules/workflow/dtos/{test-http-request-input.dto.ts => test-http-request.input.ts} (100%) rename packages/twenty-server/src/engine/core-modules/workflow/dtos/{update-workflow-run-step-input.dto.ts => update-workflow-run-step.input.ts} (100%) rename packages/twenty-server/src/engine/core-modules/workflow/dtos/{update-workflow-step-position-update-input.dto.ts => update-workflow-step-position-update.input.ts} (88%) rename packages/twenty-server/src/engine/core-modules/workflow/dtos/{update-workflow-step-position-input.dto.ts => update-workflow-step-position.input.ts} (100%) rename packages/twenty-server/src/engine/core-modules/workflow/dtos/{update-workflow-version-positions-input.dto.ts => update-workflow-version-positions.input.ts} (89%) rename packages/twenty-server/src/engine/core-modules/workflow/dtos/{update-workflow-version-step-input.dto.ts => update-workflow-version-step.input.ts} (100%) rename packages/twenty-server/src/engine/core-modules/workflow/dtos/{update-workflow-version-trigger-input.dto.ts => update-workflow-version-trigger.input.ts} (100%) rename packages/twenty-server/src/engine/core-modules/workspace-invitation/dtos/{send-invitations.output.ts => send-invitations.dto.ts} (86%) rename packages/twenty-server/src/engine/core-modules/workspace/dtos/{public-workspace-data-output.ts => public-workspace-data.dto.ts} (95%) rename packages/twenty-server/src/engine/metadata-modules/role/dtos/{create-role-input.dto.ts => create-role.input.ts} (100%) rename packages/twenty-server/src/engine/metadata-modules/role/dtos/{update-role-input.dto.ts => update-role.input.ts} (100%) rename packages/twenty-server/src/modules/dashboard/chart-data/dtos/{outputs/bar-chart-data-output.dto.ts => bar-chart-data.dto.ts} (90%) rename packages/twenty-server/src/modules/dashboard/chart-data/dtos/{outputs => }/bar-chart-series.dto.ts (100%) rename packages/twenty-server/src/modules/dashboard/chart-data/dtos/{outputs => }/line-chart-data-point.dto.ts (100%) rename packages/twenty-server/src/modules/dashboard/chart-data/dtos/{outputs/line-chart-data-output.dto.ts => line-chart-data.dto.ts} (83%) rename packages/twenty-server/src/modules/dashboard/chart-data/dtos/{outputs => }/line-chart-series.dto.ts (87%) rename packages/twenty-server/src/modules/dashboard/chart-data/dtos/{outputs => }/pie-chart-data-item.dto.ts (100%) rename packages/twenty-server/src/modules/dashboard/chart-data/dtos/{outputs/pie-chart-data-output.dto.ts => pie-chart-data.dto.ts} (81%) create mode 100644 packages/twenty-server/test/integration/oauth/suites/oauth.integration-spec.ts create mode 100644 packages/twenty-shared/src/application/server-variables.type.ts create mode 100644 packages/twenty-shared/src/utils/base64UrlEncode.ts diff --git a/npm-app-distribution-plan.md b/npm-app-distribution-plan.md new file mode 100644 index 0000000000..246a466df7 --- /dev/null +++ b/npm-app-distribution-plan.md @@ -0,0 +1,283 @@ +# npm-Based App Distribution for Twenty + +*Technical Design Document -- February 2026* + +## Overview + +Add npm registry support for distributing Twenty apps (public and private), with per-AppRegistration registry overrides, direct tarball upload as escape hatch, and version upgrade detection. + +## Assumptions + +- The marketplace install flow (currently a TODO in the resolver and frontend) will be implemented separately. This plan provides the infrastructure that install flow will call into. +- The existing `app:dev` flow (individual file uploads via CLI) remains unchanged. +- The existing GitHub-based marketplace discovery remains as a curated fallback. + +## Architecture + +``` + Developer + / | \ + npm publish | twenty app:push + / | \ + npmjs.com Private Reg Server REST Upload + | | | + v v v + [Discovery Layer] [Direct Upload] + npm search API | + GitHub curated list | + | | + v | + MarketplaceService | + (sourcePackage in DTO) | + | | + v v + AppPackageResolverService <--------+ + .npmrc generation + yarn add / tarball extract + | + v + ApplicationSyncService (existing) + WorkspaceMigrationRunnerService + | + v + AppRegistration + Application entities +``` + +## Phase 1: Entity and Config Changes + +### 1a. Extend AppRegistrationEntity + +Add four columns to `application-registration.entity.ts`: + +- **`sourcePackage`** (text, nullable) -- npm package name, e.g. `"twenty-app-fireflies"` or `"@myorg/twenty-app-crm"`. Null for tarball-only or OAuth-only apps. +- **`tarballFileId`** (uuid, nullable) -- FK to a FileEntity storing a directly-uploaded `.tar.gz`. Null when the app comes from npm. +- **`registryUrl`** (text, nullable) -- per-registration npm registry override. Null means "use the server default `APP_REGISTRY_URL`." This is how a single server can pull public apps from npmjs.com while pulling `@mycompany/*` apps from GitHub Packages. +- **`latestAvailableVersion`** (text, nullable) -- cached latest version from the registry, updated periodically. Compared against `Application.version` to surface upgrade availability. + +**Source resolution priority:** + +1. `sourcePackage` is set → resolve from npm via `yarn add` +2. `tarballFileId` is set → extract from file storage +3. Neither → OAuth-only app, no server-side code + +### 1b. Extend ApplicationEntity.sourceType + +Widen the `sourceType` union from `'local'` to `'local' | 'npm' | 'tarball'`: + +- `'local'` -- existing behavior (CLI `app:dev`, individual file uploads, workspace-custom) +- `'npm'` -- installed from an npm registry via `yarn add` +- `'tarball'` -- installed from a directly-uploaded tarball + +This lets the system distinguish how an app was installed, which matters for upgrade logic (npm apps can check the registry for newer versions; tarball apps cannot). + +### 1c. Add server-wide config variables + +Add a new `APP_REGISTRY_CONFIG` group to ConfigVariablesGroup: + +- **`APP_REGISTRY_URL`** (string, default `https://registry.npmjs.org`) -- default npm registry URL +- **`APP_REGISTRY_TOKEN`** (string, optional, sensitive) -- auth token for the default registry + +### 1d. Generate migration + +TypeORM migration adding `sourcePackage`, `tarballFileId`, `registryUrl`, `latestAvailableVersion` to `core.applicationRegistration`. + +## Phase 2: App Package Resolver Service + +### 2a. Create AppPackageResolverService + +New service with core method: + +``` +resolvePackage(appRegistration, options?: { targetVersion? }) → ResolvedPackage | null +``` + +Returns `{ manifestPath, packageJsonPath, filesDir }` or null for OAuth-only apps. + +**Resolution logic:** + +``` +if sourcePackage: + 1. Determine registry: appRegistration.registryUrl ?? APP_REGISTRY_URL + 2. Determine auth token for the resolved registry + 3. Generate temporary .npmrc in an isolated working directory + 4. Run: yarn add @ + 5. Read manifest from node_modules//.twenty/output/manifest.json + 6. Return paths + +if tarballFileId: + 1. Download tarball from FileStorageService + 2. Extract to temporary directory + 3. Read manifest from extracted files + 4. Return paths + +else: + return null (OAuth-only) +``` + +### 2b. Isolated working directories + +Each resolution runs in a temporary directory under `{os.tmpdir()}/twenty-app-resolver/{uuid}/`. This avoids contaminating the server's own `node_modules` and isolates apps from each other. Cleaned up after files are copied to storage. + +### 2c. .npmrc generation + +For scoped packages (`@scope/twenty-app-*`): + +``` +@scope:registry=https://npm.pkg.github.com +//npm.pkg.github.com/:_authToken=TOKEN +``` + +For unscoped packages with a non-default registry: + +``` +registry=https://my-verdaccio.internal:4873 +//my-verdaccio.internal:4873/:_authToken=TOKEN +``` + +### 2d. Post-resolution file transfer + +After resolving, copies files into the app's storage path using the existing FileStorageService layout: + +``` +{workspaceId}/{applicationUniversalIdentifier}/ + built-logic-function/... + built-front-component/... + dependencies/package.json + dependencies/yarn.lock + public-asset/... + source/... +``` + +This reuses the same FileFolder enum paths that `app:dev` uses, so downstream ApplicationSyncService works unchanged. + +## Phase 3: Marketplace Discovery via npm + +### 3a. Update MarketplaceService + +Add npm-based discovery alongside the existing GitHub path: + +- Query npm search API: `GET {registryUrl}/-/v1/search?text=keywords:twenty-app&size=250` +- Map each result to MarketplaceAppDTO using package.json metadata + +**Merge strategy:** + +1. Fetch from npm search API (apps with `keywords: ["twenty-app"]`) +2. Fetch from GitHub (existing curated list) +3. Merge by `universalIdentifier` -- GitHub entries override npm entries (allowing curation) +4. Cache merged result with existing 1-hour TTL + +### 3b. Add sourcePackage to MarketplaceAppDTO + +The DTO needs a `sourcePackage: string | null` field so the install flow knows which npm package to resolve. For npm-discovered apps, this is the package name. For GitHub-only apps, this is null. + +## Phase 4: Version Upgrade Support + +### 4a. Create AppUpgradeService + +**Periodic version check (npm-sourced apps only):** + +- Fetches `{registryUrl}/{sourcePackage}/latest` from the npm registry +- Stores result in `AppRegistration.latestAvailableVersion` +- Frontend compares against `Application.version` to show "Update available" + +**Upgrade trigger:** + +1. Resolve the new version via AppPackageResolverService +2. Sync via existing ApplicationSyncService (triggers workspace migration for schema changes) +3. Update Application.version + +**Rollback strategy:** If sync fails (e.g., migration validation error), re-resolve the previous version and re-sync. This is possible because npm retains all published versions. + +### 4b. Version check scheduling + +Lightweight cron or check-on-access pattern. Iterates over AppRegistrations where `sourcePackage IS NOT NULL` and calls `checkForUpdates()`. Frequency: once per hour, matching the existing marketplace cache TTL. + +## Phase 5: SDK CLI Commands + +### 5a. Finalize `twenty app:build` + +Ensure `.twenty/output/` is npm-publishable. The build step generates a `package.json` in the output directory: + +```json +{ + "name": "twenty-app-fireflies", + "version": "1.2.0", + "keywords": ["twenty-app"], + "twenty": { + "universalIdentifier": "a4df0c0f-c65e-44e5-8436-24814182d4ac" + }, + "files": ["manifest.json", "built-logic-function", "built-front-component", "public-asset"] +} +``` + +The developer then publishes with standard `npm publish` -- no custom command needed. + +### 5b. `twenty app:pack` (new command) + +``` +twenty app:pack [appPath] +``` + +- Runs `app:build` if `.twenty/output/` doesn't exist or is stale +- Uses existing TarballService to create `{name}-{version}.tar.gz` +- Outputs the file path for manual distribution + +### 5c. `twenty app:push` (new command) + +``` +twenty app:push [appPath] --server --token +``` + +- Runs `app:pack` to produce the tarball +- Reads universalIdentifier from manifest to find or create the AppRegistration +- Uploads via `POST /api/app-registrations/upload-tarball` +- Reports success with the registration ID +- Reuses `twenty auth:login` credentials if `--server` is not specified + +## Phase 6: Server Tarball Upload Endpoint + +### 6a. REST controller + +``` +POST /api/app-registrations/upload-tarball +Content-Type: multipart/form-data +Body: tarball file + optional universalIdentifier +``` + +**Validation:** + +- Max file size: 50MB +- Must be a valid `.tar.gz` +- Extracted contents must contain `manifest.json` with a valid `universalIdentifier` +- The `universalIdentifier` must not conflict with an existing registration owned by a different user + +**Flow:** + +1. Extract tarball to temp directory +2. Validate manifest structure +3. Find or create AppRegistration by universalIdentifier +4. Store tarball in FileStorageService under `FileFolder.AppTarball` +5. Set `tarballFileId` on the AppRegistration +6. Return the AppRegistration entity + +### 6b. Add FileFolder.AppTarball + +New enum value `AppTarball = 'app-tarball'` in FileFolder. + +## Key Design Decisions + +| Decision | Rationale | +|---|---| +| Per-AppRegistration registry override | `registryUrl` on the entity allows mixing registries. Public apps from npmjs.com, private from GitHub Packages/Verdaccio. Server-wide `APP_REGISTRY_URL` is the fallback. | +| npm publish is standard | No custom publish infra. Free versioning, README, `npm audit`, download stats, proven auth model. | +| Tarball as escape hatch | Air-gapped environments, CI pipelines, one-off installs. Cannot auto-upgrade. | +| sourceType distinction | `'npm' \| 'tarball' \| 'local'` lets the system know which upgrade path is available. Only npm apps can check for newer versions. | +| Backward compatible | `app:dev` flow unchanged. GitHub marketplace unchanged. All new fields nullable. | +| Upgrade rollback | Re-resolve previous version from npm on failure. Safe because npm never deletes published versions. | + +## Edge Cases + +- **npm unreachable**: Timeout after 30s, throw clear error. App remains at current installed version. +- **Package name conflicts**: The `universalIdentifier` in the `twenty` field of `package.json` is the source of truth, not the npm package name. Two packages with the same universalIdentifier conflict at the AppRegistration level (unique index). +- **Scoped vs unscoped packages**: Both work. Scoped packages naturally route to a private registry via `.npmrc` scope mapping. +- **Multiple workspaces, same server**: AppRegistration is server-level (core schema). Application is workspace-level. One AppRegistration can be installed in multiple workspaces at different versions. diff --git a/npm-app-distribution-plan.pdf b/npm-app-distribution-plan.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e37caf5d4b22c8f44c3b15aabdba1d42563b3c29 GIT binary patch literal 194061 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
CC=(4E3yUK9DNq%g*;}VLEu~C6h_o-_hXxzSJ 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 { const actual = jest.requireActual('fs-extra'); return { @@ -41,7 +40,6 @@ describe('copyBaseApplicationProject', () => { let testAppDirectory: string; beforeEach(async () => { - // Create a unique temp directory for each test testAppDirectory = join( tmpdir(), `test-twenty-app-${Date.now()}-${Math.random().toString(36).slice(2)}`, @@ -51,7 +49,6 @@ describe('copyBaseApplicationProject', () => { }); afterEach(async () => { - // Clean up temp directory after each test if (testAppDirectory && (await fs.pathExists(testAppDirectory))) { await fs.remove(testAppDirectory); } @@ -66,15 +63,12 @@ describe('copyBaseApplicationProject', () => { exampleOptions: ALL_EXAMPLES, }); - // Verify src/ folder exists const srcAppPath = join(testAppDirectory, 'src'); expect(await fs.pathExists(srcAppPath)).toBe(true); - // Verify application-config.ts exists in src/ const appConfigPath = join(srcAppPath, APPLICATION_FILE_NAME); expect(await fs.pathExists(appConfigPath)).toBe(true); - // Verify default-role.ts exists in src/ const roleConfigPath = join(srcAppPath, 'roles', DEFAULT_ROLE_FILE_NAME); expect(await fs.pathExists(roleConfigPath)).toBe(true); }); @@ -143,27 +137,22 @@ describe('copyBaseApplicationProject', () => { const appConfigPath = join(testAppDirectory, 'src', APPLICATION_FILE_NAME); const appConfigContent = await fs.readFile(appConfigPath, 'utf8'); - // Verify it uses defineApplication expect(appConfigContent).toContain( "import { defineApplication } from 'twenty-sdk'", ); expect(appConfigContent).toContain('export default defineApplication({'); - // Verify it imports the role identifier expect(appConfigContent).toContain( "import { DEFAULT_ROLE_UNIVERSAL_IDENTIFIER } from 'src/roles/default-role'", ); - // Verify display name and description expect(appConfigContent).toContain("displayName: 'My Test App'"); expect(appConfigContent).toContain("description: 'A test application'"); - // Verify it has a universalIdentifier (UUID format) expect(appConfigContent).toMatch( /universalIdentifier: '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'/, ); - // Verify it references the role expect(appConfigContent).toContain( 'defaultRoleUniversalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER', ); @@ -186,29 +175,24 @@ describe('copyBaseApplicationProject', () => { ); const roleConfigContent = await fs.readFile(roleConfigPath, 'utf8'); - // Verify it uses defineRole expect(roleConfigContent).toContain( "import { defineRole } from 'twenty-sdk'", ); expect(roleConfigContent).toContain('export default defineRole({'); - // Verify it exports the universal identifier constant expect(roleConfigContent).toContain( 'export const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER', ); - // Verify role label includes app name expect(roleConfigContent).toContain( "label: 'My Test App default function role'", ); - // Verify default permissions expect(roleConfigContent).toContain('canReadAllObjectRecords: true'); expect(roleConfigContent).toContain('canUpdateAllObjectRecords: true'); expect(roleConfigContent).toContain('canSoftDeleteAllObjectRecords: true'); expect(roleConfigContent).toContain('canDestroyAllObjectRecords: false'); - // Verify it has a universalIdentifier (UUID format) expect(roleConfigContent).toMatch( /universalIdentifier: DEFAULT_ROLE_UNIVERSAL_IDENTIFIER/, ); @@ -223,7 +207,6 @@ describe('copyBaseApplicationProject', () => { exampleOptions: ALL_EXAMPLES, }); - // Verify fs.copy was called with correct destination expect(fs.copy).toHaveBeenCalledTimes(1); expect(fs.copy).toHaveBeenCalledWith( expect.stringContaining('base-application'), @@ -247,7 +230,6 @@ describe('copyBaseApplicationProject', () => { }); it('should generate unique UUIDs for each application', async () => { - // Create first app const firstAppDir = join(testAppDirectory, 'app1'); await fs.ensureDir(firstAppDir); await copyBaseApplicationProject({ @@ -258,7 +240,6 @@ describe('copyBaseApplicationProject', () => { exampleOptions: ALL_EXAMPLES, }); - // Create second app const secondAppDir = join(testAppDirectory, 'app2'); await fs.ensureDir(secondAppDir); await copyBaseApplicationProject({ @@ -269,7 +250,6 @@ describe('copyBaseApplicationProject', () => { exampleOptions: ALL_EXAMPLES, }); - // Read both app configs const firstAppConfig = await fs.readFile( join(firstAppDir, 'src', APPLICATION_FILE_NAME), 'utf8', @@ -279,7 +259,6 @@ describe('copyBaseApplicationProject', () => { 'utf8', ); - // Extract UUIDs using regex const uuidRegex = /universalIdentifier: '([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})'/; const firstUuid = firstAppConfig.match(uuidRegex)?.[1]; @@ -291,7 +270,6 @@ describe('copyBaseApplicationProject', () => { }); it('should generate unique role UUIDs for each application', async () => { - // Create first app const firstAppDir = join(testAppDirectory, 'app1'); await fs.ensureDir(firstAppDir); await copyBaseApplicationProject({ @@ -302,7 +280,6 @@ describe('copyBaseApplicationProject', () => { exampleOptions: ALL_EXAMPLES, }); - // Create second app const secondAppDir = join(testAppDirectory, 'app2'); await fs.ensureDir(secondAppDir); await copyBaseApplicationProject({ @@ -323,7 +300,6 @@ describe('copyBaseApplicationProject', () => { 'utf8', ); - // Extract UUIDs using regex const uuidRegex = /DEFAULT_ROLE_UNIVERSAL_IDENTIFIER =\s*'([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})'/; const firstUuid = firstRoleConfig.match(uuidRegex)?.[1]; @@ -402,7 +378,6 @@ describe('copyBaseApplicationProject', () => { const srcPath = join(testAppDirectory, 'src'); - // Core files should exist expect(await fs.pathExists(join(srcPath, APPLICATION_FILE_NAME))).toBe( true, ); @@ -422,7 +397,6 @@ describe('copyBaseApplicationProject', () => { ), ).toBe(true); - // Example files should not exist expect( await fs.pathExists(join(srcPath, 'objects', 'example-object.ts')), ).toBe(false); diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index 6058b05756..2d1b54f21e 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -56,8 +56,8 @@ export type AdminAiModelConfig = { modelId: Scalars['String']; }; -export type AdminAiModelsOutput = { - __typename?: 'AdminAIModelsOutput'; +export type AdminAiModels = { + __typename?: 'AdminAIModels'; autoEnableNewModels: Scalars['Boolean']; models: Array; }; @@ -311,6 +311,42 @@ export type Application = { yarnLockFileId?: Maybe; }; +export type ApplicationRegistration = { + __typename?: 'ApplicationRegistration'; + author?: Maybe; + createdAt: Scalars['DateTime']; + description?: Maybe; + id: Scalars['UUID']; + logoUrl?: Maybe; + name: Scalars['String']; + oAuthClientId: Scalars['String']; + oAuthRedirectUris: Array; + oAuthScopes: Array; + termsUrl?: Maybe; + universalIdentifier: Scalars['String']; + updatedAt: Scalars['DateTime']; + websiteUrl?: Maybe; +}; + +export type ApplicationRegistrationStats = { + __typename?: 'ApplicationRegistrationStats'; + activeInstalls: Scalars['Int']; + mostInstalledVersion?: Maybe; + versionDistribution: Array; +}; + +export type ApplicationRegistrationVariable = { + __typename?: 'ApplicationRegistrationVariable'; + createdAt: Scalars['DateTime']; + description: Scalars['String']; + id: Scalars['UUID']; + isFilled: Scalars['Boolean']; + isRequired: Scalars['Boolean']; + isSecret: Scalars['Boolean']; + key: Scalars['String']; + updatedAt: Scalars['DateTime']; +}; + export type ApplicationTokenPair = { __typename?: 'ApplicationTokenPair'; applicationAccessToken: AuthToken; @@ -367,8 +403,8 @@ export type AuthTokens = { tokens: AuthTokenPair; }; -export type AuthorizeAppOutput = { - __typename?: 'AuthorizeAppOutput'; +export type AuthorizeApp = { + __typename?: 'AuthorizeApp'; redirectUrl: Scalars['String']; }; @@ -396,8 +432,8 @@ export type AvailableWorkspaces = { availableWorkspacesForSignUp: Array; }; -export type AvailableWorkspacesAndAccessTokensOutput = { - __typename?: 'AvailableWorkspacesAndAccessTokensOutput'; +export type AvailableWorkspacesAndAccessTokens = { + __typename?: 'AvailableWorkspacesAndAccessTokens'; availableWorkspaces: AvailableWorkspaces; tokens: AuthTokenPair; }; @@ -442,13 +478,8 @@ export type BarChartConfiguration = { timezone?: Maybe; }; -export type BarChartDataInput = { - configuration: Scalars['JSON']; - objectMetadataId: Scalars['UUID']; -}; - -export type BarChartDataOutput = { - __typename?: 'BarChartDataOutput'; +export type BarChartData = { + __typename?: 'BarChartData'; data: Array; formattedToRawLookup: Scalars['JSON']; groupMode: BarChartGroupMode; @@ -463,6 +494,11 @@ export type BarChartDataOutput = { yAxisLabel: Scalars['String']; }; +export type BarChartDataInput = { + configuration: Scalars['JSON']; + objectMetadataId: Scalars['UUID']; +}; + /** Display mode for bar charts with secondary grouping */ export enum BarChartGroupMode { GROUPED = 'GROUPED', @@ -488,8 +524,8 @@ export type Billing = { trialPeriods: Array; }; -export type BillingEndTrialPeriodOutput = { - __typename?: 'BillingEndTrialPeriodOutput'; +export type BillingEndTrialPeriod = { + __typename?: 'BillingEndTrialPeriod'; /** Billing portal URL for payment method update (returned when no payment method exists) */ billingPortalUrl?: Maybe; /** Boolean that confirms if a payment method was found */ @@ -529,8 +565,8 @@ export type BillingMeteredProduct = BillingProductDto & { prices?: Maybe>; }; -export type BillingMeteredProductUsageOutput = { - __typename?: 'BillingMeteredProductUsageOutput'; +export type BillingMeteredProductUsage = { + __typename?: 'BillingMeteredProductUsage'; grantedCredits: Scalars['Float']; periodEnd: Scalars['DateTime']; periodStart: Scalars['DateTime']; @@ -541,19 +577,19 @@ export type BillingMeteredProductUsageOutput = { usedCredits: Scalars['Float']; }; +export type BillingPlan = { + __typename?: 'BillingPlan'; + licensedProducts: Array; + meteredProducts: Array; + planKey: BillingPlanKey; +}; + /** The different billing plans available */ export enum BillingPlanKey { ENTERPRISE = 'ENTERPRISE', PRO = 'PRO' } -export type BillingPlanOutput = { - __typename?: 'BillingPlanOutput'; - licensedProducts: Array; - meteredProducts: Array; - planKey: BillingPlanKey; -}; - export type BillingPriceLicensed = { __typename?: 'BillingPriceLicensed'; priceUsageType: BillingUsageType; @@ -605,14 +641,14 @@ export type BillingProductMetadata = { productKey: BillingProductKey; }; -export type BillingSessionOutput = { - __typename?: 'BillingSessionOutput'; +export type BillingSession = { + __typename?: 'BillingSession'; url?: Maybe; }; export type BillingSubscription = { __typename?: 'BillingSubscription'; - billingSubscriptionItems?: Maybe>; + billingSubscriptionItems?: Maybe>; currentPeriodEnd?: Maybe; id: Scalars['UUID']; interval?: Maybe; @@ -621,8 +657,8 @@ export type BillingSubscription = { status: SubscriptionStatus; }; -export type BillingSubscriptionItemDto = { - __typename?: 'BillingSubscriptionItemDTO'; +export type BillingSubscriptionItem = { + __typename?: 'BillingSubscriptionItem'; billingProduct: BillingProductDto; hasReachedCurrentPeriodCap: Scalars['Boolean']; id: Scalars['UUID']; @@ -649,8 +685,8 @@ export type BillingTrialPeriod = { isCreditCardRequired: Scalars['Boolean']; }; -export type BillingUpdateOutput = { - __typename?: 'BillingUpdateOutput'; +export type BillingUpdate = { + __typename?: 'BillingUpdate'; /** All billing subscriptions */ billingSubscriptions: Array; /** Current billing subscription */ @@ -688,8 +724,8 @@ export type ChannelSyncSuccess = { success: Scalars['Boolean']; }; -export type CheckUserExistOutput = { - __typename?: 'CheckUserExistOutput'; +export type CheckUserExist = { + __typename?: 'CheckUserExist'; availableWorkspacesCount: Scalars['Float']; exists: Scalars['Boolean']; isEmailVerified: Scalars['Boolean']; @@ -788,6 +824,11 @@ export enum ConfigVariableType { STRING = 'STRING' } +export type ConfigVariables = { + __typename?: 'ConfigVariables'; + groups: Array; +}; + export enum ConfigVariablesGroup { ANALYTICS_CONFIG = 'ANALYTICS_CONFIG', AWS_SES_SETTINGS = 'AWS_SES_SETTINGS', @@ -821,11 +862,6 @@ export type ConfigVariablesGroupData = { variables: Array; }; -export type ConfigVariablesOutput = { - __typename?: 'ConfigVariablesOutput'; - groups: Array; -}; - export type ConnectedImapSmtpCaldavAccount = { __typename?: 'ConnectedImapSmtpCaldavAccount'; accountOwnerId: Scalars['UUID']; @@ -994,6 +1030,7 @@ export type CreateAppTokenInput = { }; export type CreateApplicationInput = { + applicationRegistrationId?: InputMaybe; description?: InputMaybe; name: Scalars['String']; sourcePath: Scalars['String']; @@ -1001,6 +1038,32 @@ export type CreateApplicationInput = { version: Scalars['String']; }; +export type CreateApplicationRegistration = { + __typename?: 'CreateApplicationRegistration'; + applicationRegistration: ApplicationRegistration; + clientSecret: Scalars['String']; +}; + +export type CreateApplicationRegistrationInput = { + author?: InputMaybe; + description?: InputMaybe; + logoUrl?: InputMaybe; + name: Scalars['String']; + oAuthRedirectUris?: InputMaybe>; + oAuthScopes?: InputMaybe>; + termsUrl?: InputMaybe; + universalIdentifier?: InputMaybe; + websiteUrl?: InputMaybe; +}; + +export type CreateApplicationRegistrationVariableInput = { + applicationRegistrationId: Scalars['String']; + description?: InputMaybe; + isSecret?: InputMaybe; + key: Scalars['String']; + value: Scalars['String']; +}; + export type CreateApprovedAccessDomainInput = { domain: Scalars['String']; email: Scalars['String']; @@ -1274,17 +1337,17 @@ export type DeleteOneObjectInput = { id: Scalars['UUID']; }; +export type DeleteSso = { + __typename?: 'DeleteSso'; + identityProviderId: Scalars['UUID']; +}; + export type DeleteSsoInput = { identityProviderId: Scalars['UUID']; }; -export type DeleteSsoOutput = { - __typename?: 'DeleteSsoOutput'; - identityProviderId: Scalars['UUID']; -}; - -export type DeleteTwoFactorAuthenticationMethodOutput = { - __typename?: 'DeleteTwoFactorAuthenticationMethodOutput'; +export type DeleteTwoFactorAuthenticationMethod = { + __typename?: 'DeleteTwoFactorAuthenticationMethod'; /** Boolean that confirms query was dispatched */ success: Scalars['Boolean']; }; @@ -1364,13 +1427,8 @@ export type DuplicatedDashboard = { updatedAt: Scalars['String']; }; -export type EditSsoInput = { - id: Scalars['UUID']; - status: SsoIdentityProviderStatus; -}; - -export type EditSsoOutput = { - __typename?: 'EditSsoOutput'; +export type EditSso = { + __typename?: 'EditSso'; id: Scalars['UUID']; issuer: Scalars['String']; name: Scalars['String']; @@ -1378,14 +1436,19 @@ export type EditSsoOutput = { type: IdentityProviderType; }; +export type EditSsoInput = { + id: Scalars['UUID']; + status: SsoIdentityProviderStatus; +}; + export type EmailAccountConnectionParameters = { CALDAV?: InputMaybe; IMAP?: InputMaybe; SMTP?: InputMaybe; }; -export type EmailPasswordResetLinkOutput = { - __typename?: 'EmailPasswordResetLinkOutput'; +export type EmailPasswordResetLink = { + __typename?: 'EmailPasswordResetLink'; /** Boolean that confirms query was dispatched */ success: Scalars['Boolean']; }; @@ -1484,13 +1547,6 @@ export type ExecuteOneLogicFunctionInput = { export type FeatureFlag = { __typename?: 'FeatureFlag'; - id: Scalars['UUID']; - key: FeatureFlagKey; - value: Scalars['Boolean']; -}; - -export type FeatureFlagDto = { - __typename?: 'FeatureFlagDTO'; key: FeatureFlagKey; value: Scalars['Boolean']; }; @@ -1680,8 +1736,8 @@ export type FilesConfiguration = { configurationType: WidgetConfigurationType; }; -export type FindAvailableSsoidpOutput = { - __typename?: 'FindAvailableSSOIDPOutput'; +export type FindAvailableSsoidp = { + __typename?: 'FindAvailableSSOIDP'; id: Scalars['UUID']; issuer: Scalars['String']; name: Scalars['String']; @@ -1736,18 +1792,18 @@ export type GetApiKeyInput = { id: Scalars['UUID']; }; -export type GetAuthorizationUrlForSsoInput = { - identityProviderId: Scalars['UUID']; - workspaceInviteHash?: InputMaybe; -}; - -export type GetAuthorizationUrlForSsoOutput = { - __typename?: 'GetAuthorizationUrlForSSOOutput'; +export type GetAuthorizationUrlForSso = { + __typename?: 'GetAuthorizationUrlForSSO'; authorizationURL: Scalars['String']; id: Scalars['UUID']; type: Scalars['String']; }; +export type GetAuthorizationUrlForSsoInput = { + identityProviderId: Scalars['UUID']; + workspaceInviteHash?: InputMaybe; +}; + /** Order by options for graph widgets */ export enum GraphOrderBy { FIELD_ASC = 'FIELD_ASC', @@ -1806,8 +1862,8 @@ export type ImapSmtpCaldavConnectionSuccess = { success: Scalars['Boolean']; }; -export type ImpersonateOutput = { - __typename?: 'ImpersonateOutput'; +export type Impersonate = { + __typename?: 'Impersonate'; loginToken: AuthToken; workspace: WorkspaceUrlsAndId; }; @@ -1920,13 +1976,13 @@ export enum InferenceProvider { XAI = 'XAI' } -export type InitiateTwoFactorAuthenticationProvisioningOutput = { - __typename?: 'InitiateTwoFactorAuthenticationProvisioningOutput'; +export type InitiateTwoFactorAuthenticationProvisioning = { + __typename?: 'InitiateTwoFactorAuthenticationProvisioning'; uri: Scalars['String']; }; -export type InvalidatePasswordOutput = { - __typename?: 'InvalidatePasswordOutput'; +export type InvalidatePassword = { + __typename?: 'InvalidatePassword'; /** Boolean that confirms query was dispatched */ success: Scalars['Boolean']; }; @@ -1980,13 +2036,8 @@ export type LineChartConfiguration = { timezone?: Maybe; }; -export type LineChartDataInput = { - configuration: Scalars['JSON']; - objectMetadataId: Scalars['UUID']; -}; - -export type LineChartDataOutput = { - __typename?: 'LineChartDataOutput'; +export type LineChartData = { + __typename?: 'LineChartData'; formattedToRawLookup: Scalars['JSON']; hasTooManyGroups: Scalars['Boolean']; series: Array; @@ -1996,6 +2047,11 @@ export type LineChartDataOutput = { yAxisLabel: Scalars['String']; }; +export type LineChartDataInput = { + configuration: Scalars['JSON']; + objectMetadataId: Scalars['UUID']; +}; + export type LineChartDataPoint = { __typename?: 'LineChartDataPoint'; x: Scalars['String']; @@ -2075,8 +2131,8 @@ export type LogicFunctionLogsInput = { universalIdentifier?: InputMaybe; }; -export type LoginTokenOutput = { - __typename?: 'LoginTokenOutput'; +export type LoginToken = { + __typename?: 'LoginToken'; loginToken: AuthToken; }; @@ -2207,14 +2263,16 @@ export type Mutation = { addQueryToEventStream: Scalars['Boolean']; assignRoleToAgent: Scalars['Boolean']; assignRoleToApiKey: Scalars['Boolean']; - authorizeApp: AuthorizeAppOutput; - cancelSwitchBillingInterval: BillingUpdateOutput; - cancelSwitchBillingPlan: BillingUpdateOutput; - cancelSwitchMeteredPrice: BillingUpdateOutput; + authorizeApp: AuthorizeApp; + cancelSwitchBillingInterval: BillingUpdate; + cancelSwitchBillingPlan: BillingUpdate; + cancelSwitchMeteredPrice: BillingUpdate; checkCustomDomainValidRecords?: Maybe; checkPublicDomainValidRecords?: Maybe; - checkoutSession: BillingSessionOutput; + checkoutSession: BillingSession; createApiKey: ApiKey; + createApplicationRegistration: CreateApplicationRegistration; + createApplicationRegistrationVariable: ApplicationRegistrationVariable; createApprovedAccessDomain: ApprovedAccessDomain; createChatThread: AgentChatThread; createCommandMenuItem: CommandMenuItem; @@ -2234,7 +2292,7 @@ export type Mutation = { createManyCoreViewFields: Array; createManyCoreViewGroups: Array; createNavigationMenuItem: NavigationMenuItem; - createOIDCIdentityProvider: SetupSsoOutput; + createOIDCIdentityProvider: SetupSso; createObjectEvent: Analytics; createOneAgent: Agent; createOneAppToken: AppToken; @@ -2247,10 +2305,12 @@ export type Mutation = { createPageLayoutTab: PageLayoutTab; createPageLayoutWidget: PageLayoutWidget; createPublicDomain: PublicDomain; - createSAMLIdentityProvider: SetupSsoOutput; + createSAMLIdentityProvider: SetupSso; createSkill: Skill; createWebhook: Webhook; deactivateSkill: Skill; + deleteApplicationRegistration: Scalars['Boolean']; + deleteApplicationRegistrationVariable: Scalars['Boolean']; deleteApprovedAccessDomain: Scalars['Boolean']; deleteCommandMenuItem: CommandMenuItem; deleteCoreView: Scalars['Boolean']; @@ -2274,9 +2334,9 @@ export type Mutation = { deleteOneObject: Object; deleteOneRole: Scalars['String']; deletePublicDomain: Scalars['Boolean']; - deleteSSOIdentityProvider: DeleteSsoOutput; + deleteSSOIdentityProvider: DeleteSso; deleteSkill: Skill; - deleteTwoFactorAuthenticationMethod: DeleteTwoFactorAuthenticationMethodOutput; + deleteTwoFactorAuthenticationMethod: DeleteTwoFactorAuthenticationMethod; deleteUser: User; deleteUserFromWorkspace: UserWorkspace; deleteWebhook: Webhook; @@ -2293,50 +2353,53 @@ export type Mutation = { destroyPageLayoutWidget: Scalars['Boolean']; disablePostgresProxy: PostgresCredentials; duplicateDashboard: DuplicatedDashboard; - editSSOIdentityProvider: EditSsoOutput; - emailPasswordResetLink: EmailPasswordResetLinkOutput; + editSSOIdentityProvider: EditSso; + emailPasswordResetLink: EmailPasswordResetLink; enablePostgresProxy: PostgresCredentials; - endSubscriptionTrialPeriod: BillingEndTrialPeriodOutput; + endSubscriptionTrialPeriod: BillingEndTrialPeriod; evaluateAgentTurn: AgentTurnEvaluation; executeOneLogicFunction: LogicFunctionExecutionResult; generateApiKeyToken: ApiKeyToken; generateApplicationToken: ApplicationTokenPair; - generateTransientToken: TransientTokenOutput; + generateTransientToken: TransientToken; getAuthTokensFromLoginToken: AuthTokens; getAuthTokensFromOTP: AuthTokens; - getAuthorizationUrlForSSO: GetAuthorizationUrlForSsoOutput; - getLoginTokenFromCredentials: LoginTokenOutput; - impersonate: ImpersonateOutput; - initiateOTPProvisioning: InitiateTwoFactorAuthenticationProvisioningOutput; - initiateOTPProvisioningForAuthenticatedUser: InitiateTwoFactorAuthenticationProvisioningOutput; + getAuthorizationUrlForSSO: GetAuthorizationUrlForSso; + getLoginTokenFromCredentials: LoginToken; + impersonate: Impersonate; + initiateOTPProvisioning: InitiateTwoFactorAuthenticationProvisioning; + initiateOTPProvisioningForAuthenticatedUser: InitiateTwoFactorAuthenticationProvisioning; installApplication: Scalars['Boolean']; installMarketplaceApp: Scalars['Boolean']; removeQueryFromEventStream: Scalars['Boolean']; removeRoleFromAgent: Scalars['Boolean']; renewApplicationToken: ApplicationTokenPair; renewToken: AuthTokens; - resendEmailVerificationToken: ResendEmailVerificationTokenOutput; - resendWorkspaceInvitation: SendInvitationsOutput; + resendEmailVerificationToken: ResendEmailVerificationToken; + resendWorkspaceInvitation: SendInvitations; retryJobs: RetryJobsResponse; revokeApiKey?: Maybe; + rotateApplicationRegistrationClientSecret: RotateClientSecret; runEvaluationInput: AgentTurn; saveImapSmtpCaldavAccount: ImapSmtpCaldavConnectionSuccess; - sendInvitations: SendInvitationsOutput; + sendInvitations: SendInvitations; setAdminAiModelEnabled: Scalars['Boolean']; - setMeteredSubscriptionPrice: BillingUpdateOutput; - signIn: AvailableWorkspacesAndAccessTokensOutput; - signUp: AvailableWorkspacesAndAccessTokensOutput; - signUpInNewWorkspace: SignUpOutput; - signUpInWorkspace: SignUpOutput; + setMeteredSubscriptionPrice: BillingUpdate; + signIn: AvailableWorkspacesAndAccessTokens; + signUp: AvailableWorkspacesAndAccessTokens; + signUpInNewWorkspace: SignUp; + signUpInWorkspace: SignUp; skipBookOnboardingStep: OnboardingStepSuccess; skipSyncEmailOnboardingStep: OnboardingStepSuccess; startChannelSync: ChannelSyncSuccess; - switchBillingPlan: BillingUpdateOutput; - switchSubscriptionInterval: BillingUpdateOutput; - syncApplication: WorkspaceMigrationDto; + switchBillingPlan: BillingUpdate; + switchSubscriptionInterval: BillingUpdate; + syncApplication: WorkspaceMigration; trackAnalytics: Analytics; uninstallApplication: Scalars['Boolean']; updateApiKey?: Maybe; + updateApplicationRegistration: ApplicationRegistration; + updateApplicationRegistrationVariable: ApplicationRegistrationVariable; updateCommandMenuItem: CommandMenuItem; updateCoreView: CoreView; updateCoreViewField: CoreViewField; @@ -2347,7 +2410,7 @@ export type Mutation = { updateCoreViewSort: CoreViewSort; updateDatabaseConfigVariable: Scalars['Boolean']; updateFrontComponent: FrontComponent; - updateLabPublicFeatureFlag: FeatureFlagDto; + updateLabPublicFeatureFlag: FeatureFlag; updateNavigationMenuItem: NavigationMenuItem; updateOneAgent: Agent; updateOneApplicationVariable: Scalars['Boolean']; @@ -2359,7 +2422,7 @@ export type Mutation = { updatePageLayoutTab: PageLayoutTab; updatePageLayoutWidget: PageLayoutWidget; updatePageLayoutWithTabsAndWidgets: PageLayout; - updatePasswordViaResetToken: InvalidatePasswordOutput; + updatePasswordViaResetToken: InvalidatePassword; updateSkill: Skill; updateUserEmail: Scalars['Boolean']; updateWebhook: Webhook; @@ -2384,10 +2447,10 @@ export type Mutation = { upsertRowLevelPermissionPredicates: UpsertRowLevelPermissionPredicatesResult; userLookupAdminPanel: UserLookup; validateApprovedAccessDomain: ApprovedAccessDomain; - verifyEmailAndGetLoginToken: VerifyEmailAndGetLoginTokenOutput; - verifyEmailAndGetWorkspaceAgnosticToken: AvailableWorkspacesAndAccessTokensOutput; + verifyEmailAndGetLoginToken: VerifyEmailAndGetLoginToken; + verifyEmailAndGetWorkspaceAgnosticToken: AvailableWorkspacesAndAccessTokens; verifyEmailingDomain: EmailingDomain; - verifyTwoFactorAuthenticationMethodForAuthenticatedUser: VerifyTwoFactorAuthenticationMethodOutput; + verifyTwoFactorAuthenticationMethodForAuthenticatedUser: VerifyTwoFactorAuthenticationMethod; }; @@ -2443,6 +2506,16 @@ export type MutationCreateApiKeyArgs = { }; +export type MutationCreateApplicationRegistrationArgs = { + input: CreateApplicationRegistrationInput; +}; + + +export type MutationCreateApplicationRegistrationVariableArgs = { + input: CreateApplicationRegistrationVariableInput; +}; + + export type MutationCreateApprovedAccessDomainArgs = { input: CreateApprovedAccessDomainInput; }; @@ -2618,6 +2691,16 @@ export type MutationDeactivateSkillArgs = { }; +export type MutationDeleteApplicationRegistrationArgs = { + id: Scalars['String']; +}; + + +export type MutationDeleteApplicationRegistrationVariableArgs = { + id: Scalars['String']; +}; + + export type MutationDeleteApprovedAccessDomainArgs = { input: DeleteApprovedAccessDomainInput; }; @@ -2929,6 +3012,11 @@ export type MutationRevokeApiKeyArgs = { }; +export type MutationRotateApplicationRegistrationClientSecretArgs = { + id: Scalars['String']; +}; + + export type MutationRunEvaluationInputArgs = { agentId: Scalars['UUID']; input: Scalars['String']; @@ -3017,6 +3105,16 @@ export type MutationUpdateApiKeyArgs = { }; +export type MutationUpdateApplicationRegistrationArgs = { + input: UpdateApplicationRegistrationInput; +}; + + +export type MutationUpdateApplicationRegistrationVariableArgs = { + input: UpdateApplicationRegistrationVariableInput; +}; + + export type MutationUpdateCommandMenuItemArgs = { input: UpdateCommandMenuItemInput; }; @@ -3668,6 +3766,16 @@ export type PieChartConfiguration = { timezone?: Maybe; }; +export type PieChartData = { + __typename?: 'PieChartData'; + data: Array; + formattedToRawLookup: Scalars['JSON']; + hasTooManyGroups: Scalars['Boolean']; + showCenterMetric: Scalars['Boolean']; + showDataLabels: Scalars['Boolean']; + showLegend: Scalars['Boolean']; +}; + export type PieChartDataInput = { configuration: Scalars['JSON']; objectMetadataId: Scalars['UUID']; @@ -3679,16 +3787,6 @@ export type PieChartDataItem = { value: Scalars['Float']; }; -export type PieChartDataOutput = { - __typename?: 'PieChartDataOutput'; - data: Array; - formattedToRawLookup: Scalars['JSON']; - hasTooManyGroups: Scalars['Boolean']; - showCenterMetric: Scalars['Boolean']; - showDataLabels: Scalars['Boolean']; - showLegend: Scalars['Boolean']; -}; - export type PlaceDetailsResult = { __typename?: 'PlaceDetailsResult'; city?: Maybe; @@ -3727,8 +3825,8 @@ export type PublicFeatureFlagMetadata = { label: Scalars['String']; }; -export type PublicWorkspaceDataOutput = { - __typename?: 'PublicWorkspaceDataOutput'; +export type PublicWorkspaceData = { + __typename?: 'PublicWorkspaceData'; authBypassProviders?: Maybe; authProviders: AuthProviders; displayName?: Maybe; @@ -3742,13 +3840,13 @@ export type Query = { agentTurns: Array; apiKey?: Maybe; apiKeys: Array; - barChartData: BarChartDataOutput; - billingPortalSession: BillingSessionOutput; + barChartData: BarChartData; + billingPortalSession: BillingSession; chatMessages: Array; chatThread: AgentChatThread; chatThreads: Array; - checkUserExists: CheckUserExistOutput; - checkWorkspaceInviteHashIsValid: WorkspaceInviteHashValidOutput; + checkUserExists: CheckUserExist; + checkWorkspaceInviteHashIsValid: WorkspaceInviteHashValid; commandMenuItem?: Maybe; commandMenuItems: Array; currentUser: User; @@ -3756,13 +3854,19 @@ export type Query = { eventLogs: EventLogQueryResult; field: Field; fields: FieldConnection; + findApplicationRegistrationByClientId?: Maybe; + findApplicationRegistrationByUniversalIdentifier?: Maybe; + findApplicationRegistrationStats: ApplicationRegistrationStats; + findApplicationRegistrationVariables: Array; findManyAgents: Array; + findManyApplicationRegistrations: Array; findManyApplications: Array; findManyLogicFunctions: Array; findManyMarketplaceApps: Array; findManyPublicDomains: Array; findOneAgent: Agent; findOneApplication: Application; + findOneApplicationRegistration: ApplicationRegistration; findOneLogicFunction: LogicFunction; findWorkspaceFromInviteHash: Workspace; findWorkspaceInvitations: Array; @@ -3770,11 +3874,11 @@ export type Query = { frontComponents: Array; getAISystemPromptPreview: AiSystemPromptPreview; getAddressDetails: PlaceDetailsResult; - getAdminAiModels: AdminAiModelsOutput; + getAdminAiModels: AdminAiModels; getApprovedAccessDomains: Array; getAutoCompleteAddress: Array; getAvailablePackages: Scalars['JSON']; - getConfigVariablesGrouped: ConfigVariablesOutput; + getConfigVariablesGrouped: ConfigVariables; getConnectedImapSmtpCaldavAccount: ConnectedImapSmtpCaldavAccount; getCoreView?: Maybe; getCoreViewField?: Maybe; @@ -3794,7 +3898,7 @@ export type Query = { getEmailingDomains: Array; getIndicatorHealthStatus: AdminPanelHealthServiceData; getLogicFunctionSourceCode?: Maybe; - getMeteredProductsUsage: Array; + getMeteredProductsUsage: Array; getPageLayout?: Maybe; getPageLayoutTab: PageLayoutTab; getPageLayoutTabs: Array; @@ -3802,27 +3906,27 @@ export type Query = { getPageLayoutWidgets: Array; getPageLayouts: Array; getPostgresCredentials?: Maybe; - getPublicWorkspaceDataByDomain: PublicWorkspaceDataOutput; + getPublicWorkspaceDataByDomain: PublicWorkspaceData; getQueueJobs: QueueJobsResponse; getQueueMetrics: QueueMetricsData; getRoles: Array; - getSSOIdentityProviders: Array; + getSSOIdentityProviders: Array; getSystemHealthStatus: SystemHealth; getToolIndex: Array; getToolInputSchema?: Maybe; index: Index; indexMetadatas: IndexConnection; - lineChartData: LineChartDataOutput; - listPlans: Array; + lineChartData: LineChartData; + listPlans: Array; navigationMenuItem?: Maybe; navigationMenuItems: Array; object: Object; objectRecordCounts: Array; objects: ObjectConnection; - pieChartData: PieChartDataOutput; + pieChartData: PieChartData; skill?: Maybe; skills: Array; - validatePasswordResetToken: ValidatePasswordResetTokenOutput; + validatePasswordResetToken: ValidatePasswordResetToken; versionInfo: VersionInfo; webhook?: Maybe; webhooks: Array; @@ -3891,6 +3995,26 @@ export type QueryFieldsArgs = { }; +export type QueryFindApplicationRegistrationByClientIdArgs = { + clientId: Scalars['String']; +}; + + +export type QueryFindApplicationRegistrationByUniversalIdentifierArgs = { + universalIdentifier: Scalars['String']; +}; + + +export type QueryFindApplicationRegistrationStatsArgs = { + id: Scalars['String']; +}; + + +export type QueryFindApplicationRegistrationVariablesArgs = { + applicationRegistrationId: Scalars['String']; +}; + + export type QueryFindOneAgentArgs = { input: AgentIdInput; }; @@ -3902,6 +4026,11 @@ export type QueryFindOneApplicationArgs = { }; +export type QueryFindOneApplicationRegistrationArgs = { + id: Scalars['String']; +}; + + export type QueryFindOneLogicFunctionArgs = { input: LogicFunctionIdInput; }; @@ -4228,8 +4357,8 @@ export type RemoveQueryFromEventStreamInput = { queryId: Scalars['String']; }; -export type ResendEmailVerificationTokenOutput = { - __typename?: 'ResendEmailVerificationTokenOutput'; +export type ResendEmailVerificationToken = { + __typename?: 'ResendEmailVerificationToken'; success: Scalars['Boolean']; }; @@ -4276,6 +4405,11 @@ export type Role = { workspaceMembers: Array; }; +export type RotateClientSecret = { + __typename?: 'RotateClientSecret'; + clientSecret: Scalars['String']; +}; + export type RowLevelPermissionPredicate = { __typename?: 'RowLevelPermissionPredicate'; fieldMetadataId: Scalars['String']; @@ -4369,8 +4503,8 @@ export enum SsoIdentityProviderStatus { Inactive = 'Inactive' } -export type SendInvitationsOutput = { - __typename?: 'SendInvitationsOutput'; +export type SendInvitations = { + __typename?: 'SendInvitations'; errors: Array; result: Array; /** Boolean that confirms query was dispatched */ @@ -4400,8 +4534,8 @@ export type SetupSamlSsoInput = { ssoURL: Scalars['String']; }; -export type SetupSsoOutput = { - __typename?: 'SetupSsoOutput'; +export type SetupSso = { + __typename?: 'SetupSso'; id: Scalars['UUID']; issuer: Scalars['String']; name: Scalars['String']; @@ -4409,8 +4543,8 @@ export type SetupSsoOutput = { type: IdentityProviderType; }; -export type SignUpOutput = { - __typename?: 'SignUpOutput'; +export type SignUp = { + __typename?: 'SignUp'; loginToken: AuthToken; workspace: WorkspaceUrlsAndId; }; @@ -4530,13 +4664,13 @@ export type ToolIndexEntry = { objectName?: Maybe; }; -export type TransientTokenOutput = { - __typename?: 'TransientTokenOutput'; +export type TransientToken = { + __typename?: 'TransientToken'; transientToken: AuthToken; }; -export type TwoFactorAuthenticationMethodDto = { - __typename?: 'TwoFactorAuthenticationMethodDTO'; +export type TwoFactorAuthenticationMethodSummary = { + __typename?: 'TwoFactorAuthenticationMethodSummary'; status: Scalars['String']; strategy: Scalars['String']; twoFactorAuthenticationMethodId: Scalars['UUID']; @@ -4580,6 +4714,32 @@ export type UpdateApiKeyInput = { revokedAt?: InputMaybe; }; +export type UpdateApplicationRegistrationInput = { + id: Scalars['String']; + update: UpdateApplicationRegistrationPayload; +}; + +export type UpdateApplicationRegistrationPayload = { + author?: InputMaybe; + description?: InputMaybe; + logoUrl?: InputMaybe; + name?: InputMaybe; + oAuthRedirectUris?: InputMaybe>; + oAuthScopes?: InputMaybe>; + termsUrl?: InputMaybe; + websiteUrl?: InputMaybe; +}; + +export type UpdateApplicationRegistrationVariableInput = { + id: Scalars['String']; + update: UpdateApplicationRegistrationVariablePayload; +}; + +export type UpdateApplicationRegistrationVariablePayload = { + description?: InputMaybe; + value?: InputMaybe; +}; + export type UpdateCommandMenuItemInput = { availabilityObjectMetadataId?: InputMaybe; availabilityType?: InputMaybe; @@ -5002,7 +5162,7 @@ export type UserWorkspace = { objectPermissions?: Maybe>; objectsPermissions?: Maybe>; permissionFlags?: Maybe>; - twoFactorAuthenticationMethodSummary?: Maybe>; + twoFactorAuthenticationMethodSummary?: Maybe>; updatedAt: Scalars['DateTime']; user: User; userId: Scalars['UUID']; @@ -5013,8 +5173,8 @@ export type ValidateApprovedAccessDomainInput = { validationToken: Scalars['String']; }; -export type ValidatePasswordResetTokenOutput = { - __typename?: 'ValidatePasswordResetTokenOutput'; +export type ValidatePasswordResetToken = { + __typename?: 'ValidatePasswordResetToken'; email: Scalars['String']; hasPassword: Scalars['Boolean']; id: Scalars['UUID']; @@ -5028,17 +5188,23 @@ export type VerificationRecord = { value: Scalars['String']; }; -export type VerifyEmailAndGetLoginTokenOutput = { - __typename?: 'VerifyEmailAndGetLoginTokenOutput'; +export type VerifyEmailAndGetLoginToken = { + __typename?: 'VerifyEmailAndGetLoginToken'; loginToken: AuthToken; workspaceUrls: WorkspaceUrls; }; -export type VerifyTwoFactorAuthenticationMethodOutput = { - __typename?: 'VerifyTwoFactorAuthenticationMethodOutput'; +export type VerifyTwoFactorAuthenticationMethod = { + __typename?: 'VerifyTwoFactorAuthenticationMethod'; success: Scalars['Boolean']; }; +export type VersionDistributionEntry = { + __typename?: 'VersionDistributionEntry'; + count: Scalars['Int']; + version: Scalars['String']; +}; + export type VersionInfo = { __typename?: 'VersionInfo'; currentVersion?: Maybe; @@ -5214,7 +5380,7 @@ export type Workspace = { enabledAiModelIds?: Maybe>; eventLogRetentionDays: Scalars['Float']; fastModel: Scalars['String']; - featureFlags?: Maybe>; + featureFlags?: Maybe>; hasValidEnterpriseKey: Scalars['Boolean']; id: Scalars['UUID']; inviteHash?: Maybe; @@ -5276,8 +5442,8 @@ export type WorkspaceInvitation = { id: Scalars['UUID']; }; -export type WorkspaceInviteHashValidOutput = { - __typename?: 'WorkspaceInviteHashValidOutput'; +export type WorkspaceInviteHashValid = { + __typename?: 'WorkspaceInviteHashValid'; isValid: Scalars['Boolean']; }; @@ -5322,18 +5488,18 @@ export enum WorkspaceMemberTimeFormatEnum { SYSTEM = 'SYSTEM' } +export type WorkspaceMigration = { + __typename?: 'WorkspaceMigration'; + actions: Scalars['JSON']; + applicationUniversalIdentifier: Scalars['String']; +}; + export enum WorkspaceMigrationActionType { create = 'create', delete = 'delete', update = 'update' } -export type WorkspaceMigrationDto = { - __typename?: 'WorkspaceMigrationDTO'; - actions: Scalars['JSON']; - applicationUniversalIdentifier: Scalars['String']; -}; - export type WorkspaceMigrationDeleteActionInput = { metadataName: AllMetadataName; type: WorkspaceMigrationActionType; @@ -5569,16 +5735,16 @@ export type AvailableWorkspaceFragmentFragment = { __typename?: 'AvailableWorksp export type AvailableWorkspacesFragmentFragment = { __typename?: 'AvailableWorkspaces', availableWorkspacesForSignIn: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }>, availableWorkspacesForSignUp: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }> }; -export type AvailableSsoIdentityProvidersFragmentFragment = { __typename?: 'FindAvailableSSOIDPOutput', id: string, issuer: string, name: string, status: SsoIdentityProviderStatus, workspace: { __typename?: 'WorkspaceNameAndId', id: string, displayName?: string | null } }; +export type AvailableSsoIdentityProvidersFragmentFragment = { __typename?: 'FindAvailableSSOIDP', id: string, issuer: string, name: string, status: SsoIdentityProviderStatus, workspace: { __typename?: 'WorkspaceNameAndId', id: string, displayName?: string | null } }; export type AuthorizeAppMutationVariables = Exact<{ clientId: Scalars['String']; - codeChallenge: Scalars['String']; + codeChallenge?: InputMaybe; redirectUrl: Scalars['String']; }>; -export type AuthorizeAppMutation = { __typename?: 'Mutation', authorizeApp: { __typename?: 'AuthorizeAppOutput', redirectUrl: string } }; +export type AuthorizeAppMutation = { __typename?: 'Mutation', authorizeApp: { __typename?: 'AuthorizeApp', redirectUrl: string } }; export type EmailPasswordResetLinkMutationVariables = Exact<{ email: Scalars['String']; @@ -5586,7 +5752,7 @@ export type EmailPasswordResetLinkMutationVariables = Exact<{ }>; -export type EmailPasswordResetLinkMutation = { __typename?: 'Mutation', emailPasswordResetLink: { __typename?: 'EmailPasswordResetLinkOutput', success: boolean } }; +export type EmailPasswordResetLinkMutation = { __typename?: 'Mutation', emailPasswordResetLink: { __typename?: 'EmailPasswordResetLink', success: boolean } }; export type GenerateApiKeyTokenMutationVariables = Exact<{ apiKeyId: Scalars['UUID']; @@ -5599,7 +5765,7 @@ export type GenerateApiKeyTokenMutation = { __typename?: 'Mutation', generateApi export type GenerateTransientTokenMutationVariables = Exact<{ [key: string]: never; }>; -export type GenerateTransientTokenMutation = { __typename?: 'Mutation', generateTransientToken: { __typename?: 'TransientTokenOutput', transientToken: { __typename?: 'AuthToken', token: string } } }; +export type GenerateTransientTokenMutation = { __typename?: 'Mutation', generateTransientToken: { __typename?: 'TransientToken', transientToken: { __typename?: 'AuthToken', token: string } } }; export type GetAuthTokensFromLoginTokenMutationVariables = Exact<{ loginToken: Scalars['String']; @@ -5624,7 +5790,7 @@ export type GetAuthorizationUrlForSsoMutationVariables = Exact<{ }>; -export type GetAuthorizationUrlForSsoMutation = { __typename?: 'Mutation', getAuthorizationUrlForSSO: { __typename?: 'GetAuthorizationUrlForSSOOutput', id: string, type: string, authorizationURL: string } }; +export type GetAuthorizationUrlForSsoMutation = { __typename?: 'Mutation', getAuthorizationUrlForSSO: { __typename?: 'GetAuthorizationUrlForSSO', id: string, type: string, authorizationURL: string } }; export type GetLoginTokenFromCredentialsMutationVariables = Exact<{ email: Scalars['String']; @@ -5634,7 +5800,7 @@ export type GetLoginTokenFromCredentialsMutationVariables = Exact<{ }>; -export type GetLoginTokenFromCredentialsMutation = { __typename?: 'Mutation', getLoginTokenFromCredentials: { __typename?: 'LoginTokenOutput', loginToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } }; +export type GetLoginTokenFromCredentialsMutation = { __typename?: 'Mutation', getLoginTokenFromCredentials: { __typename?: 'LoginToken', loginToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } }; export type ImpersonateMutationVariables = Exact<{ userId: Scalars['UUID']; @@ -5642,7 +5808,7 @@ export type ImpersonateMutationVariables = Exact<{ }>; -export type ImpersonateMutation = { __typename?: 'Mutation', impersonate: { __typename?: 'ImpersonateOutput', workspace: { __typename?: 'WorkspaceUrlsAndId', id: string, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null } }, loginToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } }; +export type ImpersonateMutation = { __typename?: 'Mutation', impersonate: { __typename?: 'Impersonate', workspace: { __typename?: 'WorkspaceUrlsAndId', id: string, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null } }, loginToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } }; export type InitiateOtpProvisioningMutationVariables = Exact<{ loginToken: Scalars['String']; @@ -5650,12 +5816,12 @@ export type InitiateOtpProvisioningMutationVariables = Exact<{ }>; -export type InitiateOtpProvisioningMutation = { __typename?: 'Mutation', initiateOTPProvisioning: { __typename?: 'InitiateTwoFactorAuthenticationProvisioningOutput', uri: string } }; +export type InitiateOtpProvisioningMutation = { __typename?: 'Mutation', initiateOTPProvisioning: { __typename?: 'InitiateTwoFactorAuthenticationProvisioning', uri: string } }; export type InitiateOtpProvisioningForAuthenticatedUserMutationVariables = Exact<{ [key: string]: never; }>; -export type InitiateOtpProvisioningForAuthenticatedUserMutation = { __typename?: 'Mutation', initiateOTPProvisioningForAuthenticatedUser: { __typename?: 'InitiateTwoFactorAuthenticationProvisioningOutput', uri: string } }; +export type InitiateOtpProvisioningForAuthenticatedUserMutation = { __typename?: 'Mutation', initiateOTPProvisioningForAuthenticatedUser: { __typename?: 'InitiateTwoFactorAuthenticationProvisioning', uri: string } }; export type RenewTokenMutationVariables = Exact<{ appToken: Scalars['String']; @@ -5670,14 +5836,14 @@ export type ResendEmailVerificationTokenMutationVariables = Exact<{ }>; -export type ResendEmailVerificationTokenMutation = { __typename?: 'Mutation', resendEmailVerificationToken: { __typename?: 'ResendEmailVerificationTokenOutput', success: boolean } }; +export type ResendEmailVerificationTokenMutation = { __typename?: 'Mutation', resendEmailVerificationToken: { __typename?: 'ResendEmailVerificationToken', success: boolean } }; export type DeleteTwoFactorAuthenticationMethodMutationVariables = Exact<{ twoFactorAuthenticationMethodId: Scalars['UUID']; }>; -export type DeleteTwoFactorAuthenticationMethodMutation = { __typename?: 'Mutation', deleteTwoFactorAuthenticationMethod: { __typename?: 'DeleteTwoFactorAuthenticationMethodOutput', success: boolean } }; +export type DeleteTwoFactorAuthenticationMethodMutation = { __typename?: 'Mutation', deleteTwoFactorAuthenticationMethod: { __typename?: 'DeleteTwoFactorAuthenticationMethod', success: boolean } }; export type SignInMutationVariables = Exact<{ email: Scalars['String']; @@ -5686,7 +5852,7 @@ export type SignInMutationVariables = Exact<{ }>; -export type SignInMutation = { __typename?: 'Mutation', signIn: { __typename?: 'AvailableWorkspacesAndAccessTokensOutput', availableWorkspaces: { __typename?: 'AvailableWorkspaces', availableWorkspacesForSignIn: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }>, availableWorkspacesForSignUp: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }> }, tokens: { __typename?: 'AuthTokenPair', accessOrWorkspaceAgnosticToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } }; +export type SignInMutation = { __typename?: 'Mutation', signIn: { __typename?: 'AvailableWorkspacesAndAccessTokens', availableWorkspaces: { __typename?: 'AvailableWorkspaces', availableWorkspacesForSignIn: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }>, availableWorkspacesForSignUp: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }> }, tokens: { __typename?: 'AuthTokenPair', accessOrWorkspaceAgnosticToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } }; export type SignUpMutationVariables = Exact<{ email: Scalars['String']; @@ -5697,12 +5863,12 @@ export type SignUpMutationVariables = Exact<{ }>; -export type SignUpMutation = { __typename?: 'Mutation', signUp: { __typename?: 'AvailableWorkspacesAndAccessTokensOutput', availableWorkspaces: { __typename?: 'AvailableWorkspaces', availableWorkspacesForSignIn: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }>, availableWorkspacesForSignUp: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }> }, tokens: { __typename?: 'AuthTokenPair', accessOrWorkspaceAgnosticToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } }; +export type SignUpMutation = { __typename?: 'Mutation', signUp: { __typename?: 'AvailableWorkspacesAndAccessTokens', availableWorkspaces: { __typename?: 'AvailableWorkspaces', availableWorkspacesForSignIn: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }>, availableWorkspacesForSignUp: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }> }, tokens: { __typename?: 'AuthTokenPair', accessOrWorkspaceAgnosticToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } }; export type SignUpInNewWorkspaceMutationVariables = Exact<{ [key: string]: never; }>; -export type SignUpInNewWorkspaceMutation = { __typename?: 'Mutation', signUpInNewWorkspace: { __typename?: 'SignUpOutput', loginToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, workspace: { __typename?: 'WorkspaceUrlsAndId', id: string, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null } } } }; +export type SignUpInNewWorkspaceMutation = { __typename?: 'Mutation', signUpInNewWorkspace: { __typename?: 'SignUp', loginToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, workspace: { __typename?: 'WorkspaceUrlsAndId', id: string, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null } } } }; export type SignUpInWorkspaceMutationVariables = Exact<{ email: Scalars['String']; @@ -5716,7 +5882,7 @@ export type SignUpInWorkspaceMutationVariables = Exact<{ }>; -export type SignUpInWorkspaceMutation = { __typename?: 'Mutation', signUpInWorkspace: { __typename?: 'SignUpOutput', loginToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, workspace: { __typename?: 'WorkspaceUrlsAndId', id: string, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null } } } }; +export type SignUpInWorkspaceMutation = { __typename?: 'Mutation', signUpInWorkspace: { __typename?: 'SignUp', loginToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, workspace: { __typename?: 'WorkspaceUrlsAndId', id: string, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null } } } }; export type UpdatePasswordViaResetTokenMutationVariables = Exact<{ token: Scalars['String']; @@ -5724,7 +5890,7 @@ export type UpdatePasswordViaResetTokenMutationVariables = Exact<{ }>; -export type UpdatePasswordViaResetTokenMutation = { __typename?: 'Mutation', updatePasswordViaResetToken: { __typename?: 'InvalidatePasswordOutput', success: boolean } }; +export type UpdatePasswordViaResetTokenMutation = { __typename?: 'Mutation', updatePasswordViaResetToken: { __typename?: 'InvalidatePassword', success: boolean } }; export type VerifyEmailAndGetLoginTokenMutationVariables = Exact<{ emailVerificationToken: Scalars['String']; @@ -5734,7 +5900,7 @@ export type VerifyEmailAndGetLoginTokenMutationVariables = Exact<{ }>; -export type VerifyEmailAndGetLoginTokenMutation = { __typename?: 'Mutation', verifyEmailAndGetLoginToken: { __typename?: 'VerifyEmailAndGetLoginTokenOutput', loginToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null } } }; +export type VerifyEmailAndGetLoginTokenMutation = { __typename?: 'Mutation', verifyEmailAndGetLoginToken: { __typename?: 'VerifyEmailAndGetLoginToken', loginToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null } } }; export type VerifyEmailAndGetWorkspaceAgnosticTokenMutationVariables = Exact<{ emailVerificationToken: Scalars['String']; @@ -5743,7 +5909,7 @@ export type VerifyEmailAndGetWorkspaceAgnosticTokenMutationVariables = Exact<{ }>; -export type VerifyEmailAndGetWorkspaceAgnosticTokenMutation = { __typename?: 'Mutation', verifyEmailAndGetWorkspaceAgnosticToken: { __typename?: 'AvailableWorkspacesAndAccessTokensOutput', availableWorkspaces: { __typename?: 'AvailableWorkspaces', availableWorkspacesForSignIn: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }>, availableWorkspacesForSignUp: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }> }, tokens: { __typename?: 'AuthTokenPair', accessOrWorkspaceAgnosticToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } }; +export type VerifyEmailAndGetWorkspaceAgnosticTokenMutation = { __typename?: 'Mutation', verifyEmailAndGetWorkspaceAgnosticToken: { __typename?: 'AvailableWorkspacesAndAccessTokens', availableWorkspaces: { __typename?: 'AvailableWorkspaces', availableWorkspacesForSignIn: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }>, availableWorkspacesForSignUp: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }> }, tokens: { __typename?: 'AuthTokenPair', accessOrWorkspaceAgnosticToken: { __typename?: 'AuthToken', token: string, expiresAt: string }, refreshToken: { __typename?: 'AuthToken', token: string, expiresAt: string } } } }; export type CheckUserExistsQueryVariables = Exact<{ email: Scalars['String']; @@ -5751,21 +5917,21 @@ export type CheckUserExistsQueryVariables = Exact<{ }>; -export type CheckUserExistsQuery = { __typename?: 'Query', checkUserExists: { __typename?: 'CheckUserExistOutput', exists: boolean, availableWorkspacesCount: number, isEmailVerified: boolean } }; +export type CheckUserExistsQuery = { __typename?: 'Query', checkUserExists: { __typename?: 'CheckUserExist', exists: boolean, availableWorkspacesCount: number, isEmailVerified: boolean } }; export type GetPublicWorkspaceDataByDomainQueryVariables = Exact<{ origin: Scalars['String']; }>; -export type GetPublicWorkspaceDataByDomainQuery = { __typename?: 'Query', getPublicWorkspaceDataByDomain: { __typename?: 'PublicWorkspaceDataOutput', id: string, logo?: string | null, displayName?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, authProviders: { __typename?: 'AuthProviders', google: boolean, magicLink: boolean, password: boolean, microsoft: boolean, sso: Array<{ __typename?: 'SSOIdentityProvider', id: string, name: string, type: IdentityProviderType, status: SsoIdentityProviderStatus, issuer: string }> }, authBypassProviders?: { __typename?: 'AuthBypassProviders', google: boolean, password: boolean, microsoft: boolean } | null } }; +export type GetPublicWorkspaceDataByDomainQuery = { __typename?: 'Query', getPublicWorkspaceDataByDomain: { __typename?: 'PublicWorkspaceData', id: string, logo?: string | null, displayName?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, authProviders: { __typename?: 'AuthProviders', google: boolean, magicLink: boolean, password: boolean, microsoft: boolean, sso: Array<{ __typename?: 'SSOIdentityProvider', id: string, name: string, type: IdentityProviderType, status: SsoIdentityProviderStatus, issuer: string }> }, authBypassProviders?: { __typename?: 'AuthBypassProviders', google: boolean, password: boolean, microsoft: boolean } | null } }; export type ValidatePasswordResetTokenQueryVariables = Exact<{ token: Scalars['String']; }>; -export type ValidatePasswordResetTokenQuery = { __typename?: 'Query', validatePasswordResetToken: { __typename?: 'ValidatePasswordResetTokenOutput', id: string, email: string, hasPassword: boolean } }; +export type ValidatePasswordResetTokenQuery = { __typename?: 'Query', validatePasswordResetToken: { __typename?: 'ValidatePasswordResetToken', id: string, email: string, hasPassword: boolean } }; export type BillingPriceLicensedFragmentFragment = { __typename?: 'BillingPriceLicensed', stripePriceId: string, unitAmount: number, recurringInterval: SubscriptionInterval, priceUsageType: BillingUsageType }; @@ -5778,17 +5944,17 @@ export type BillingSubscriptionSchedulePhaseItemFragmentFragment = { __typename? export type CancelSwitchBillingIntervalMutationVariables = Exact<{ [key: string]: never; }>; -export type CancelSwitchBillingIntervalMutation = { __typename?: 'Mutation', cancelSwitchBillingInterval: { __typename?: 'BillingUpdateOutput', currentBillingSubscription: { __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, interval?: SubscriptionInterval | null, metadata: any, currentPeriodEnd?: string | null, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }>, billingSubscriptionItems?: Array<{ __typename?: 'BillingSubscriptionItemDTO', id: string, hasReachedCurrentPeriodCap: boolean, quantity?: number | null, stripePriceId: string, billingProduct: { __typename?: 'BillingLicensedProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } | { __typename?: 'BillingMeteredProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } }> | null }, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, metadata: any, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }> }> } }; +export type CancelSwitchBillingIntervalMutation = { __typename?: 'Mutation', cancelSwitchBillingInterval: { __typename?: 'BillingUpdate', currentBillingSubscription: { __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, interval?: SubscriptionInterval | null, metadata: any, currentPeriodEnd?: string | null, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }>, billingSubscriptionItems?: Array<{ __typename?: 'BillingSubscriptionItem', id: string, hasReachedCurrentPeriodCap: boolean, quantity?: number | null, stripePriceId: string, billingProduct: { __typename?: 'BillingLicensedProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } | { __typename?: 'BillingMeteredProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } }> | null }, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, metadata: any, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }> }> } }; export type CancelSwitchMeteredPriceMutationVariables = Exact<{ [key: string]: never; }>; -export type CancelSwitchMeteredPriceMutation = { __typename?: 'Mutation', cancelSwitchMeteredPrice: { __typename?: 'BillingUpdateOutput', currentBillingSubscription: { __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, interval?: SubscriptionInterval | null, metadata: any, currentPeriodEnd?: string | null, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }>, billingSubscriptionItems?: Array<{ __typename?: 'BillingSubscriptionItemDTO', id: string, hasReachedCurrentPeriodCap: boolean, quantity?: number | null, stripePriceId: string, billingProduct: { __typename?: 'BillingLicensedProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } | { __typename?: 'BillingMeteredProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } }> | null }, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, metadata: any, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }> }> } }; +export type CancelSwitchMeteredPriceMutation = { __typename?: 'Mutation', cancelSwitchMeteredPrice: { __typename?: 'BillingUpdate', currentBillingSubscription: { __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, interval?: SubscriptionInterval | null, metadata: any, currentPeriodEnd?: string | null, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }>, billingSubscriptionItems?: Array<{ __typename?: 'BillingSubscriptionItem', id: string, hasReachedCurrentPeriodCap: boolean, quantity?: number | null, stripePriceId: string, billingProduct: { __typename?: 'BillingLicensedProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } | { __typename?: 'BillingMeteredProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } }> | null }, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, metadata: any, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }> }> } }; export type CancelSwitchBillingPlanMutationVariables = Exact<{ [key: string]: never; }>; -export type CancelSwitchBillingPlanMutation = { __typename?: 'Mutation', cancelSwitchBillingPlan: { __typename?: 'BillingUpdateOutput', currentBillingSubscription: { __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, interval?: SubscriptionInterval | null, metadata: any, currentPeriodEnd?: string | null, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }>, billingSubscriptionItems?: Array<{ __typename?: 'BillingSubscriptionItemDTO', id: string, hasReachedCurrentPeriodCap: boolean, quantity?: number | null, stripePriceId: string, billingProduct: { __typename?: 'BillingLicensedProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } | { __typename?: 'BillingMeteredProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } }> | null }, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, metadata: any, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }> }> } }; +export type CancelSwitchBillingPlanMutation = { __typename?: 'Mutation', cancelSwitchBillingPlan: { __typename?: 'BillingUpdate', currentBillingSubscription: { __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, interval?: SubscriptionInterval | null, metadata: any, currentPeriodEnd?: string | null, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }>, billingSubscriptionItems?: Array<{ __typename?: 'BillingSubscriptionItem', id: string, hasReachedCurrentPeriodCap: boolean, quantity?: number | null, stripePriceId: string, billingProduct: { __typename?: 'BillingLicensedProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } | { __typename?: 'BillingMeteredProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } }> | null }, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, metadata: any, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }> }> } }; export type CheckoutSessionMutationVariables = Exact<{ recurringInterval: SubscriptionInterval; @@ -5798,46 +5964,46 @@ export type CheckoutSessionMutationVariables = Exact<{ }>; -export type CheckoutSessionMutation = { __typename?: 'Mutation', checkoutSession: { __typename?: 'BillingSessionOutput', url?: string | null } }; +export type CheckoutSessionMutation = { __typename?: 'Mutation', checkoutSession: { __typename?: 'BillingSession', url?: string | null } }; export type EndSubscriptionTrialPeriodMutationVariables = Exact<{ [key: string]: never; }>; -export type EndSubscriptionTrialPeriodMutation = { __typename?: 'Mutation', endSubscriptionTrialPeriod: { __typename?: 'BillingEndTrialPeriodOutput', status?: SubscriptionStatus | null, hasPaymentMethod: boolean, billingPortalUrl?: string | null } }; +export type EndSubscriptionTrialPeriodMutation = { __typename?: 'Mutation', endSubscriptionTrialPeriod: { __typename?: 'BillingEndTrialPeriod', status?: SubscriptionStatus | null, hasPaymentMethod: boolean, billingPortalUrl?: string | null } }; export type SetMeteredSubscriptionPriceMutationVariables = Exact<{ priceId: Scalars['String']; }>; -export type SetMeteredSubscriptionPriceMutation = { __typename?: 'Mutation', setMeteredSubscriptionPrice: { __typename?: 'BillingUpdateOutput', currentBillingSubscription: { __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, interval?: SubscriptionInterval | null, metadata: any, currentPeriodEnd?: string | null, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }>, billingSubscriptionItems?: Array<{ __typename?: 'BillingSubscriptionItemDTO', id: string, hasReachedCurrentPeriodCap: boolean, quantity?: number | null, stripePriceId: string, billingProduct: { __typename?: 'BillingLicensedProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } | { __typename?: 'BillingMeteredProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } }> | null }, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, metadata: any, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }> }> } }; +export type SetMeteredSubscriptionPriceMutation = { __typename?: 'Mutation', setMeteredSubscriptionPrice: { __typename?: 'BillingUpdate', currentBillingSubscription: { __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, interval?: SubscriptionInterval | null, metadata: any, currentPeriodEnd?: string | null, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }>, billingSubscriptionItems?: Array<{ __typename?: 'BillingSubscriptionItem', id: string, hasReachedCurrentPeriodCap: boolean, quantity?: number | null, stripePriceId: string, billingProduct: { __typename?: 'BillingLicensedProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } | { __typename?: 'BillingMeteredProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } }> | null }, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, metadata: any, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }> }> } }; export type SwitchBillingPlanMutationVariables = Exact<{ [key: string]: never; }>; -export type SwitchBillingPlanMutation = { __typename?: 'Mutation', switchBillingPlan: { __typename?: 'BillingUpdateOutput', currentBillingSubscription: { __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, interval?: SubscriptionInterval | null, metadata: any, currentPeriodEnd?: string | null, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }>, billingSubscriptionItems?: Array<{ __typename?: 'BillingSubscriptionItemDTO', id: string, hasReachedCurrentPeriodCap: boolean, quantity?: number | null, stripePriceId: string, billingProduct: { __typename?: 'BillingLicensedProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } | { __typename?: 'BillingMeteredProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } }> | null }, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, metadata: any, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }> }> } }; +export type SwitchBillingPlanMutation = { __typename?: 'Mutation', switchBillingPlan: { __typename?: 'BillingUpdate', currentBillingSubscription: { __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, interval?: SubscriptionInterval | null, metadata: any, currentPeriodEnd?: string | null, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }>, billingSubscriptionItems?: Array<{ __typename?: 'BillingSubscriptionItem', id: string, hasReachedCurrentPeriodCap: boolean, quantity?: number | null, stripePriceId: string, billingProduct: { __typename?: 'BillingLicensedProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } | { __typename?: 'BillingMeteredProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } }> | null }, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, metadata: any, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }> }> } }; export type SwitchSubscriptionIntervalMutationVariables = Exact<{ [key: string]: never; }>; -export type SwitchSubscriptionIntervalMutation = { __typename?: 'Mutation', switchSubscriptionInterval: { __typename?: 'BillingUpdateOutput', currentBillingSubscription: { __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, interval?: SubscriptionInterval | null, metadata: any, currentPeriodEnd?: string | null, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }>, billingSubscriptionItems?: Array<{ __typename?: 'BillingSubscriptionItemDTO', id: string, hasReachedCurrentPeriodCap: boolean, quantity?: number | null, stripePriceId: string, billingProduct: { __typename?: 'BillingLicensedProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } | { __typename?: 'BillingMeteredProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } }> | null }, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, metadata: any, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }> }> } }; +export type SwitchSubscriptionIntervalMutation = { __typename?: 'Mutation', switchSubscriptionInterval: { __typename?: 'BillingUpdate', currentBillingSubscription: { __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, interval?: SubscriptionInterval | null, metadata: any, currentPeriodEnd?: string | null, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }>, billingSubscriptionItems?: Array<{ __typename?: 'BillingSubscriptionItem', id: string, hasReachedCurrentPeriodCap: boolean, quantity?: number | null, stripePriceId: string, billingProduct: { __typename?: 'BillingLicensedProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } | { __typename?: 'BillingMeteredProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } }> | null }, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, metadata: any, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }> }> } }; export type BillingPortalSessionQueryVariables = Exact<{ returnUrlPath?: InputMaybe; }>; -export type BillingPortalSessionQuery = { __typename?: 'Query', billingPortalSession: { __typename?: 'BillingSessionOutput', url?: string | null } }; +export type BillingPortalSessionQuery = { __typename?: 'Query', billingPortalSession: { __typename?: 'BillingSession', url?: string | null } }; export type GetMeteredProductsUsageQueryVariables = Exact<{ [key: string]: never; }>; -export type GetMeteredProductsUsageQuery = { __typename?: 'Query', getMeteredProductsUsage: Array<{ __typename?: 'BillingMeteredProductUsageOutput', productKey: BillingProductKey, usedCredits: number, grantedCredits: number, rolloverCredits: number, totalGrantedCredits: number, unitPriceCents: number }> }; +export type GetMeteredProductsUsageQuery = { __typename?: 'Query', getMeteredProductsUsage: Array<{ __typename?: 'BillingMeteredProductUsage', productKey: BillingProductKey, usedCredits: number, grantedCredits: number, rolloverCredits: number, totalGrantedCredits: number, unitPriceCents: number }> }; export type ListPlansQueryVariables = Exact<{ [key: string]: never; }>; -export type ListPlansQuery = { __typename?: 'Query', listPlans: Array<{ __typename?: 'BillingPlanOutput', planKey: BillingPlanKey, licensedProducts: Array<{ __typename?: 'BillingLicensedProduct', name: string, description: string, images?: Array | null, prices?: Array<{ __typename?: 'BillingPriceLicensed', stripePriceId: string, unitAmount: number, recurringInterval: SubscriptionInterval, priceUsageType: BillingUsageType }> | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } }>, meteredProducts: Array<{ __typename?: 'BillingMeteredProduct', name: string, description: string, images?: Array | null, prices?: Array<{ __typename?: 'BillingPriceMetered', priceUsageType: BillingUsageType, recurringInterval: SubscriptionInterval, stripePriceId: string, tiers: Array<{ __typename?: 'BillingPriceTier', flatAmount?: number | null, unitAmount?: number | null, upTo?: number | null }> }> | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } }> }> }; +export type ListPlansQuery = { __typename?: 'Query', listPlans: Array<{ __typename?: 'BillingPlan', planKey: BillingPlanKey, licensedProducts: Array<{ __typename?: 'BillingLicensedProduct', name: string, description: string, images?: Array | null, prices?: Array<{ __typename?: 'BillingPriceLicensed', stripePriceId: string, unitAmount: number, recurringInterval: SubscriptionInterval, priceUsageType: BillingUsageType }> | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } }>, meteredProducts: Array<{ __typename?: 'BillingMeteredProduct', name: string, description: string, images?: Array | null, prices?: Array<{ __typename?: 'BillingPriceMetered', priceUsageType: BillingUsageType, recurringInterval: SubscriptionInterval, stripePriceId: string, tiers: Array<{ __typename?: 'BillingPriceTier', flatAmount?: number | null, unitAmount?: number | null, upTo?: number | null }> }> | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } }> }> }; export type CommandMenuItemFieldsFragment = { __typename?: 'CommandMenuItem', id: string, workflowVersionId?: string | null, frontComponentId?: string | null, label: string, icon?: string | null, isPinned: boolean, availabilityType: CommandMenuItemAvailabilityType, availabilityObjectMetadataId?: string | null, frontComponent?: { __typename?: 'FrontComponent', id: string, name: string, isHeadless: boolean } | null }; @@ -6105,21 +6271,21 @@ export type BarChartDataQueryVariables = Exact<{ }>; -export type BarChartDataQuery = { __typename?: 'Query', barChartData: { __typename?: 'BarChartDataOutput', data: Array, indexBy: string, keys: Array, xAxisLabel: string, yAxisLabel: string, showLegend: boolean, showDataLabels: boolean, layout: BarChartLayout, groupMode: BarChartGroupMode, hasTooManyGroups: boolean, formattedToRawLookup: any, series: Array<{ __typename?: 'BarChartSeries', key: string, label: string }> } }; +export type BarChartDataQuery = { __typename?: 'Query', barChartData: { __typename?: 'BarChartData', data: Array, indexBy: string, keys: Array, xAxisLabel: string, yAxisLabel: string, showLegend: boolean, showDataLabels: boolean, layout: BarChartLayout, groupMode: BarChartGroupMode, hasTooManyGroups: boolean, formattedToRawLookup: any, series: Array<{ __typename?: 'BarChartSeries', key: string, label: string }> } }; export type LineChartDataQueryVariables = Exact<{ input: LineChartDataInput; }>; -export type LineChartDataQuery = { __typename?: 'Query', lineChartData: { __typename?: 'LineChartDataOutput', xAxisLabel: string, yAxisLabel: string, showLegend: boolean, showDataLabels: boolean, hasTooManyGroups: boolean, formattedToRawLookup: any, series: Array<{ __typename?: 'LineChartSeries', id: string, label: string, data: Array<{ __typename?: 'LineChartDataPoint', x: string, y: number }> }> } }; +export type LineChartDataQuery = { __typename?: 'Query', lineChartData: { __typename?: 'LineChartData', xAxisLabel: string, yAxisLabel: string, showLegend: boolean, showDataLabels: boolean, hasTooManyGroups: boolean, formattedToRawLookup: any, series: Array<{ __typename?: 'LineChartSeries', id: string, label: string, data: Array<{ __typename?: 'LineChartDataPoint', x: string, y: number }> }> } }; export type PieChartDataQueryVariables = Exact<{ input: PieChartDataInput; }>; -export type PieChartDataQuery = { __typename?: 'Query', pieChartData: { __typename?: 'PieChartDataOutput', showLegend: boolean, showDataLabels: boolean, showCenterMetric: boolean, hasTooManyGroups: boolean, formattedToRawLookup: any, data: Array<{ __typename?: 'PieChartDataItem', id: string, value: number }> } }; +export type PieChartDataQuery = { __typename?: 'Query', pieChartData: { __typename?: 'PieChartData', showLegend: boolean, showDataLabels: boolean, showCenterMetric: boolean, hasTooManyGroups: boolean, formattedToRawLookup: any, data: Array<{ __typename?: 'PieChartDataItem', id: string, value: number }> } }; export type SaveImapSmtpCaldavAccountMutationVariables = Exact<{ accountOwnerId: Scalars['UUID']; @@ -6156,7 +6322,7 @@ export type SetAdminAiModelEnabledMutation = { __typename?: 'Mutation', setAdmin export type GetAdminAiModelsQueryVariables = Exact<{ [key: string]: never; }>; -export type GetAdminAiModelsQuery = { __typename?: 'Query', getAdminAiModels: { __typename?: 'AdminAIModelsOutput', autoEnableNewModels: boolean, models: Array<{ __typename?: 'AdminAIModelConfig', modelId: string, label: string, modelFamily?: ModelFamily | null, inferenceProvider: InferenceProvider, isAvailable: boolean, isAdminEnabled: boolean, deprecated?: boolean | null, isRecommended?: boolean | null }> } }; +export type GetAdminAiModelsQuery = { __typename?: 'Query', getAdminAiModels: { __typename?: 'AdminAIModels', autoEnableNewModels: boolean, models: Array<{ __typename?: 'AdminAIModelConfig', modelId: string, label: string, modelFamily?: ModelFamily | null, inferenceProvider: InferenceProvider, isAvailable: boolean, isAdminEnabled: boolean, deprecated?: boolean | null, isRecommended?: boolean | null }> } }; export type CreateDatabaseConfigVariableMutationVariables = Exact<{ key: Scalars['String']; @@ -6184,7 +6350,7 @@ export type UpdateDatabaseConfigVariableMutation = { __typename?: 'Mutation', up export type GetConfigVariablesGroupedQueryVariables = Exact<{ [key: string]: never; }>; -export type GetConfigVariablesGroupedQuery = { __typename?: 'Query', getConfigVariablesGrouped: { __typename?: 'ConfigVariablesOutput', groups: Array<{ __typename?: 'ConfigVariablesGroupData', name: ConfigVariablesGroup, description: string, isHiddenOnLoad: boolean, variables: Array<{ __typename?: 'ConfigVariable', name: string, description: string, value?: any | null, isSensitive: boolean, isEnvOnly: boolean, type: ConfigVariableType, options?: any | null, source: ConfigSource }> }> } }; +export type GetConfigVariablesGroupedQuery = { __typename?: 'Query', getConfigVariablesGrouped: { __typename?: 'ConfigVariables', groups: Array<{ __typename?: 'ConfigVariablesGroupData', name: ConfigVariablesGroup, description: string, isHiddenOnLoad: boolean, variables: Array<{ __typename?: 'ConfigVariable', name: string, description: string, value?: any | null, isSensitive: boolean, isEnvOnly: boolean, type: ConfigVariableType, options?: any | null, source: ConfigSource }> }> } }; export type GetDatabaseConfigVariableQueryVariables = Exact<{ key: Scalars['String']; @@ -6260,6 +6426,69 @@ export type GetSystemHealthStatusQueryVariables = Exact<{ [key: string]: never; export type GetSystemHealthStatusQuery = { __typename?: 'Query', getSystemHealthStatus: { __typename?: 'SystemHealth', services: Array<{ __typename?: 'SystemHealthService', id: HealthIndicatorId, label: string, status: AdminPanelHealthServiceStatus }> } }; +export type ApplicationRegistrationFragmentFragment = { __typename?: 'ApplicationRegistration', id: string, universalIdentifier: string, name: string, description?: string | null, logoUrl?: string | null, author?: string | null, oAuthClientId: string, oAuthRedirectUris: Array, oAuthScopes: Array, websiteUrl?: string | null, termsUrl?: string | null, createdAt: string, updatedAt: string }; + +export type DeleteApplicationRegistrationMutationVariables = Exact<{ + id: Scalars['String']; +}>; + + +export type DeleteApplicationRegistrationMutation = { __typename?: 'Mutation', deleteApplicationRegistration: boolean }; + +export type RotateApplicationRegistrationClientSecretMutationVariables = Exact<{ + id: Scalars['String']; +}>; + + +export type RotateApplicationRegistrationClientSecretMutation = { __typename?: 'Mutation', rotateApplicationRegistrationClientSecret: { __typename?: 'RotateClientSecret', clientSecret: string } }; + +export type UpdateApplicationRegistrationMutationVariables = Exact<{ + input: UpdateApplicationRegistrationInput; +}>; + + +export type UpdateApplicationRegistrationMutation = { __typename?: 'Mutation', updateApplicationRegistration: { __typename?: 'ApplicationRegistration', id: string, universalIdentifier: string, name: string, description?: string | null, logoUrl?: string | null, author?: string | null, oAuthClientId: string, oAuthRedirectUris: Array, oAuthScopes: Array, websiteUrl?: string | null, termsUrl?: string | null, createdAt: string, updatedAt: string } }; + +export type UpdateApplicationRegistrationVariableMutationVariables = Exact<{ + input: UpdateApplicationRegistrationVariableInput; +}>; + + +export type UpdateApplicationRegistrationVariableMutation = { __typename?: 'Mutation', updateApplicationRegistrationVariable: { __typename?: 'ApplicationRegistrationVariable', id: string, key: string, description: string, isSecret: boolean, isRequired: boolean, isFilled: boolean, createdAt: string, updatedAt: string } }; + +export type FindApplicationRegistrationByClientIdQueryVariables = Exact<{ + clientId: Scalars['String']; +}>; + + +export type FindApplicationRegistrationByClientIdQuery = { __typename?: 'Query', findApplicationRegistrationByClientId?: { __typename?: 'ApplicationRegistration', id: string, name: string, oAuthScopes: Array, websiteUrl?: string | null, logoUrl?: string | null } | null }; + +export type FindApplicationRegistrationStatsQueryVariables = Exact<{ + id: Scalars['String']; +}>; + + +export type FindApplicationRegistrationStatsQuery = { __typename?: 'Query', findApplicationRegistrationStats: { __typename?: 'ApplicationRegistrationStats', activeInstalls: number, mostInstalledVersion?: string | null, versionDistribution: Array<{ __typename?: 'VersionDistributionEntry', version: string, count: number }> } }; + +export type FindApplicationRegistrationVariablesQueryVariables = Exact<{ + applicationRegistrationId: Scalars['String']; +}>; + + +export type FindApplicationRegistrationVariablesQuery = { __typename?: 'Query', findApplicationRegistrationVariables: Array<{ __typename?: 'ApplicationRegistrationVariable', id: string, key: string, description: string, isSecret: boolean, isRequired: boolean, isFilled: boolean, createdAt: string, updatedAt: string }> }; + +export type FindManyApplicationRegistrationsQueryVariables = Exact<{ [key: string]: never; }>; + + +export type FindManyApplicationRegistrationsQuery = { __typename?: 'Query', findManyApplicationRegistrations: Array<{ __typename?: 'ApplicationRegistration', id: string, universalIdentifier: string, name: string, description?: string | null, logoUrl?: string | null, author?: string | null, oAuthClientId: string, oAuthRedirectUris: Array, oAuthScopes: Array, websiteUrl?: string | null, termsUrl?: string | null, createdAt: string, updatedAt: string }> }; + +export type FindOneApplicationRegistrationQueryVariables = Exact<{ + id: Scalars['String']; +}>; + + +export type FindOneApplicationRegistrationQuery = { __typename?: 'Query', findOneApplicationRegistration: { __typename?: 'ApplicationRegistration', id: string, universalIdentifier: string, name: string, description?: string | null, logoUrl?: string | null, author?: string | null, oAuthClientId: string, oAuthRedirectUris: Array, oAuthScopes: Array, websiteUrl?: string | null, termsUrl?: string | null, createdAt: string, updatedAt: string } }; + export type UninstallApplicationMutationVariables = Exact<{ universalIdentifier: Scalars['String']; }>; @@ -6403,7 +6632,7 @@ export type UpdateLabPublicFeatureFlagMutationVariables = Exact<{ }>; -export type UpdateLabPublicFeatureFlagMutation = { __typename?: 'Mutation', updateLabPublicFeatureFlag: { __typename?: 'FeatureFlagDTO', key: FeatureFlagKey, value: boolean } }; +export type UpdateLabPublicFeatureFlagMutation = { __typename?: 'Mutation', updateLabPublicFeatureFlag: { __typename?: 'FeatureFlag', key: FeatureFlagKey, value: boolean } }; export type UploadWorkspaceMemberProfilePictureMutationVariables = Exact<{ file: Scalars['Upload']; @@ -6515,14 +6744,14 @@ export type CreateOidcIdentityProviderMutationVariables = Exact<{ }>; -export type CreateOidcIdentityProviderMutation = { __typename?: 'Mutation', createOIDCIdentityProvider: { __typename?: 'SetupSsoOutput', id: string, type: IdentityProviderType, issuer: string, name: string, status: SsoIdentityProviderStatus } }; +export type CreateOidcIdentityProviderMutation = { __typename?: 'Mutation', createOIDCIdentityProvider: { __typename?: 'SetupSso', id: string, type: IdentityProviderType, issuer: string, name: string, status: SsoIdentityProviderStatus } }; export type CreateSamlIdentityProviderMutationVariables = Exact<{ input: SetupSamlSsoInput; }>; -export type CreateSamlIdentityProviderMutation = { __typename?: 'Mutation', createSAMLIdentityProvider: { __typename?: 'SetupSsoOutput', id: string, type: IdentityProviderType, issuer: string, name: string, status: SsoIdentityProviderStatus } }; +export type CreateSamlIdentityProviderMutation = { __typename?: 'Mutation', createSAMLIdentityProvider: { __typename?: 'SetupSso', id: string, type: IdentityProviderType, issuer: string, name: string, status: SsoIdentityProviderStatus } }; export type DeleteApprovedAccessDomainMutationVariables = Exact<{ input: DeleteApprovedAccessDomainInput; @@ -6536,14 +6765,14 @@ export type DeleteSsoIdentityProviderMutationVariables = Exact<{ }>; -export type DeleteSsoIdentityProviderMutation = { __typename?: 'Mutation', deleteSSOIdentityProvider: { __typename?: 'DeleteSsoOutput', identityProviderId: string } }; +export type DeleteSsoIdentityProviderMutation = { __typename?: 'Mutation', deleteSSOIdentityProvider: { __typename?: 'DeleteSso', identityProviderId: string } }; export type EditSsoIdentityProviderMutationVariables = Exact<{ input: EditSsoInput; }>; -export type EditSsoIdentityProviderMutation = { __typename?: 'Mutation', editSSOIdentityProvider: { __typename?: 'EditSsoOutput', id: string, type: IdentityProviderType, issuer: string, name: string, status: SsoIdentityProviderStatus } }; +export type EditSsoIdentityProviderMutation = { __typename?: 'Mutation', editSSOIdentityProvider: { __typename?: 'EditSso', id: string, type: IdentityProviderType, issuer: string, name: string, status: SsoIdentityProviderStatus } }; export type ValidateApprovedAccessDomainMutationVariables = Exact<{ input: ValidateApprovedAccessDomainInput; @@ -6560,20 +6789,20 @@ export type GetApprovedAccessDomainsQuery = { __typename?: 'Query', getApprovedA export type GetSsoIdentityProvidersQueryVariables = Exact<{ [key: string]: never; }>; -export type GetSsoIdentityProvidersQuery = { __typename?: 'Query', getSSOIdentityProviders: Array<{ __typename?: 'FindAvailableSSOIDPOutput', type: IdentityProviderType, id: string, name: string, issuer: string, status: SsoIdentityProviderStatus }> }; +export type GetSsoIdentityProvidersQuery = { __typename?: 'Query', getSSOIdentityProviders: Array<{ __typename?: 'FindAvailableSSOIDP', type: IdentityProviderType, id: string, name: string, issuer: string, status: SsoIdentityProviderStatus }> }; export type VerifyTwoFactorAuthenticationMethodForAuthenticatedUserMutationVariables = Exact<{ otp: Scalars['String']; }>; -export type VerifyTwoFactorAuthenticationMethodForAuthenticatedUserMutation = { __typename?: 'Mutation', verifyTwoFactorAuthenticationMethodForAuthenticatedUser: { __typename?: 'VerifyTwoFactorAuthenticationMethodOutput', success: boolean } }; +export type VerifyTwoFactorAuthenticationMethodForAuthenticatedUserMutation = { __typename?: 'Mutation', verifyTwoFactorAuthenticationMethodForAuthenticatedUser: { __typename?: 'VerifyTwoFactorAuthenticationMethod', success: boolean } }; export type BillingSubscriptionFragmentFragment = { __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, metadata: any, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }> }; -export type CurrentBillingSubscriptionFragmentFragment = { __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, interval?: SubscriptionInterval | null, metadata: any, currentPeriodEnd?: string | null, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }>, billingSubscriptionItems?: Array<{ __typename?: 'BillingSubscriptionItemDTO', id: string, hasReachedCurrentPeriodCap: boolean, quantity?: number | null, stripePriceId: string, billingProduct: { __typename?: 'BillingLicensedProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } | { __typename?: 'BillingMeteredProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } }> | null }; +export type CurrentBillingSubscriptionFragmentFragment = { __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, interval?: SubscriptionInterval | null, metadata: any, currentPeriodEnd?: string | null, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }>, billingSubscriptionItems?: Array<{ __typename?: 'BillingSubscriptionItem', id: string, hasReachedCurrentPeriodCap: boolean, quantity?: number | null, stripePriceId: string, billingProduct: { __typename?: 'BillingLicensedProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } | { __typename?: 'BillingMeteredProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } }> | null }; -export type UserQueryFragmentFragment = { __typename?: 'User', id: string, firstName: string, lastName: string, email: string, hasPassword: boolean, canAccessFullAdminPanel: boolean, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars?: any | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: string, colorScheme: string, avatarUrl?: string | null, locale?: string | null, userEmail: string, userWorkspaceId?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, calendarStartDay?: number | null, numberFormat?: WorkspaceMemberNumberFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: string, avatarUrl?: string | null, userEmail: string, userWorkspaceId?: string | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, deletedWorkspaceMembers?: Array<{ __typename?: 'DeletedWorkspaceMember', id: string, avatarUrl?: string | null, userEmail: string, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, currentUserWorkspace?: { __typename?: 'UserWorkspace', id: string, permissionFlags?: Array | null, objectsPermissions?: Array<{ __typename?: 'ObjectPermission', objectMetadataId: string, canReadObjectRecords?: boolean | null, canUpdateObjectRecords?: boolean | null, canSoftDeleteObjectRecords?: boolean | null, canDestroyObjectRecords?: boolean | null, restrictedFields?: any | null, rowLevelPermissionPredicates?: Array<{ __typename?: 'RowLevelPermissionPredicate', id: string, fieldMetadataId: string, objectMetadataId: string, operand: RowLevelPermissionPredicateOperand, subFieldName?: string | null, workspaceMemberFieldMetadataId?: string | null, workspaceMemberSubFieldName?: string | null, rowLevelPermissionPredicateGroupId?: string | null, positionInRowLevelPermissionPredicateGroup?: number | null, roleId: string, value?: any | null }> | null, rowLevelPermissionPredicateGroups?: Array<{ __typename?: 'RowLevelPermissionPredicateGroup', id: string, parentRowLevelPermissionPredicateGroupId?: string | null, logicalOperator: RowLevelPermissionPredicateGroupLogicalOperator, positionInRowLevelPermissionPredicateGroup?: number | null, roleId: string, objectMetadataId: string }> | null }> | null, twoFactorAuthenticationMethodSummary?: Array<{ __typename?: 'TwoFactorAuthenticationMethodDTO', twoFactorAuthenticationMethodId: string, status: string, strategy: string }> | null } | null, currentWorkspace?: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, isPublicInviteLinkEnabled: boolean, isGoogleAuthEnabled: boolean, isMicrosoftAuthEnabled: boolean, isPasswordAuthEnabled: boolean, isGoogleAuthBypassEnabled: boolean, isMicrosoftAuthBypassEnabled: boolean, isPasswordAuthBypassEnabled: boolean, subdomain: string, customDomain?: string | null, hasValidEnterpriseKey: boolean, isCustomDomainEnabled: boolean, metadataVersion: number, workspaceMembersCount?: number | null, fastModel: string, smartModel: string, aiAdditionalInstructions?: string | null, autoEnableNewAiModels: boolean, disabledAiModelIds?: Array | null, enabledAiModelIds?: Array | null, useRecommendedModels: boolean, isTwoFactorAuthenticationEnforced: boolean, trashRetentionDays: number, eventLogRetentionDays: number, editableProfileFields?: Array | null, workspaceCustomApplication?: { __typename?: 'Application', id: string } | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, featureFlags?: Array<{ __typename?: 'FeatureFlagDTO', key: FeatureFlagKey, value: boolean }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, interval?: SubscriptionInterval | null, metadata: any, currentPeriodEnd?: string | null, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }>, billingSubscriptionItems?: Array<{ __typename?: 'BillingSubscriptionItemDTO', id: string, hasReachedCurrentPeriodCap: boolean, quantity?: number | null, stripePriceId: string, billingProduct: { __typename?: 'BillingLicensedProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } | { __typename?: 'BillingMeteredProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } }> | null } | null, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, metadata: any, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }> }>, billingEntitlements: Array<{ __typename?: 'BillingEntitlement', key: BillingEntitlementKey, value: boolean }>, defaultRole?: { __typename?: 'Role', id: string, label: string, description?: string | null, icon?: string | null, canUpdateAllSettings: boolean, canAccessAllTools: boolean, isEditable: boolean, canReadAllObjectRecords: boolean, canUpdateAllObjectRecords: boolean, canSoftDeleteAllObjectRecords: boolean, canDestroyAllObjectRecords: boolean, canBeAssignedToUsers: boolean, canBeAssignedToAgents: boolean, canBeAssignedToApiKeys: boolean } | null } | null, availableWorkspaces: { __typename?: 'AvailableWorkspaces', availableWorkspacesForSignIn: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }>, availableWorkspacesForSignUp: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }> } }; +export type UserQueryFragmentFragment = { __typename?: 'User', id: string, firstName: string, lastName: string, email: string, hasPassword: boolean, canAccessFullAdminPanel: boolean, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars?: any | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: string, colorScheme: string, avatarUrl?: string | null, locale?: string | null, userEmail: string, userWorkspaceId?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, calendarStartDay?: number | null, numberFormat?: WorkspaceMemberNumberFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: string, avatarUrl?: string | null, userEmail: string, userWorkspaceId?: string | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, deletedWorkspaceMembers?: Array<{ __typename?: 'DeletedWorkspaceMember', id: string, avatarUrl?: string | null, userEmail: string, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, currentUserWorkspace?: { __typename?: 'UserWorkspace', id: string, permissionFlags?: Array | null, objectsPermissions?: Array<{ __typename?: 'ObjectPermission', objectMetadataId: string, canReadObjectRecords?: boolean | null, canUpdateObjectRecords?: boolean | null, canSoftDeleteObjectRecords?: boolean | null, canDestroyObjectRecords?: boolean | null, restrictedFields?: any | null, rowLevelPermissionPredicates?: Array<{ __typename?: 'RowLevelPermissionPredicate', id: string, fieldMetadataId: string, objectMetadataId: string, operand: RowLevelPermissionPredicateOperand, subFieldName?: string | null, workspaceMemberFieldMetadataId?: string | null, workspaceMemberSubFieldName?: string | null, rowLevelPermissionPredicateGroupId?: string | null, positionInRowLevelPermissionPredicateGroup?: number | null, roleId: string, value?: any | null }> | null, rowLevelPermissionPredicateGroups?: Array<{ __typename?: 'RowLevelPermissionPredicateGroup', id: string, parentRowLevelPermissionPredicateGroupId?: string | null, logicalOperator: RowLevelPermissionPredicateGroupLogicalOperator, positionInRowLevelPermissionPredicateGroup?: number | null, roleId: string, objectMetadataId: string }> | null }> | null, twoFactorAuthenticationMethodSummary?: Array<{ __typename?: 'TwoFactorAuthenticationMethodSummary', twoFactorAuthenticationMethodId: string, status: string, strategy: string }> | null } | null, currentWorkspace?: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, isPublicInviteLinkEnabled: boolean, isGoogleAuthEnabled: boolean, isMicrosoftAuthEnabled: boolean, isPasswordAuthEnabled: boolean, isGoogleAuthBypassEnabled: boolean, isMicrosoftAuthBypassEnabled: boolean, isPasswordAuthBypassEnabled: boolean, subdomain: string, customDomain?: string | null, hasValidEnterpriseKey: boolean, isCustomDomainEnabled: boolean, metadataVersion: number, workspaceMembersCount?: number | null, fastModel: string, smartModel: string, aiAdditionalInstructions?: string | null, autoEnableNewAiModels: boolean, disabledAiModelIds?: Array | null, enabledAiModelIds?: Array | null, useRecommendedModels: boolean, isTwoFactorAuthenticationEnforced: boolean, trashRetentionDays: number, eventLogRetentionDays: number, editableProfileFields?: Array | null, workspaceCustomApplication?: { __typename?: 'Application', id: string } | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, featureFlags?: Array<{ __typename?: 'FeatureFlag', key: FeatureFlagKey, value: boolean }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, interval?: SubscriptionInterval | null, metadata: any, currentPeriodEnd?: string | null, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }>, billingSubscriptionItems?: Array<{ __typename?: 'BillingSubscriptionItem', id: string, hasReachedCurrentPeriodCap: boolean, quantity?: number | null, stripePriceId: string, billingProduct: { __typename?: 'BillingLicensedProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } | { __typename?: 'BillingMeteredProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } }> | null } | null, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, metadata: any, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }> }>, billingEntitlements: Array<{ __typename?: 'BillingEntitlement', key: BillingEntitlementKey, value: boolean }>, defaultRole?: { __typename?: 'Role', id: string, label: string, description?: string | null, icon?: string | null, canUpdateAllSettings: boolean, canAccessAllTools: boolean, isEditable: boolean, canReadAllObjectRecords: boolean, canUpdateAllObjectRecords: boolean, canSoftDeleteAllObjectRecords: boolean, canDestroyAllObjectRecords: boolean, canBeAssignedToUsers: boolean, canBeAssignedToAgents: boolean, canBeAssignedToApiKeys: boolean } | null } | null, availableWorkspaces: { __typename?: 'AvailableWorkspaces', availableWorkspacesForSignIn: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }>, availableWorkspacesForSignUp: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }> } }; export type WorkspaceUrlsFragmentFragment = { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }; @@ -6592,7 +6821,7 @@ export type DeleteUserWorkspaceMutation = { __typename?: 'Mutation', deleteUserF export type GetCurrentUserQueryVariables = Exact<{ [key: string]: never; }>; -export type GetCurrentUserQuery = { __typename?: 'Query', currentUser: { __typename?: 'User', id: string, firstName: string, lastName: string, email: string, hasPassword: boolean, canAccessFullAdminPanel: boolean, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars?: any | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: string, colorScheme: string, avatarUrl?: string | null, locale?: string | null, userEmail: string, userWorkspaceId?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, calendarStartDay?: number | null, numberFormat?: WorkspaceMemberNumberFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: string, avatarUrl?: string | null, userEmail: string, userWorkspaceId?: string | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, deletedWorkspaceMembers?: Array<{ __typename?: 'DeletedWorkspaceMember', id: string, avatarUrl?: string | null, userEmail: string, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, currentUserWorkspace?: { __typename?: 'UserWorkspace', id: string, permissionFlags?: Array | null, objectsPermissions?: Array<{ __typename?: 'ObjectPermission', objectMetadataId: string, canReadObjectRecords?: boolean | null, canUpdateObjectRecords?: boolean | null, canSoftDeleteObjectRecords?: boolean | null, canDestroyObjectRecords?: boolean | null, restrictedFields?: any | null, rowLevelPermissionPredicates?: Array<{ __typename?: 'RowLevelPermissionPredicate', id: string, fieldMetadataId: string, objectMetadataId: string, operand: RowLevelPermissionPredicateOperand, subFieldName?: string | null, workspaceMemberFieldMetadataId?: string | null, workspaceMemberSubFieldName?: string | null, rowLevelPermissionPredicateGroupId?: string | null, positionInRowLevelPermissionPredicateGroup?: number | null, roleId: string, value?: any | null }> | null, rowLevelPermissionPredicateGroups?: Array<{ __typename?: 'RowLevelPermissionPredicateGroup', id: string, parentRowLevelPermissionPredicateGroupId?: string | null, logicalOperator: RowLevelPermissionPredicateGroupLogicalOperator, positionInRowLevelPermissionPredicateGroup?: number | null, roleId: string, objectMetadataId: string }> | null }> | null, twoFactorAuthenticationMethodSummary?: Array<{ __typename?: 'TwoFactorAuthenticationMethodDTO', twoFactorAuthenticationMethodId: string, status: string, strategy: string }> | null } | null, currentWorkspace?: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, isPublicInviteLinkEnabled: boolean, isGoogleAuthEnabled: boolean, isMicrosoftAuthEnabled: boolean, isPasswordAuthEnabled: boolean, isGoogleAuthBypassEnabled: boolean, isMicrosoftAuthBypassEnabled: boolean, isPasswordAuthBypassEnabled: boolean, subdomain: string, customDomain?: string | null, hasValidEnterpriseKey: boolean, isCustomDomainEnabled: boolean, metadataVersion: number, workspaceMembersCount?: number | null, fastModel: string, smartModel: string, aiAdditionalInstructions?: string | null, autoEnableNewAiModels: boolean, disabledAiModelIds?: Array | null, enabledAiModelIds?: Array | null, useRecommendedModels: boolean, isTwoFactorAuthenticationEnforced: boolean, trashRetentionDays: number, eventLogRetentionDays: number, editableProfileFields?: Array | null, workspaceCustomApplication?: { __typename?: 'Application', id: string } | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, featureFlags?: Array<{ __typename?: 'FeatureFlagDTO', key: FeatureFlagKey, value: boolean }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, interval?: SubscriptionInterval | null, metadata: any, currentPeriodEnd?: string | null, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }>, billingSubscriptionItems?: Array<{ __typename?: 'BillingSubscriptionItemDTO', id: string, hasReachedCurrentPeriodCap: boolean, quantity?: number | null, stripePriceId: string, billingProduct: { __typename?: 'BillingLicensedProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } | { __typename?: 'BillingMeteredProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } }> | null } | null, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, metadata: any, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }> }>, billingEntitlements: Array<{ __typename?: 'BillingEntitlement', key: BillingEntitlementKey, value: boolean }>, defaultRole?: { __typename?: 'Role', id: string, label: string, description?: string | null, icon?: string | null, canUpdateAllSettings: boolean, canAccessAllTools: boolean, isEditable: boolean, canReadAllObjectRecords: boolean, canUpdateAllObjectRecords: boolean, canSoftDeleteAllObjectRecords: boolean, canDestroyAllObjectRecords: boolean, canBeAssignedToUsers: boolean, canBeAssignedToAgents: boolean, canBeAssignedToApiKeys: boolean } | null } | null, availableWorkspaces: { __typename?: 'AvailableWorkspaces', availableWorkspacesForSignIn: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }>, availableWorkspacesForSignUp: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }> } } }; +export type GetCurrentUserQuery = { __typename?: 'Query', currentUser: { __typename?: 'User', id: string, firstName: string, lastName: string, email: string, hasPassword: boolean, canAccessFullAdminPanel: boolean, canImpersonate: boolean, supportUserHash?: string | null, onboardingStatus?: OnboardingStatus | null, userVars?: any | null, workspaceMember?: { __typename?: 'WorkspaceMember', id: string, colorScheme: string, avatarUrl?: string | null, locale?: string | null, userEmail: string, userWorkspaceId?: string | null, timeZone?: string | null, dateFormat?: WorkspaceMemberDateFormatEnum | null, timeFormat?: WorkspaceMemberTimeFormatEnum | null, calendarStartDay?: number | null, numberFormat?: WorkspaceMemberNumberFormatEnum | null, name: { __typename?: 'FullName', firstName: string, lastName: string } } | null, workspaceMembers?: Array<{ __typename?: 'WorkspaceMember', id: string, avatarUrl?: string | null, userEmail: string, userWorkspaceId?: string | null, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, deletedWorkspaceMembers?: Array<{ __typename?: 'DeletedWorkspaceMember', id: string, avatarUrl?: string | null, userEmail: string, name: { __typename?: 'FullName', firstName: string, lastName: string } }> | null, currentUserWorkspace?: { __typename?: 'UserWorkspace', id: string, permissionFlags?: Array | null, objectsPermissions?: Array<{ __typename?: 'ObjectPermission', objectMetadataId: string, canReadObjectRecords?: boolean | null, canUpdateObjectRecords?: boolean | null, canSoftDeleteObjectRecords?: boolean | null, canDestroyObjectRecords?: boolean | null, restrictedFields?: any | null, rowLevelPermissionPredicates?: Array<{ __typename?: 'RowLevelPermissionPredicate', id: string, fieldMetadataId: string, objectMetadataId: string, operand: RowLevelPermissionPredicateOperand, subFieldName?: string | null, workspaceMemberFieldMetadataId?: string | null, workspaceMemberSubFieldName?: string | null, rowLevelPermissionPredicateGroupId?: string | null, positionInRowLevelPermissionPredicateGroup?: number | null, roleId: string, value?: any | null }> | null, rowLevelPermissionPredicateGroups?: Array<{ __typename?: 'RowLevelPermissionPredicateGroup', id: string, parentRowLevelPermissionPredicateGroupId?: string | null, logicalOperator: RowLevelPermissionPredicateGroupLogicalOperator, positionInRowLevelPermissionPredicateGroup?: number | null, roleId: string, objectMetadataId: string }> | null }> | null, twoFactorAuthenticationMethodSummary?: Array<{ __typename?: 'TwoFactorAuthenticationMethodSummary', twoFactorAuthenticationMethodId: string, status: string, strategy: string }> | null } | null, currentWorkspace?: { __typename?: 'Workspace', id: string, displayName?: string | null, logo?: string | null, inviteHash?: string | null, allowImpersonation: boolean, activationStatus: WorkspaceActivationStatus, isPublicInviteLinkEnabled: boolean, isGoogleAuthEnabled: boolean, isMicrosoftAuthEnabled: boolean, isPasswordAuthEnabled: boolean, isGoogleAuthBypassEnabled: boolean, isMicrosoftAuthBypassEnabled: boolean, isPasswordAuthBypassEnabled: boolean, subdomain: string, customDomain?: string | null, hasValidEnterpriseKey: boolean, isCustomDomainEnabled: boolean, metadataVersion: number, workspaceMembersCount?: number | null, fastModel: string, smartModel: string, aiAdditionalInstructions?: string | null, autoEnableNewAiModels: boolean, disabledAiModelIds?: Array | null, enabledAiModelIds?: Array | null, useRecommendedModels: boolean, isTwoFactorAuthenticationEnforced: boolean, trashRetentionDays: number, eventLogRetentionDays: number, editableProfileFields?: Array | null, workspaceCustomApplication?: { __typename?: 'Application', id: string } | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, featureFlags?: Array<{ __typename?: 'FeatureFlag', key: FeatureFlagKey, value: boolean }> | null, currentBillingSubscription?: { __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, interval?: SubscriptionInterval | null, metadata: any, currentPeriodEnd?: string | null, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }>, billingSubscriptionItems?: Array<{ __typename?: 'BillingSubscriptionItem', id: string, hasReachedCurrentPeriodCap: boolean, quantity?: number | null, stripePriceId: string, billingProduct: { __typename?: 'BillingLicensedProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } | { __typename?: 'BillingMeteredProduct', name: string, description: string, images?: Array | null, metadata: { __typename?: 'BillingProductMetadata', productKey: BillingProductKey, planKey: BillingPlanKey, priceUsageBased: BillingUsageType } } }> | null } | null, billingSubscriptions: Array<{ __typename?: 'BillingSubscription', id: string, status: SubscriptionStatus, metadata: any, phases: Array<{ __typename?: 'BillingSubscriptionSchedulePhase', start_date: number, end_date: number, items: Array<{ __typename?: 'BillingSubscriptionSchedulePhaseItem', price: string, quantity?: number | null }> }> }>, billingEntitlements: Array<{ __typename?: 'BillingEntitlement', key: BillingEntitlementKey, value: boolean }>, defaultRole?: { __typename?: 'Role', id: string, label: string, description?: string | null, icon?: string | null, canUpdateAllSettings: boolean, canAccessAllTools: boolean, isEditable: boolean, canReadAllObjectRecords: boolean, canUpdateAllObjectRecords: boolean, canSoftDeleteAllObjectRecords: boolean, canDestroyAllObjectRecords: boolean, canBeAssignedToUsers: boolean, canBeAssignedToAgents: boolean, canBeAssignedToApiKeys: boolean } | null } | null, availableWorkspaces: { __typename?: 'AvailableWorkspaces', availableWorkspacesForSignIn: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }>, availableWorkspacesForSignUp: Array<{ __typename?: 'AvailableWorkspace', id: string, displayName?: string | null, loginToken?: string | null, inviteHash?: string | null, personalInviteToken?: string | null, logo?: string | null, workspaceUrls: { __typename?: 'WorkspaceUrls', subdomainUrl: string, customUrl?: string | null }, sso: Array<{ __typename?: 'SSOConnection', type: IdentityProviderType, id: string, issuer: string, name: string, status: SsoIdentityProviderStatus }> }> } } }; export type ViewFieldFragmentFragment = { __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }; @@ -6932,14 +7161,14 @@ export type ResendWorkspaceInvitationMutationVariables = Exact<{ }>; -export type ResendWorkspaceInvitationMutation = { __typename?: 'Mutation', resendWorkspaceInvitation: { __typename?: 'SendInvitationsOutput', success: boolean, errors: Array, result: Array<{ __typename?: 'WorkspaceInvitation', id: string, email: string, expiresAt: string }> } }; +export type ResendWorkspaceInvitationMutation = { __typename?: 'Mutation', resendWorkspaceInvitation: { __typename?: 'SendInvitations', success: boolean, errors: Array, result: Array<{ __typename?: 'WorkspaceInvitation', id: string, email: string, expiresAt: string }> } }; export type SendInvitationsMutationVariables = Exact<{ emails: Array | Scalars['String']; }>; -export type SendInvitationsMutation = { __typename?: 'Mutation', sendInvitations: { __typename?: 'SendInvitationsOutput', success: boolean, errors: Array, result: Array<{ __typename?: 'WorkspaceInvitation', id: string, email: string, expiresAt: string }> } }; +export type SendInvitationsMutation = { __typename?: 'Mutation', sendInvitations: { __typename?: 'SendInvitations', success: boolean, errors: Array, result: Array<{ __typename?: 'WorkspaceInvitation', id: string, email: string, expiresAt: string }> } }; export type GetWorkspaceInvitationsQueryVariables = Exact<{ [key: string]: never; }>; @@ -7207,7 +7436,7 @@ export const AuthTokenPairFragmentFragmentDoc = gql` } ${AuthTokenFragmentFragmentDoc}`; export const AvailableSsoIdentityProvidersFragmentFragmentDoc = gql` - fragment AvailableSSOIdentityProvidersFragment on FindAvailableSSOIDPOutput { + fragment AvailableSSOIdentityProvidersFragment on FindAvailableSSOIDP { id issuer name @@ -7588,6 +7817,23 @@ export const NavigationMenuItemQueryFieldsFragmentDoc = gql` } } ${NavigationMenuItemFieldsFragmentDoc}`; +export const ApplicationRegistrationFragmentFragmentDoc = gql` + fragment ApplicationRegistrationFragment on ApplicationRegistration { + id + universalIdentifier + name + description + logoUrl + author + oAuthClientId + oAuthRedirectUris + oAuthScopes + websiteUrl + termsUrl + createdAt + updatedAt +} + `; export const ApiKeyFragmentFragmentDoc = gql` fragment ApiKeyFragment on ApiKey { id @@ -9094,7 +9340,7 @@ export type UploadImageMutationHookResult = ReturnType; export type UploadImageMutationOptions = Apollo.BaseMutationOptions; export const AuthorizeAppDocument = gql` - mutation authorizeApp($clientId: String!, $codeChallenge: String!, $redirectUrl: String!) { + mutation authorizeApp($clientId: String!, $codeChallenge: String, $redirectUrl: String!) { authorizeApp( clientId: $clientId codeChallenge: $codeChallenge @@ -12841,6 +13087,335 @@ export function useGetSystemHealthStatusLazyQuery(baseOptions?: Apollo.LazyQuery export type GetSystemHealthStatusQueryHookResult = ReturnType; export type GetSystemHealthStatusLazyQueryHookResult = ReturnType; export type GetSystemHealthStatusQueryResult = Apollo.QueryResult; +export const DeleteApplicationRegistrationDocument = gql` + mutation DeleteApplicationRegistration($id: String!) { + deleteApplicationRegistration(id: $id) +} + `; +export type DeleteApplicationRegistrationMutationFn = Apollo.MutationFunction; + +/** + * __useDeleteApplicationRegistrationMutation__ + * + * To run a mutation, you first call `useDeleteApplicationRegistrationMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useDeleteApplicationRegistrationMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [deleteApplicationRegistrationMutation, { data, loading, error }] = useDeleteApplicationRegistrationMutation({ + * variables: { + * id: // value for 'id' + * }, + * }); + */ +export function useDeleteApplicationRegistrationMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(DeleteApplicationRegistrationDocument, options); + } +export type DeleteApplicationRegistrationMutationHookResult = ReturnType; +export type DeleteApplicationRegistrationMutationResult = Apollo.MutationResult; +export type DeleteApplicationRegistrationMutationOptions = Apollo.BaseMutationOptions; +export const RotateApplicationRegistrationClientSecretDocument = gql` + mutation RotateApplicationRegistrationClientSecret($id: String!) { + rotateApplicationRegistrationClientSecret(id: $id) { + clientSecret + } +} + `; +export type RotateApplicationRegistrationClientSecretMutationFn = Apollo.MutationFunction; + +/** + * __useRotateApplicationRegistrationClientSecretMutation__ + * + * To run a mutation, you first call `useRotateApplicationRegistrationClientSecretMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useRotateApplicationRegistrationClientSecretMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [rotateApplicationRegistrationClientSecretMutation, { data, loading, error }] = useRotateApplicationRegistrationClientSecretMutation({ + * variables: { + * id: // value for 'id' + * }, + * }); + */ +export function useRotateApplicationRegistrationClientSecretMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(RotateApplicationRegistrationClientSecretDocument, options); + } +export type RotateApplicationRegistrationClientSecretMutationHookResult = ReturnType; +export type RotateApplicationRegistrationClientSecretMutationResult = Apollo.MutationResult; +export type RotateApplicationRegistrationClientSecretMutationOptions = Apollo.BaseMutationOptions; +export const UpdateApplicationRegistrationDocument = gql` + mutation UpdateApplicationRegistration($input: UpdateApplicationRegistrationInput!) { + updateApplicationRegistration(input: $input) { + ...ApplicationRegistrationFragment + } +} + ${ApplicationRegistrationFragmentFragmentDoc}`; +export type UpdateApplicationRegistrationMutationFn = Apollo.MutationFunction; + +/** + * __useUpdateApplicationRegistrationMutation__ + * + * To run a mutation, you first call `useUpdateApplicationRegistrationMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useUpdateApplicationRegistrationMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [updateApplicationRegistrationMutation, { data, loading, error }] = useUpdateApplicationRegistrationMutation({ + * variables: { + * input: // value for 'input' + * }, + * }); + */ +export function useUpdateApplicationRegistrationMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(UpdateApplicationRegistrationDocument, options); + } +export type UpdateApplicationRegistrationMutationHookResult = ReturnType; +export type UpdateApplicationRegistrationMutationResult = Apollo.MutationResult; +export type UpdateApplicationRegistrationMutationOptions = Apollo.BaseMutationOptions; +export const UpdateApplicationRegistrationVariableDocument = gql` + mutation UpdateApplicationRegistrationVariable($input: UpdateApplicationRegistrationVariableInput!) { + updateApplicationRegistrationVariable(input: $input) { + id + key + description + isSecret + isRequired + isFilled + createdAt + updatedAt + } +} + `; +export type UpdateApplicationRegistrationVariableMutationFn = Apollo.MutationFunction; + +/** + * __useUpdateApplicationRegistrationVariableMutation__ + * + * To run a mutation, you first call `useUpdateApplicationRegistrationVariableMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useUpdateApplicationRegistrationVariableMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [updateApplicationRegistrationVariableMutation, { data, loading, error }] = useUpdateApplicationRegistrationVariableMutation({ + * variables: { + * input: // value for 'input' + * }, + * }); + */ +export function useUpdateApplicationRegistrationVariableMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(UpdateApplicationRegistrationVariableDocument, options); + } +export type UpdateApplicationRegistrationVariableMutationHookResult = ReturnType; +export type UpdateApplicationRegistrationVariableMutationResult = Apollo.MutationResult; +export type UpdateApplicationRegistrationVariableMutationOptions = Apollo.BaseMutationOptions; +export const FindApplicationRegistrationByClientIdDocument = gql` + query FindApplicationRegistrationByClientId($clientId: String!) { + findApplicationRegistrationByClientId(clientId: $clientId) { + id + name + oAuthScopes + websiteUrl + logoUrl + } +} + `; + +/** + * __useFindApplicationRegistrationByClientIdQuery__ + * + * To run a query within a React component, call `useFindApplicationRegistrationByClientIdQuery` and pass it any options that fit your needs. + * When your component renders, `useFindApplicationRegistrationByClientIdQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useFindApplicationRegistrationByClientIdQuery({ + * variables: { + * clientId: // value for 'clientId' + * }, + * }); + */ +export function useFindApplicationRegistrationByClientIdQuery(baseOptions: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(FindApplicationRegistrationByClientIdDocument, options); + } +export function useFindApplicationRegistrationByClientIdLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(FindApplicationRegistrationByClientIdDocument, options); + } +export type FindApplicationRegistrationByClientIdQueryHookResult = ReturnType; +export type FindApplicationRegistrationByClientIdLazyQueryHookResult = ReturnType; +export type FindApplicationRegistrationByClientIdQueryResult = Apollo.QueryResult; +export const FindApplicationRegistrationStatsDocument = gql` + query FindApplicationRegistrationStats($id: String!) { + findApplicationRegistrationStats(id: $id) { + activeInstalls + mostInstalledVersion + versionDistribution { + version + count + } + } +} + `; + +/** + * __useFindApplicationRegistrationStatsQuery__ + * + * To run a query within a React component, call `useFindApplicationRegistrationStatsQuery` and pass it any options that fit your needs. + * When your component renders, `useFindApplicationRegistrationStatsQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useFindApplicationRegistrationStatsQuery({ + * variables: { + * id: // value for 'id' + * }, + * }); + */ +export function useFindApplicationRegistrationStatsQuery(baseOptions: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(FindApplicationRegistrationStatsDocument, options); + } +export function useFindApplicationRegistrationStatsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(FindApplicationRegistrationStatsDocument, options); + } +export type FindApplicationRegistrationStatsQueryHookResult = ReturnType; +export type FindApplicationRegistrationStatsLazyQueryHookResult = ReturnType; +export type FindApplicationRegistrationStatsQueryResult = Apollo.QueryResult; +export const FindApplicationRegistrationVariablesDocument = gql` + query FindApplicationRegistrationVariables($applicationRegistrationId: String!) { + findApplicationRegistrationVariables( + applicationRegistrationId: $applicationRegistrationId + ) { + id + key + description + isSecret + isRequired + isFilled + createdAt + updatedAt + } +} + `; + +/** + * __useFindApplicationRegistrationVariablesQuery__ + * + * To run a query within a React component, call `useFindApplicationRegistrationVariablesQuery` and pass it any options that fit your needs. + * When your component renders, `useFindApplicationRegistrationVariablesQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useFindApplicationRegistrationVariablesQuery({ + * variables: { + * applicationRegistrationId: // value for 'applicationRegistrationId' + * }, + * }); + */ +export function useFindApplicationRegistrationVariablesQuery(baseOptions: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(FindApplicationRegistrationVariablesDocument, options); + } +export function useFindApplicationRegistrationVariablesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(FindApplicationRegistrationVariablesDocument, options); + } +export type FindApplicationRegistrationVariablesQueryHookResult = ReturnType; +export type FindApplicationRegistrationVariablesLazyQueryHookResult = ReturnType; +export type FindApplicationRegistrationVariablesQueryResult = Apollo.QueryResult; +export const FindManyApplicationRegistrationsDocument = gql` + query FindManyApplicationRegistrations { + findManyApplicationRegistrations { + ...ApplicationRegistrationFragment + } +} + ${ApplicationRegistrationFragmentFragmentDoc}`; + +/** + * __useFindManyApplicationRegistrationsQuery__ + * + * To run a query within a React component, call `useFindManyApplicationRegistrationsQuery` and pass it any options that fit your needs. + * When your component renders, `useFindManyApplicationRegistrationsQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useFindManyApplicationRegistrationsQuery({ + * variables: { + * }, + * }); + */ +export function useFindManyApplicationRegistrationsQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(FindManyApplicationRegistrationsDocument, options); + } +export function useFindManyApplicationRegistrationsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(FindManyApplicationRegistrationsDocument, options); + } +export type FindManyApplicationRegistrationsQueryHookResult = ReturnType; +export type FindManyApplicationRegistrationsLazyQueryHookResult = ReturnType; +export type FindManyApplicationRegistrationsQueryResult = Apollo.QueryResult; +export const FindOneApplicationRegistrationDocument = gql` + query FindOneApplicationRegistration($id: String!) { + findOneApplicationRegistration(id: $id) { + ...ApplicationRegistrationFragment + } +} + ${ApplicationRegistrationFragmentFragmentDoc}`; + +/** + * __useFindOneApplicationRegistrationQuery__ + * + * To run a query within a React component, call `useFindOneApplicationRegistrationQuery` and pass it any options that fit your needs. + * When your component renders, `useFindOneApplicationRegistrationQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useFindOneApplicationRegistrationQuery({ + * variables: { + * id: // value for 'id' + * }, + * }); + */ +export function useFindOneApplicationRegistrationQuery(baseOptions: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(FindOneApplicationRegistrationDocument, options); + } +export function useFindOneApplicationRegistrationLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(FindOneApplicationRegistrationDocument, options); + } +export type FindOneApplicationRegistrationQueryHookResult = ReturnType; +export type FindOneApplicationRegistrationLazyQueryHookResult = ReturnType; +export type FindOneApplicationRegistrationQueryResult = Apollo.QueryResult; export const UninstallApplicationDocument = gql` mutation UninstallApplication($universalIdentifier: String!) { uninstallApplication(universalIdentifier: $universalIdentifier) diff --git a/packages/twenty-front/src/generated/graphql.ts b/packages/twenty-front/src/generated/graphql.ts index 12520090d5..8b96d77801 100644 --- a/packages/twenty-front/src/generated/graphql.ts +++ b/packages/twenty-front/src/generated/graphql.ts @@ -134,10 +134,10 @@ export type Mutation = { dismissReconnectAccountBanner: Scalars['Boolean']; duplicateWorkflow: WorkflowVersionDto; duplicateWorkflowVersionStep: WorkflowVersionStepChanges; - runWorkflowVersion: RunWorkflowVersionOutput; + runWorkflowVersion: RunWorkflowVersion; stopWorkflowRun: WorkflowRun; submitFormStep: Scalars['Boolean']; - testHttpRequest: TestHttpRequestOutput; + testHttpRequest: TestHttpRequest; updateWorkflowRunStep: WorkflowAction; updateWorkflowVersionPositions: Scalars['Boolean']; updateWorkflowVersionStep: WorkflowAction; @@ -306,6 +306,11 @@ export type QuerySearchArgs = { searchInput: Scalars['String']; }; +export type RunWorkflowVersion = { + __typename?: 'RunWorkflowVersion'; + workflowRunId: Scalars['UUID']; +}; + export type RunWorkflowVersionInput = { /** Execution result in JSON format */ payload?: InputMaybe; @@ -315,11 +320,6 @@ export type RunWorkflowVersionInput = { workflowVersionId: Scalars['UUID']; }; -export type RunWorkflowVersionOutput = { - __typename?: 'RunWorkflowVersionOutput'; - workflowRunId: Scalars['UUID']; -}; - export type SearchRecord = { __typename?: 'SearchRecord'; imageUrl?: Maybe; @@ -358,19 +358,8 @@ export type SubmitFormStepInput = { workflowRunId: Scalars['UUID']; }; -export type TestHttpRequestInput = { - /** Request body */ - body?: InputMaybe; - /** HTTP headers */ - headers?: InputMaybe; - /** HTTP method */ - method: Scalars['String']; - /** URL to make the request to */ - url: Scalars['String']; -}; - -export type TestHttpRequestOutput = { - __typename?: 'TestHttpRequestOutput'; +export type TestHttpRequest = { + __typename?: 'TestHttpRequest'; /** Error information */ error?: Maybe; /** Response headers */ @@ -387,6 +376,17 @@ export type TestHttpRequestOutput = { success: Scalars['Boolean']; }; +export type TestHttpRequestInput = { + /** Request body */ + body?: InputMaybe; + /** HTTP headers */ + headers?: InputMaybe; + /** HTTP method */ + method: Scalars['String']; + /** URL to make the request to */ + url: Scalars['String']; +}; + export type TimelineCalendarEvent = { __typename?: 'TimelineCalendarEvent'; conferenceLink: LinksMetadata; @@ -722,7 +722,7 @@ export type RunWorkflowVersionMutationVariables = Exact<{ }>; -export type RunWorkflowVersionMutation = { __typename?: 'Mutation', runWorkflowVersion: { __typename?: 'RunWorkflowVersionOutput', workflowRunId: any } }; +export type RunWorkflowVersionMutation = { __typename?: 'Mutation', runWorkflowVersion: { __typename?: 'RunWorkflowVersion', workflowRunId: any } }; export type StopWorkflowRunMutationVariables = Exact<{ workflowRunId: Scalars['UUID']; @@ -757,7 +757,7 @@ export type TestHttpRequestMutationVariables = Exact<{ }>; -export type TestHttpRequestMutation = { __typename?: 'Mutation', testHttpRequest: { __typename?: 'TestHttpRequestOutput', success: boolean, message: string, result?: any | null, error?: any | null, status?: number | null, statusText?: string | null, headers?: any | null } }; +export type TestHttpRequestMutation = { __typename?: 'Mutation', testHttpRequest: { __typename?: 'TestHttpRequest', success: boolean, message: string, result?: any | null, error?: any | null, status?: number | null, statusText?: string | null, headers?: any | null } }; export type UpdateWorkflowVersionPositionsMutationVariables = Exact<{ input: UpdateWorkflowVersionPositionsInput; diff --git a/packages/twenty-front/src/modules/app/components/SettingsRoutes.tsx b/packages/twenty-front/src/modules/app/components/SettingsRoutes.tsx index d2e3e73ace..8a940c97cf 100644 --- a/packages/twenty-front/src/modules/app/components/SettingsRoutes.tsx +++ b/packages/twenty-front/src/modules/app/components/SettingsRoutes.tsx @@ -170,6 +170,14 @@ const SettingsAvailableApplicationDetails = lazy(() => })), ); +const SettingsApplicationRegistrationDetails = lazy(() => + import( + '~/pages/settings/applications/SettingsApplicationRegistrationDetails' + ).then((module) => ({ + default: module.SettingsApplicationRegistrationDetails, + })), +); + const SettingsAgentForm = lazy(() => import('~/pages/settings/ai/SettingsAgentForm').then((module) => ({ default: module.SettingsAgentForm, @@ -622,6 +630,10 @@ export const SettingsRoutes = ({ isAdminPageEnabled }: SettingsRoutesProps) => ( path={SettingsPath.AvailableApplicationDetail} element={} /> + } + /> } diff --git a/packages/twenty-front/src/modules/auth/graphql/fragments/availableSSOIdentityProvidersFragment.ts b/packages/twenty-front/src/modules/auth/graphql/fragments/availableSSOIdentityProvidersFragment.ts index 45bc6c944c..3f4926d8bd 100644 --- a/packages/twenty-front/src/modules/auth/graphql/fragments/availableSSOIdentityProvidersFragment.ts +++ b/packages/twenty-front/src/modules/auth/graphql/fragments/availableSSOIdentityProvidersFragment.ts @@ -3,7 +3,7 @@ import { gql } from '@apollo/client'; export const AVAILABLE_SSO_IDENTITY_PROVIDERS_FRAGMENT = gql` - fragment AvailableSSOIdentityProvidersFragment on FindAvailableSSOIDPOutput { + fragment AvailableSSOIdentityProvidersFragment on FindAvailableSSOIDP { id issuer name diff --git a/packages/twenty-front/src/modules/auth/graphql/mutations/authorizeApp.ts b/packages/twenty-front/src/modules/auth/graphql/mutations/authorizeApp.ts index df0ae9bbfa..ab2ec03e29 100644 --- a/packages/twenty-front/src/modules/auth/graphql/mutations/authorizeApp.ts +++ b/packages/twenty-front/src/modules/auth/graphql/mutations/authorizeApp.ts @@ -3,7 +3,7 @@ import { gql } from '@apollo/client'; export const AUTHORIZE_APP = gql` mutation authorizeApp( $clientId: String! - $codeChallenge: String! + $codeChallenge: String $redirectUrl: String! ) { authorizeApp( diff --git a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/__tests__/useHandleResetPassword.test.ts b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/__tests__/useHandleResetPassword.test.ts index 3eaccd5950..492d00a78f 100644 --- a/packages/twenty-front/src/modules/auth/sign-in-up/hooks/__tests__/useHandleResetPassword.test.ts +++ b/packages/twenty-front/src/modules/auth/sign-in-up/hooks/__tests__/useHandleResetPassword.test.ts @@ -10,7 +10,7 @@ import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore'; import { SOURCE_LOCALE } from 'twenty-shared/translations'; import { - type PublicWorkspaceDataOutput, + type PublicWorkspaceData, useEmailPasswordResetLinkMutation, } from '~/generated-metadata/graphql'; import { dynamicActivate } from '~/utils/i18n/dynamicActivate'; @@ -24,7 +24,7 @@ dynamicActivate(SOURCE_LOCALE); const renderHooks = () => { jotaiStore.set(workspacePublicDataState.atom, { id: 'workspace-id', - } as PublicWorkspaceDataOutput); + } as PublicWorkspaceData); const { result } = renderHook(() => useHandleResetPassword(), { wrapper: ({ children }: { children: ReactNode }) => diff --git a/packages/twenty-front/src/modules/auth/states/workspacePublicDataState.ts b/packages/twenty-front/src/modules/auth/states/workspacePublicDataState.ts index 57b5db6498..9e16130dc5 100644 --- a/packages/twenty-front/src/modules/auth/states/workspacePublicDataState.ts +++ b/packages/twenty-front/src/modules/auth/states/workspacePublicDataState.ts @@ -1,8 +1,8 @@ -import { type PublicWorkspaceDataOutput } from '~/generated-metadata/graphql'; +import { type PublicWorkspaceData } from '~/generated-metadata/graphql'; import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState'; export const workspacePublicDataState = - createAtomState({ + createAtomState({ key: 'workspacePublicDataState', defaultValue: null, }); diff --git a/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminTableCard.tsx b/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminTableCard.tsx index 70df572646..c0041d999f 100644 --- a/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminTableCard.tsx +++ b/packages/twenty-front/src/modules/settings/admin-panel/components/SettingsAdminTableCard.tsx @@ -4,8 +4,9 @@ import { TableCell } from '@/ui/layout/table/components/TableCell'; import { TableRow } from '@/ui/layout/table/components/TableRow'; import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; -import { Card } from 'twenty-ui/layout'; +import { isDefined } from 'twenty-shared/utils'; import { type IconComponent } from 'twenty-ui/display'; +import { Card } from 'twenty-ui/layout'; const StyledCard = styled(Card)` background-color: ${({ theme }) => theme.background.secondary}; @@ -33,8 +34,10 @@ const StyledTableCellLabel = styled(TableCell)<{ const StyledTableCellValue = styled(TableCell)<{ align?: 'left' | 'center' | 'right'; + clickable?: boolean; }>` color: ${({ theme }) => theme.font.color.primary}; + cursor: ${({ clickable }) => (clickable ? 'pointer' : 'default')}; height: ${({ theme }) => theme.spacing(6)}; justify-content: ${({ align }) => align === 'left' @@ -48,6 +51,7 @@ type TableItem = { Icon?: IconComponent; label: string; value: string | number | React.ReactNode; + onClick?: () => void; }; type SettingsAdminTableCardProps = { @@ -82,7 +86,11 @@ export const SettingsAdminTableCard = ({ {item.Icon && } {item.label} - + {item.value} diff --git a/packages/twenty-front/src/modules/settings/application-registrations/graphql/fragments/applicationRegistrationFragment.ts b/packages/twenty-front/src/modules/settings/application-registrations/graphql/fragments/applicationRegistrationFragment.ts new file mode 100644 index 0000000000..e9756655e6 --- /dev/null +++ b/packages/twenty-front/src/modules/settings/application-registrations/graphql/fragments/applicationRegistrationFragment.ts @@ -0,0 +1,19 @@ +import { gql } from '@apollo/client'; + +export const APPLICATION_REGISTRATION_FRAGMENT = gql` + fragment ApplicationRegistrationFragment on ApplicationRegistration { + id + universalIdentifier + name + description + logoUrl + author + oAuthClientId + oAuthRedirectUris + oAuthScopes + websiteUrl + termsUrl + createdAt + updatedAt + } +`; diff --git a/packages/twenty-front/src/modules/settings/application-registrations/graphql/mutations/deleteApplicationRegistration.ts b/packages/twenty-front/src/modules/settings/application-registrations/graphql/mutations/deleteApplicationRegistration.ts new file mode 100644 index 0000000000..0e48bbdf27 --- /dev/null +++ b/packages/twenty-front/src/modules/settings/application-registrations/graphql/mutations/deleteApplicationRegistration.ts @@ -0,0 +1,7 @@ +import { gql } from '@apollo/client'; + +export const DELETE_APPLICATION_REGISTRATION = gql` + mutation DeleteApplicationRegistration($id: String!) { + deleteApplicationRegistration(id: $id) + } +`; diff --git a/packages/twenty-front/src/modules/settings/application-registrations/graphql/mutations/rotateApplicationRegistrationClientSecret.ts b/packages/twenty-front/src/modules/settings/application-registrations/graphql/mutations/rotateApplicationRegistrationClientSecret.ts new file mode 100644 index 0000000000..658bbecaf4 --- /dev/null +++ b/packages/twenty-front/src/modules/settings/application-registrations/graphql/mutations/rotateApplicationRegistrationClientSecret.ts @@ -0,0 +1,9 @@ +import { gql } from '@apollo/client'; + +export const ROTATE_APPLICATION_REGISTRATION_CLIENT_SECRET = gql` + mutation RotateApplicationRegistrationClientSecret($id: String!) { + rotateApplicationRegistrationClientSecret(id: $id) { + clientSecret + } + } +`; diff --git a/packages/twenty-front/src/modules/settings/application-registrations/graphql/mutations/updateApplicationRegistration.ts b/packages/twenty-front/src/modules/settings/application-registrations/graphql/mutations/updateApplicationRegistration.ts new file mode 100644 index 0000000000..76dee1164e --- /dev/null +++ b/packages/twenty-front/src/modules/settings/application-registrations/graphql/mutations/updateApplicationRegistration.ts @@ -0,0 +1,14 @@ +import { gql } from '@apollo/client'; + +import { APPLICATION_REGISTRATION_FRAGMENT } from '@/settings/application-registrations/graphql/fragments/applicationRegistrationFragment'; + +export const UPDATE_APPLICATION_REGISTRATION = gql` + mutation UpdateApplicationRegistration( + $input: UpdateApplicationRegistrationInput! + ) { + updateApplicationRegistration(input: $input) { + ...ApplicationRegistrationFragment + } + } + ${APPLICATION_REGISTRATION_FRAGMENT} +`; diff --git a/packages/twenty-front/src/modules/settings/application-registrations/graphql/mutations/updateApplicationRegistrationVariable.ts b/packages/twenty-front/src/modules/settings/application-registrations/graphql/mutations/updateApplicationRegistrationVariable.ts new file mode 100644 index 0000000000..7fe2c960d4 --- /dev/null +++ b/packages/twenty-front/src/modules/settings/application-registrations/graphql/mutations/updateApplicationRegistrationVariable.ts @@ -0,0 +1,18 @@ +import { gql } from '@apollo/client'; + +export const UPDATE_APPLICATION_REGISTRATION_VARIABLE = gql` + mutation UpdateApplicationRegistrationVariable( + $input: UpdateApplicationRegistrationVariableInput! + ) { + updateApplicationRegistrationVariable(input: $input) { + id + key + description + isSecret + isRequired + isFilled + createdAt + updatedAt + } + } +`; diff --git a/packages/twenty-front/src/modules/settings/application-registrations/graphql/queries/findApplicationRegistrationByClientId.ts b/packages/twenty-front/src/modules/settings/application-registrations/graphql/queries/findApplicationRegistrationByClientId.ts new file mode 100644 index 0000000000..f125b42c7a --- /dev/null +++ b/packages/twenty-front/src/modules/settings/application-registrations/graphql/queries/findApplicationRegistrationByClientId.ts @@ -0,0 +1,13 @@ +import { gql } from '@apollo/client'; + +export const FIND_APPLICATION_REGISTRATION_BY_CLIENT_ID = gql` + query FindApplicationRegistrationByClientId($clientId: String!) { + findApplicationRegistrationByClientId(clientId: $clientId) { + id + name + oAuthScopes + websiteUrl + logoUrl + } + } +`; diff --git a/packages/twenty-front/src/modules/settings/application-registrations/graphql/queries/findApplicationRegistrationStats.ts b/packages/twenty-front/src/modules/settings/application-registrations/graphql/queries/findApplicationRegistrationStats.ts new file mode 100644 index 0000000000..d84229e133 --- /dev/null +++ b/packages/twenty-front/src/modules/settings/application-registrations/graphql/queries/findApplicationRegistrationStats.ts @@ -0,0 +1,14 @@ +import { gql } from '@apollo/client'; + +export const FIND_APPLICATION_REGISTRATION_STATS = gql` + query FindApplicationRegistrationStats($id: String!) { + findApplicationRegistrationStats(id: $id) { + activeInstalls + mostInstalledVersion + versionDistribution { + version + count + } + } + } +`; diff --git a/packages/twenty-front/src/modules/settings/application-registrations/graphql/queries/findApplicationRegistrationVariables.ts b/packages/twenty-front/src/modules/settings/application-registrations/graphql/queries/findApplicationRegistrationVariables.ts new file mode 100644 index 0000000000..5be591bb89 --- /dev/null +++ b/packages/twenty-front/src/modules/settings/application-registrations/graphql/queries/findApplicationRegistrationVariables.ts @@ -0,0 +1,20 @@ +import { gql } from '@apollo/client'; + +export const FIND_APPLICATION_REGISTRATION_VARIABLES = gql` + query FindApplicationRegistrationVariables( + $applicationRegistrationId: String! + ) { + findApplicationRegistrationVariables( + applicationRegistrationId: $applicationRegistrationId + ) { + id + key + description + isSecret + isRequired + isFilled + createdAt + updatedAt + } + } +`; diff --git a/packages/twenty-front/src/modules/settings/application-registrations/graphql/queries/findManyApplicationRegistrations.ts b/packages/twenty-front/src/modules/settings/application-registrations/graphql/queries/findManyApplicationRegistrations.ts new file mode 100644 index 0000000000..c86bcaee97 --- /dev/null +++ b/packages/twenty-front/src/modules/settings/application-registrations/graphql/queries/findManyApplicationRegistrations.ts @@ -0,0 +1,12 @@ +import { gql } from '@apollo/client'; + +import { APPLICATION_REGISTRATION_FRAGMENT } from '@/settings/application-registrations/graphql/fragments/applicationRegistrationFragment'; + +export const FIND_MANY_APPLICATION_REGISTRATIONS = gql` + query FindManyApplicationRegistrations { + findManyApplicationRegistrations { + ...ApplicationRegistrationFragment + } + } + ${APPLICATION_REGISTRATION_FRAGMENT} +`; diff --git a/packages/twenty-front/src/modules/settings/application-registrations/graphql/queries/findOneApplicationRegistration.ts b/packages/twenty-front/src/modules/settings/application-registrations/graphql/queries/findOneApplicationRegistration.ts new file mode 100644 index 0000000000..56856e61f3 --- /dev/null +++ b/packages/twenty-front/src/modules/settings/application-registrations/graphql/queries/findOneApplicationRegistration.ts @@ -0,0 +1,12 @@ +import { gql } from '@apollo/client'; + +import { APPLICATION_REGISTRATION_FRAGMENT } from '@/settings/application-registrations/graphql/fragments/applicationRegistrationFragment'; + +export const FIND_ONE_APPLICATION_REGISTRATION = gql` + query FindOneApplicationRegistration($id: String!) { + findOneApplicationRegistration(id: $id) { + ...ApplicationRegistrationFragment + } + } + ${APPLICATION_REGISTRATION_FRAGMENT} +`; diff --git a/packages/twenty-front/src/modules/settings/hooks/useSettingsNavigationItems.tsx b/packages/twenty-front/src/modules/settings/hooks/useSettingsNavigationItems.tsx index 5174816730..c3aec543db 100644 --- a/packages/twenty-front/src/modules/settings/hooks/useSettingsNavigationItems.tsx +++ b/packages/twenty-front/src/modules/settings/hooks/useSettingsNavigationItems.tsx @@ -8,10 +8,10 @@ import { supportChatState } from '@/client-config/states/supportChatState'; import { usePermissionFlagMap } from '@/settings/roles/hooks/usePermissionFlagMap'; import { getDocumentationUrl } from '@/support/utils/getDocumentationUrl'; import { type NavigationDrawerItemIndentationLevel } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem'; +import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue'; import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; import { t } from '@lingui/core/macro'; import { isNonEmptyString } from '@sniptt/guards'; -import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue'; import { IconApi, // IconApps, // TODO: Re-enable when integrations page is ready @@ -173,7 +173,7 @@ const useSettingsNavigationItems = (): SettingsNavigationSection[] => { // isHidden: !permissionMap[PermissionFlagType.API_KEYS_AND_WEBHOOKS], // }, { - label: t`Applications`, + label: t`Apps`, path: SettingsPath.Applications, Icon: IconPlug, isHidden: diff --git a/packages/twenty-front/src/modules/settings/two-factor-authentication/hooks/useCurrentUserWorkspaceTwoFactorAuthentication.ts b/packages/twenty-front/src/modules/settings/two-factor-authentication/hooks/useCurrentUserWorkspaceTwoFactorAuthentication.ts index c0f08e1e85..3146957a2f 100644 --- a/packages/twenty-front/src/modules/settings/two-factor-authentication/hooks/useCurrentUserWorkspaceTwoFactorAuthentication.ts +++ b/packages/twenty-front/src/modules/settings/two-factor-authentication/hooks/useCurrentUserWorkspaceTwoFactorAuthentication.ts @@ -1,7 +1,7 @@ import { currentUserWorkspaceState } from '@/auth/states/currentUserWorkspaceState'; import { useMemo } from 'react'; import { - type TwoFactorAuthenticationMethodDto, + type TwoFactorAuthenticationMethodSummary, useInitiateOtpProvisioningMutation, } from '~/generated-metadata/graphql'; import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue'; @@ -12,7 +12,7 @@ export const useCurrentUserWorkspaceTwoFactorAuthentication = () => { useInitiateOtpProvisioningMutation(); const currentUserWorkspaceTwoFactorAuthenticationMethods = useMemo(() => { - const methods: Record = {}; + const methods: Record = {}; (currentUserWorkspace?.twoFactorAuthenticationMethodSummary ?? []).forEach( (method) => (methods[method.strategy] = method), diff --git a/packages/twenty-front/src/pages/auth/Authorize.tsx b/packages/twenty-front/src/pages/auth/Authorize.tsx index e793677010..4fef494c9f 100644 --- a/packages/twenty-front/src/pages/auth/Authorize.tsx +++ b/packages/twenty-front/src/pages/auth/Authorize.tsx @@ -1,3 +1,4 @@ +import { FIND_APPLICATION_REGISTRATION_BY_CLIENT_ID } from '@/settings/application-registrations/graphql/queries/findApplicationRegistrationByClientId'; import styled from '@emotion/styled'; import { useEffect, useState } from 'react'; import { useSearchParams } from 'react-router-dom'; @@ -5,14 +6,15 @@ import { AppPath } from 'twenty-shared/types'; import { useRedirect } from '@/domain-manager/hooks/useRedirect'; import { Trans, useLingui } from '@lingui/react/macro'; +import { useQuery } from '@apollo/client'; +import { isNonEmptyString } from '@sniptt/guards'; import { isDefined } from 'twenty-shared/utils'; +import { Avatar } from 'twenty-ui/display'; import { MainButton } from 'twenty-ui/input'; import { UndecoratedLink } from 'twenty-ui/navigation'; import { useAuthorizeAppMutation } from '~/generated-metadata/graphql'; import { useNavigateApp } from '~/hooks/useNavigateApp'; -type App = { id: string; name: string; logo: string }; - const StyledContainer = styled.div` display: flex; align-items: center; @@ -56,52 +58,85 @@ const StyledButtonContainer = styled.div` gap: 10px; width: 100%; `; + +const StyledScopeList = styled.ul` + list-style: none; + padding: 0; + margin: 0 0 ${({ theme }) => theme.spacing(4)} 0; + width: 100%; +`; + +const StyledScopeItem = styled.li` + color: ${({ theme }) => theme.font.color.secondary}; + font-size: ${({ theme }) => theme.font.size.md}; + padding: ${({ theme }) => theme.spacing(1)} 0; + border-bottom: 1px solid ${({ theme }) => theme.border.color.light}; + + &:last-child { + border-bottom: none; + } +`; + export const Authorize = () => { const { t } = useLingui(); const navigate = useNavigateApp(); const [searchParam] = useSearchParams(); const { redirect } = useRedirect(); - //TODO: Replace with db call for registered third party apps - const [apps] = useState([ - { - id: 'chrome', - name: 'Chrome Extension', - logo: 'images/integrations/chrome-icon.svg', - }, - ]); - const [app, setApp] = useState(); + + const oauthScopeLabels: { [scope: string]: string | undefined } = { + api: t`Access workspace data`, + profile: t`Read your profile`, + }; + const clientId = searchParam.get('clientId'); const codeChallenge = searchParam.get('codeChallenge'); const redirectUrl = searchParam.get('redirectUrl'); - useEffect(() => { - const app = apps.find((app) => app.id === clientId); - if (!isDefined(app)) navigate(AppPath.NotFound); - else setApp(app); - //eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + const { data, loading } = useQuery( + FIND_APPLICATION_REGISTRATION_BY_CLIENT_ID, + { + variables: { clientId: clientId ?? '' }, + skip: !isDefined(clientId), + }, + ); + const applicationRegistration = data?.findApplicationRegistrationByClientId; const [authorizeApp] = useAuthorizeAppMutation(); + const [hasLogoError, setHasLogoError] = useState(false); + + const shouldRedirectToNotFound = + !isDefined(clientId) || (!loading && !isDefined(applicationRegistration)); + + useEffect(() => { + if (shouldRedirectToNotFound) { + navigate(AppPath.NotFound); + } + }, [shouldRedirectToNotFound, navigate]); + const handleAuthorize = async () => { - if ( - isDefined(clientId) && - isDefined(codeChallenge) && - isDefined(redirectUrl) - ) { + if (isDefined(clientId) && isDefined(redirectUrl)) { await authorizeApp({ variables: { clientId, - codeChallenge, + codeChallenge: codeChallenge ?? undefined, redirectUrl, }, - onCompleted: (data) => { - redirect(data.authorizeApp.redirectUrl); + onCompleted: (responseData) => { + redirect(responseData.authorizeApp.redirectUrl); }, }); } }; - const appName = app?.name; + if (loading || !applicationRegistration) { + return null; + } + + const appName = applicationRegistration.name; + const appLogoUrl = applicationRegistration.logoUrl; + const requestedScopes: string[] = applicationRegistration.oAuthScopes ?? []; + + const showLogoImage = isNonEmptyString(appLogoUrl) && !hasLogoError; return ( @@ -119,11 +154,36 @@ export const Authorize = () => { height={60} width={60} /> - app-icon + {showLogoImage ? ( + {appName} setHasLogoError(true)} + /> + ) : ( + + )} {appName} wants to access your account + {requestedScopes.length > 0 && ( + + {requestedScopes.map((scope) => ( + + {oauthScopeLabels[scope] ?? scope} + + ))} + + )} diff --git a/packages/twenty-front/src/pages/auth/SignInUp.tsx b/packages/twenty-front/src/pages/auth/SignInUp.tsx index 7f3561bc1e..e572ad71fb 100644 --- a/packages/twenty-front/src/pages/auth/SignInUp.tsx +++ b/packages/twenty-front/src/pages/auth/SignInUp.tsx @@ -35,7 +35,7 @@ import { useSearchParams } from 'react-router-dom'; import { isDefined } from 'twenty-shared/utils'; import { Loader } from 'twenty-ui/feedback'; import { AnimatedEaseIn } from 'twenty-ui/utilities'; -import { type PublicWorkspaceDataOutput } from '~/generated-metadata/graphql'; +import { type PublicWorkspaceData } from '~/generated-metadata/graphql'; const StyledLoaderContainer = styled.div` align-items: center; @@ -53,7 +53,7 @@ const StandardContent = ({ title, onClickOnLogo, }: { - workspacePublicData: PublicWorkspaceDataOutput | null; + workspacePublicData: PublicWorkspaceData | null; signInUpForm: JSX.Element | null; signInUpStep: SignInUpStep; title: string; diff --git a/packages/twenty-front/src/pages/auth/__stories__/PasswordReset.stories.tsx b/packages/twenty-front/src/pages/auth/__stories__/PasswordReset.stories.tsx index ad217808eb..a7732dfdec 100644 --- a/packages/twenty-front/src/pages/auth/__stories__/PasswordReset.stories.tsx +++ b/packages/twenty-front/src/pages/auth/__stories__/PasswordReset.stories.tsx @@ -27,7 +27,7 @@ const buildHandlers = (hasPassword: boolean) => [ HttpResponse.json({ data: { validatePasswordResetToken: { - __typename: 'ValidatePasswordResetTokenOutput', + __typename: 'ValidatePasswordResetToken', id: mockedOnboardingUsersData.id, email: mockedOnboardingUsersData.email, hasPassword, diff --git a/packages/twenty-front/src/pages/settings/applications/SettingsApplicationRegistrationDetails.tsx b/packages/twenty-front/src/pages/settings/applications/SettingsApplicationRegistrationDetails.tsx new file mode 100644 index 0000000000..11fa16e105 --- /dev/null +++ b/packages/twenty-front/src/pages/settings/applications/SettingsApplicationRegistrationDetails.tsx @@ -0,0 +1,626 @@ +import { SettingsAdminTableCard } from '@/settings/admin-panel/components/SettingsAdminTableCard'; +import { DELETE_APPLICATION_REGISTRATION } from '@/settings/application-registrations/graphql/mutations/deleteApplicationRegistration'; +import { ROTATE_APPLICATION_REGISTRATION_CLIENT_SECRET } from '@/settings/application-registrations/graphql/mutations/rotateApplicationRegistrationClientSecret'; +import { UPDATE_APPLICATION_REGISTRATION } from '@/settings/application-registrations/graphql/mutations/updateApplicationRegistration'; +import { UPDATE_APPLICATION_REGISTRATION_VARIABLE } from '@/settings/application-registrations/graphql/mutations/updateApplicationRegistrationVariable'; +import { FIND_APPLICATION_REGISTRATION_STATS } from '@/settings/application-registrations/graphql/queries/findApplicationRegistrationStats'; +import { FIND_APPLICATION_REGISTRATION_VARIABLES } from '@/settings/application-registrations/graphql/queries/findApplicationRegistrationVariables'; +import { FIND_MANY_APPLICATION_REGISTRATIONS } from '@/settings/application-registrations/graphql/queries/findManyApplicationRegistrations'; +import { FIND_ONE_APPLICATION_REGISTRATION } from '@/settings/application-registrations/graphql/queries/findOneApplicationRegistration'; +import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons'; +import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; +import { ApiKeyInput } from '@/settings/developers/components/ApiKeyInput'; +import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; +import { SettingsTextInput } from '@/ui/input/components/SettingsTextInput'; +import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; +import { useModal } from '@/ui/layout/modal/hooks/useModal'; +import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer'; +import { useAtomFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilyStateValue'; +import { useMutation, useQuery } from '@apollo/client'; +import styled from '@emotion/styled'; +import { Trans, useLingui } from '@lingui/react/macro'; +import { isNonEmptyString } from '@sniptt/guards'; +import { useState } from 'react'; +import { useParams } from 'react-router-dom'; +import { SettingsPath } from 'twenty-shared/types'; +import { getSettingsPath, isDefined, isValidUrl } from 'twenty-shared/utils'; +import { + H2Title, + IconChartBar, + IconCheck, + IconDownload, + IconKey, + IconRefresh, + IconShield, + IconTag, + IconTextCaption, + IconTrash, + IconWorld, + Status, +} from 'twenty-ui/display'; +import { Button } from 'twenty-ui/input'; +import { Section } from 'twenty-ui/layout'; +import { useCopyToClipboard } from '~/hooks/useCopyToClipboard'; +import { useNavigateSettings } from '~/hooks/useNavigateSettings'; +import { applicationRegistrationClientSecretFamilyState } from '~/pages/settings/applications/states/applicationRegistrationClientSecretFamilyState'; + +const DELETE_REGISTRATION_MODAL_ID = 'delete-application-registration-modal'; +const ROTATE_SECRET_MODAL_ID = 'rotate-application-registration-secret-modal'; + +const StyledInputContainer = styled.div` + align-items: center; + display: flex; + flex-direction: row; + gap: ${({ theme }) => theme.spacing(2)}; + width: 100%; +`; + +const StyledRedirectUriRow = styled.div` + align-items: center; + display: flex; + gap: ${({ theme }) => theme.spacing(2)}; + padding: ${({ theme }) => theme.spacing(1)} 0; +`; + +const StyledRedirectUriValue = styled.span` + color: ${({ theme }) => theme.font.color.primary}; + font-family: monospace; + word-break: break-all; +`; + +const StyledVariableRow = styled.div` + align-items: center; + border-bottom: 1px solid ${({ theme }) => theme.border.color.light}; + display: flex; + gap: ${({ theme }) => theme.spacing(2)}; + padding: ${({ theme }) => theme.spacing(2)} 0; +`; + +const StyledVariableInfo = styled.div` + flex: 1; + display: flex; + flex-direction: column; + gap: ${({ theme }) => theme.spacing(0.5)}; +`; + +const StyledVariableKey = styled.span` + color: ${({ theme }) => theme.font.color.primary}; + font-family: monospace; + font-weight: ${({ theme }) => theme.font.weight.medium}; +`; + +const StyledVariableDescription = styled.span` + color: ${({ theme }) => theme.font.color.tertiary}; + font-size: ${({ theme }) => theme.font.size.sm}; +`; + +const StyledRotateContainer = styled.div` + padding-top: ${({ theme }) => theme.spacing(2)}; +`; + +type ServerVariable = { + id: string; + key: string; + description: string; + isSecret: boolean; + isRequired: boolean; + isFilled: boolean; +}; + +export const SettingsApplicationRegistrationDetails = () => { + const { t } = useLingui(); + const navigate = useNavigateSettings(); + const { copyToClipboard } = useCopyToClipboard(); + const { enqueueSuccessSnackBar, enqueueErrorSnackBar } = useSnackBar(); + const { openModal } = useModal(); + const { applicationRegistrationId = '' } = useParams<{ + applicationRegistrationId: string; + }>(); + + const applicationRegistrationClientSecret = useAtomFamilyStateValue( + applicationRegistrationClientSecretFamilyState, + applicationRegistrationId, + ); + + const [isLoading, setIsLoading] = useState(false); + const [formRedirectUris, setFormRedirectUris] = useState([]); + const [newRedirectUri, setNewRedirectUri] = useState(''); + const [hasChanges, setHasChanges] = useState(false); + const [rotatedSecret, setRotatedSecret] = useState(null); + + const [variableValues, setVariableValues] = useState>( + {}, + ); + + const { data, loading } = useQuery(FIND_ONE_APPLICATION_REGISTRATION, { + variables: { id: applicationRegistrationId }, + skip: !applicationRegistrationId, + onCompleted: (result) => { + const foundRegistration = result?.findOneApplicationRegistration; + + if (isDefined(foundRegistration)) { + setFormRedirectUris(foundRegistration.oAuthRedirectUris ?? []); + } + }, + }); + + const { data: variablesData } = useQuery( + FIND_APPLICATION_REGISTRATION_VARIABLES, + { + variables: { applicationRegistrationId }, + skip: !applicationRegistrationId, + }, + ); + + const { data: statsData } = useQuery(FIND_APPLICATION_REGISTRATION_STATS, { + variables: { id: applicationRegistrationId }, + skip: !applicationRegistrationId, + }); + + const [updateRegistration] = useMutation(UPDATE_APPLICATION_REGISTRATION, { + refetchQueries: [ + FIND_ONE_APPLICATION_REGISTRATION, + FIND_MANY_APPLICATION_REGISTRATIONS, + ], + }); + const [deleteRegistration] = useMutation(DELETE_APPLICATION_REGISTRATION, { + refetchQueries: [FIND_MANY_APPLICATION_REGISTRATIONS], + }); + const [rotateSecret] = useMutation( + ROTATE_APPLICATION_REGISTRATION_CLIENT_SECRET, + ); + const [updateVariable] = useMutation( + UPDATE_APPLICATION_REGISTRATION_VARIABLE, + { + refetchQueries: [FIND_APPLICATION_REGISTRATION_VARIABLES], + }, + ); + + const registration = data?.findOneApplicationRegistration; + const variables: ServerVariable[] = + variablesData?.findApplicationRegistrationVariables ?? []; + + if (loading || !registration) { + return null; + } + + const markDirty = () => setHasChanges(true); + + const handleSave = async () => { + setIsLoading(true); + try { + await updateRegistration({ + variables: { + input: { + id: applicationRegistrationId, + update: { + oAuthRedirectUris: formRedirectUris, + }, + }, + }, + }); + setHasChanges(false); + enqueueSuccessSnackBar({ message: t`App updated` }); + } catch { + enqueueErrorSnackBar({ message: t`Error updating app` }); + } finally { + setIsLoading(false); + } + }; + + const handleCancel = () => { + setFormRedirectUris(registration.oAuthRedirectUris ?? []); + setHasChanges(false); + }; + + const handleDelete = async () => { + setIsLoading(true); + try { + await deleteRegistration({ + variables: { id: applicationRegistrationId }, + }); + navigate(SettingsPath.Applications); + } catch { + enqueueErrorSnackBar({ + message: t`Error deleting app`, + }); + } finally { + setIsLoading(false); + } + }; + + const handleRotateSecret = async () => { + setIsLoading(true); + try { + const result = await rotateSecret({ + variables: { id: applicationRegistrationId }, + }); + const secret = + result.data?.rotateApplicationRegistrationClientSecret?.clientSecret; + + if (isNonEmptyString(secret)) { + setRotatedSecret(secret); + enqueueSuccessSnackBar({ + message: t`Client secret rotated. Copy it now — it won't be shown again.`, + }); + } + } catch { + enqueueErrorSnackBar({ + message: t`Error rotating client secret`, + }); + } finally { + setIsLoading(false); + } + }; + + const handleAddRedirectUri = () => { + const trimmed = newRedirectUri.trim(); + + if (!trimmed) { + return; + } + + if (!isValidUrl(trimmed)) { + enqueueErrorSnackBar({ message: t`Please enter a valid URL` }); + + return; + } + + if (formRedirectUris.includes(trimmed)) { + enqueueErrorSnackBar({ message: t`This redirect URI is already added` }); + + return; + } + + setFormRedirectUris([...formRedirectUris, trimmed]); + setNewRedirectUri(''); + markDirty(); + }; + + const handleRemoveRedirectUri = (index: number) => { + setFormRedirectUris( + formRedirectUris.filter((_, uriIndex) => uriIndex !== index), + ); + markDirty(); + }; + + const handleSaveVariableValue = async (variable: ServerVariable) => { + const value = variableValues[variable.id]; + const variableKey = variable.key; + + if (!isNonEmptyString(value)) { + return; + } + + try { + await updateVariable({ + variables: { + input: { + id: variable.id, + update: { + value, + }, + }, + }, + }); + setVariableValues((previous) => { + const next = { ...previous }; + + delete next[variable.id]; + + return next; + }); + enqueueSuccessSnackBar({ + message: t`Variable ${variableKey} updated`, + }); + } catch { + enqueueErrorSnackBar({ + message: t`Error updating variable`, + }); + } + }; + + const displayedSecret = applicationRegistrationClientSecret ?? rotatedSecret; + const confirmationValue = t`yes`; + + const credentialItems = [ + { + Icon: IconKey, + label: t`Client ID`, + value: registration.oAuthClientId, + onClick: () => + copyToClipboard(registration.oAuthClientId, t`Client ID copied`), + }, + { + Icon: IconShield, + label: t`Scopes`, + value: (registration.oAuthScopes ?? []).join(', ') || '—', + }, + ]; + + const generalItems = [ + { + Icon: IconTag, + label: t`Name`, + value: registration.name, + }, + ...(isNonEmptyString(registration.description) + ? [ + { + Icon: IconTextCaption, + label: t`Description`, + value: registration.description, + }, + ] + : []), + { + Icon: IconWorld, + label: t`Universal ID`, + value: registration.universalIdentifier, + onClick: () => + copyToClipboard( + registration.universalIdentifier, + t`Universal identifier copied`, + ), + }, + ]; + + const stats = statsData?.findApplicationRegistrationStats; + const hasActiveInstalls = (stats?.activeInstalls ?? 0) > 0; + + const versionDistributionLabel = + stats?.versionDistribution + ?.map( + (entry: { version: string; count: number }) => + `${entry.version} (${entry.count})`, + ) + .join(', ') || '—'; + + const statsItems = [ + { + Icon: IconDownload, + label: t`Active installs`, + value: stats?.activeInstalls ?? '—', + }, + { + Icon: IconTag, + label: t`Most installed version`, + value: stats?.mostInstalledVersion ?? '—', + }, + { + Icon: IconChartBar, + label: t`Distribution`, + value: versionDistributionLabel, + }, + ]; + + return ( + <> + + ) : undefined + } + > + + {stats && stats.activeInstalls > 0 && ( +
+ + +
+ )} + +
+ + +
+ +
+ + + +
+ + {displayedSecret && ( +
+ + +
+ )} + +
+ + {formRedirectUris.map((uri, index) => ( + + {uri} +
+ + {variables.length > 0 && ( +
+ + {variables.map((variable) => ( + + + + {variable.key} + {variable.isRequired && ( + * + )} + + {isNonEmptyString(variable.description) && ( + + {variable.description} + + )} + + {variable.isFilled && + !isNonEmptyString(variableValues[variable.id]) && ( + + )} + {!variable.isFilled && + !isNonEmptyString(variableValues[variable.id]) && ( + + )} + + setVariableValues((previous) => ({ + ...previous, + [variable.id]: value, + })) + } + placeholder={ + variable.isSecret ? t`Enter secret value` : t`Enter value` + } + fullWidth + /> +
+ )} + +
+ +
+
+
+ + + If you rotate this secret, any integration using the current secret + will stop working. Please type {`"${confirmationValue}"`} to + confirm. + + } + onConfirmClick={handleRotateSecret} + confirmButtonText={t`Rotate secret`} + loading={isLoading} + /> + + + Please type {`"${confirmationValue}"`} to confirm you want to delete + this app. All workspace installations linked to it will lose their + OAuth credentials. + + } + onConfirmClick={handleDelete} + confirmButtonText={t`Delete`} + loading={isLoading} + /> + + ); +}; diff --git a/packages/twenty-front/src/pages/settings/applications/SettingsApplications.tsx b/packages/twenty-front/src/pages/settings/applications/SettingsApplications.tsx index 712db07dda..e1afaaa165 100644 --- a/packages/twenty-front/src/pages/settings/applications/SettingsApplications.tsx +++ b/packages/twenty-front/src/pages/settings/applications/SettingsApplications.tsx @@ -1,3 +1,4 @@ +import { useHasPermissionFlag } from '@/settings/roles/hooks/useHasPermissionFlag'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer'; import { TabList } from '@/ui/layout/tab-list/components/TabList'; @@ -10,11 +11,12 @@ import { getSettingsPath } from 'twenty-shared/utils'; import { IconApps, IconCode, IconDownload } from 'twenty-ui/display'; import { type FeatureFlagKey, + PermissionFlagType, useFindManyApplicationsQuery, } from '~/generated-metadata/graphql'; import { SettingsApplicationsTable } from '~/pages/settings/applications/components/SettingsApplicationsTable'; import { SettingsApplicationsAvailableTab } from '~/pages/settings/applications/tabs/SettingsApplicationsAvailableTab'; -import { SettingsApplicationsCreateTab } from '~/pages/settings/applications/tabs/SettingsApplicationsCreateTab'; +import { SettingsApplicationsDeveloperTab } from '~/pages/settings/applications/tabs/SettingsApplicationsDeveloperTab'; import { SettingsApplicationsInstalledTab } from '~/pages/settings/applications/tabs/SettingsApplicationsInstalledTab'; const APPLICATIONS_TAB_LIST_ID = 'applications-tab-list'; @@ -22,6 +24,10 @@ const APPLICATIONS_TAB_LIST_ID = 'applications-tab-list'; export const SettingsApplications = () => { const { t } = useLingui(); + const hasDeveloperAccess = useHasPermissionFlag( + PermissionFlagType.API_KEYS_AND_WEBHOOKS, + ); + const isMarketplaceEnabled = useIsFeatureEnabled( 'IS_MARKETPLACE_ENABLED' as FeatureFlagKey, ); @@ -51,26 +57,28 @@ export const SettingsApplications = () => { {applications.length > 0 && ( )} - + {hasDeveloperAccess && } ); } const tabs = [ - { id: 'available', title: t`Available`, Icon: IconDownload }, + { id: 'marketplace', title: t`Marketplace`, Icon: IconDownload }, { id: 'installed', title: t`Installed`, Icon: IconApps }, - { id: 'create', title: t`Create an app`, Icon: IconCode }, + ...(hasDeveloperAccess + ? [{ id: 'developer', title: t`Developer`, Icon: IconCode }] + : []), ]; const renderActiveTabContent = () => { switch (activeTabId) { - case 'available': + case 'marketplace': return ; case 'installed': return ; - case 'create': - return ; + case 'developer': + return ; default: return ; } diff --git a/packages/twenty-front/src/pages/settings/applications/states/applicationRegistrationClientSecretFamilyState.ts b/packages/twenty-front/src/pages/settings/applications/states/applicationRegistrationClientSecretFamilyState.ts new file mode 100644 index 0000000000..239879d1af --- /dev/null +++ b/packages/twenty-front/src/pages/settings/applications/states/applicationRegistrationClientSecretFamilyState.ts @@ -0,0 +1,7 @@ +import { createAtomFamilyState } from '@/ui/utilities/state/jotai/utils/createAtomFamilyState'; + +export const applicationRegistrationClientSecretFamilyState = + createAtomFamilyState({ + key: 'applicationRegistrationClientSecretState', + defaultValue: null, + }); diff --git a/packages/twenty-front/src/pages/settings/applications/tabs/SettingsApplicationsCreateTab.tsx b/packages/twenty-front/src/pages/settings/applications/tabs/SettingsApplicationsCreateTab.tsx deleted file mode 100644 index 11120f2920..0000000000 --- a/packages/twenty-front/src/pages/settings/applications/tabs/SettingsApplicationsCreateTab.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; -import { getDocumentationUrl } from '@/support/utils/getDocumentationUrl'; -import styled from '@emotion/styled'; -import { useLingui } from '@lingui/react/macro'; -import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue'; -import { - CommandBlock, - H2Title, - IconCopy, - IconFileInfo, -} from 'twenty-ui/display'; -import { Button } from 'twenty-ui/input'; -import { Section } from 'twenty-ui/layout'; -import { useCopyToClipboard } from '~/hooks/useCopyToClipboard'; - -const StyledButtonContainer = styled.div` - margin: ${({ theme }) => theme.spacing(2)} 0; -`; - -export const SettingsApplicationsCreateTab = () => { - const { t } = useLingui(); - - const currentWorkspaceMember = useAtomStateValue(currentWorkspaceMemberState); - - const { copyToClipboard } = useCopyToClipboard(); - - const commands = [ - // eslint-disable-next-line lingui/no-unlocalized-strings - 'npx create-twenty-app@latest my-twenty-app', - // eslint-disable-next-line lingui/no-unlocalized-strings - 'cd my-twenty-app', - ]; - - const button = ( -