Merge branch 'main' into feat/multipleApprovalEnvs

This commit is contained in:
Carlos Monastyrski
2025-07-24 12:03:07 -03:00
595 changed files with 12408 additions and 6322 deletions
@@ -4,8 +4,10 @@ import { apiRequest } from "@app/config/request";
import { appConnectionKeys } from "../queries";
import {
TBitbucketConnectionListEnvironmentsResponse,
TBitbucketConnectionListRepositoriesResponse,
TBitbucketConnectionListWorkspacesResponse,
TBitbucketEnvironment,
TBitbucketRepo,
TBitbucketWorkspace
} from "./types";
@@ -15,7 +17,9 @@ const bitbucketConnectionKeys = {
listRepos: (connectionId: string, workspaceSlug: string) =>
[...bitbucketConnectionKeys.all, "repos", connectionId, workspaceSlug] as const,
listWorkspaces: (connectionId: string) =>
[...bitbucketConnectionKeys.all, "workspaces", connectionId] as const
[...bitbucketConnectionKeys.all, "workspaces", connectionId] as const,
listEnvironments: (connectionId: string, workspaceSlug: string, repoSlug: string) =>
[...bitbucketConnectionKeys.all, "environments", connectionId, workspaceSlug, repoSlug] as const
};
export const useBitbucketConnectionListWorkspaces = (
@@ -68,3 +72,30 @@ export const useBitbucketConnectionListRepositories = (
...options
});
};
export const useBitbucketConnectionListEnvironments = (
connectionId: string,
workspaceSlug: string,
repoSlug: string,
options?: Omit<
UseQueryOptions<
TBitbucketEnvironment[],
unknown,
TBitbucketEnvironment[],
ReturnType<typeof bitbucketConnectionKeys.listEnvironments>
>,
"queryKey" | "queryFn"
>
) => {
return useQuery({
queryKey: bitbucketConnectionKeys.listEnvironments(connectionId, workspaceSlug, repoSlug),
queryFn: async () => {
const { data } = await apiRequest.get<TBitbucketConnectionListEnvironmentsResponse>(
`/api/v1/app-connections/bitbucket/${connectionId}/environments?workspaceSlug=${encodeURIComponent(workspaceSlug)}&repositorySlug=${encodeURIComponent(repoSlug)}`
);
return data.environments;
},
...options
});
};
@@ -15,3 +15,13 @@ export type TBitbucketConnectionListWorkspacesResponse = {
export type TBitbucketConnectionListRepositoriesResponse = {
repositories: TBitbucketRepo[];
};
export type TBitbucketEnvironment = {
uuid: string;
name: string;
slug: string;
};
export type TBitbucketConnectionListEnvironmentsResponse = {
environments: TBitbucketEnvironment[];
};
@@ -0,0 +1 @@
export * from "./queries";
@@ -0,0 +1,37 @@
import { useQuery, UseQueryOptions } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request";
import { appConnectionKeys } from "@app/hooks/api/appConnections";
import { TDigitalOceanApp } from "./types";
const digitalOceanAppPlatformConnectionKeys = {
all: [...appConnectionKeys.all, "digitalOceanAppPlatform"] as const,
listAccounts: (connectionId: string) =>
[...digitalOceanAppPlatformConnectionKeys.all, "workspace-scopes", connectionId] as const
};
export const useDigitalOceanConnectionListApps = (
connectionId: string,
options?: Omit<
UseQueryOptions<
TDigitalOceanApp[],
unknown,
TDigitalOceanApp[],
ReturnType<typeof digitalOceanAppPlatformConnectionKeys.listAccounts>
>,
"queryKey" | "queryFn"
>
) => {
return useQuery({
queryKey: digitalOceanAppPlatformConnectionKeys.listAccounts(connectionId),
queryFn: async () => {
const { data } = await apiRequest.get<{ apps: TDigitalOceanApp[] }>(
`/api/v1/app-connections/digital-ocean/${connectionId}/apps`
);
return data.apps;
},
...options
});
};
@@ -0,0 +1,16 @@
export type TDigitalOceanAppPlatformVariable = {
key: string;
value: string;
type: "SECRET" | "GENERAL";
};
export type TDigitalOceanApp = {
id: string;
spec: {
name: string;
services: Array<{
name: string;
}>;
envs?: TDigitalOceanAppPlatformVariable[];
};
};
@@ -33,5 +33,6 @@ export enum AppConnection {
Railway = "railway",
Checkly = "checkly",
Supabase = "supabase",
DigitalOcean = "digital-ocean",
Okta = "okta"
}
@@ -152,6 +152,10 @@ export type TSupabaseConnectionOption = TAppConnectionOptionBase & {
app: AppConnection.Supabase;
};
export type TDigitalOceanConnectionOption = TAppConnectionOptionBase & {
app: AppConnection.DigitalOcean;
};
export type TOktaConnectionOption = TAppConnectionOptionBase & {
app: AppConnection.Okta;
};
@@ -188,6 +192,7 @@ export type TAppConnectionOption =
| TZabbixConnectionOption
| TRailwayConnectionOption
| TChecklyConnectionOption
| TDigitalOceanConnectionOption
| TOktaConnectionOption;
export type TAppConnectionOptionMap = {
@@ -225,5 +230,6 @@ export type TAppConnectionOptionMap = {
[AppConnection.Railway]: TRailwayConnectionOption;
[AppConnection.Checkly]: TChecklyConnectionOption;
[AppConnection.Supabase]: TSupabaseConnectionOption;
[AppConnection.DigitalOcean]: TDigitalOceanConnectionOption;
[AppConnection.Okta]: TOktaConnectionOption;
};
@@ -0,0 +1,14 @@
import { AppConnection } from "@app/hooks/api/appConnections/enums";
import { TRootAppConnection } from "@app/hooks/api/appConnections/types/root-connection";
export enum DigitalOceanConnectionMethod {
ApiToken = "api-token"
}
export type TDigitalOceanConnection = TRootAppConnection & {
app: AppConnection.DigitalOcean;
method: DigitalOceanConnectionMethod.ApiToken;
credentials: {
apiToken: string;
};
};
@@ -12,6 +12,7 @@ import { TCamundaConnection } from "./camunda-connection";
import { TChecklyConnection } from "./checkly-connection";
import { TCloudflareConnection } from "./cloudflare-connection";
import { TDatabricksConnection } from "./databricks-connection";
import { TDigitalOceanConnection } from "./digital-ocean";
import { TFlyioConnection } from "./flyio-connection";
import { TGcpConnection } from "./gcp-connection";
import { TGitHubConnection } from "./github-connection";
@@ -107,6 +108,7 @@ export type TAppConnection =
| TRailwayConnection
| TChecklyConnection
| TSupabaseConnection
| TDigitalOceanConnection
| TOktaConnection;
export type TAvailableAppConnection = Pick<TAppConnection, "name" | "id">;
@@ -178,5 +180,6 @@ export type TAppConnectionMap = {
[AppConnection.Railway]: TRailwayConnection;
[AppConnection.Checkly]: TChecklyConnection;
[AppConnection.Supabase]: TSupabaseConnection;
[AppConnection.DigitalOcean]: TDigitalOceanConnection;
[AppConnection.Okta]: TOktaConnection;
};
+1 -1
View File
@@ -51,7 +51,7 @@ export type IdentityMembershipOrg = {
export type IdentityMembership = {
id: string;
identity: Identity;
project: Pick<Workspace, "id" | "name" | "defaultProduct">;
project: Pick<Workspace, "id" | "name" | "type">;
roles: Array<
{
id: string;
@@ -1,9 +1,12 @@
import { TProjectRole } from "@app/hooks/api/roles/types";
import { ProjectType } from "../workspace/types";
export type TProjectTemplate = {
id: string;
name: string;
description?: string;
type: ProjectType;
roles: Pick<TProjectRole, "slug" | "name" | "permissions">[];
environments?: { name: string; slug: string; position: number }[] | null;
createdAt: string;
@@ -16,6 +19,7 @@ export type TProjectTemplateResponse = { projectTemplate: TProjectTemplate };
export type TCreateProjectTemplateDTO = {
name: string;
description?: string;
type?: ProjectType;
};
export type TUpdateProjectTemplateDTO = Partial<
@@ -0,0 +1 @@
export { useCreateReminder, useDeleteReminder, useGetReminder } from "./queries";
@@ -0,0 +1,60 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request";
import { CreateReminderDTO, DeleteReminderDTO, Reminder } from "./types";
export const reminderKeys = {
getReminder: (secretId: string) => ["get-reminder", secretId] as const
};
export const useCreateReminder = (secretId: string) => {
const queryClient = useQueryClient();
return useMutation<Reminder, object, CreateReminderDTO>({
mutationFn: async ({ message, repeatDays, nextReminderDate, recipients }) => {
const { data } = await apiRequest.post<{ reminder: Reminder }>(
`/api/v1/reminders/secrets/${secretId}`,
{
message,
repeatDays,
nextReminderDate,
recipients
}
);
return data.reminder;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: reminderKeys.getReminder(secretId) });
}
});
};
export const useDeleteReminder = (secretId: string) => {
const queryClient = useQueryClient();
return useMutation<Reminder, object, DeleteReminderDTO>({
mutationFn: async () => {
const { data } = await apiRequest.delete<{ reminder: Reminder }>(
`/api/v1/reminders/secrets/${secretId}`
);
return data.reminder;
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: reminderKeys.getReminder(secretId) });
}
});
};
export const useGetReminder = (secretId: string) => {
return useQuery({
queryKey: reminderKeys.getReminder(secretId),
queryFn: async () => {
const { data } = await apiRequest.get<{ reminder: Reminder }>(
`/api/v1/reminders/secrets/${secretId}`
);
return data.reminder;
},
enabled: Boolean(secretId)
});
};
+14
View File
@@ -0,0 +1,14 @@
export type CreateReminderDTO = {
message?: string | null;
repeatDays?: number | null;
nextReminderDate?: Date | null;
secretId: string;
recipients?: string[];
};
export type DeleteReminderDTO = {
secretId: string;
reminderId: string;
};
export type Reminder = { id: string } & CreateReminderDTO;
+3 -1
View File
@@ -25,7 +25,9 @@ export enum SecretSync {
Supabase = "supabase",
Zabbix = "zabbix",
Railway = "railway",
Checkly = "checkly"
Checkly = "checkly",
DigitalOceanAppPlatform = "digital-ocean-app-platform",
Bitbucket = "bitbucket"
}
export enum SecretSyncStatus {
@@ -0,0 +1,17 @@
import { AppConnection } from "@app/hooks/api/appConnections/enums";
import { SecretSync } from "@app/hooks/api/secretSyncs";
import { TRootSecretSync } from "@app/hooks/api/secretSyncs/types/root-sync";
export type TBitbucketSync = TRootSecretSync & {
destination: SecretSync.Bitbucket;
destinationConfig: {
workspaceSlug: string;
repositorySlug: string;
environmentId?: string;
};
connection: {
app: AppConnection.Bitbucket;
name: string;
id: string;
};
};
@@ -0,0 +1,17 @@
/* eslint-disable @typescript-eslint/no-empty-object-type */
import { AppConnection } from "@app/hooks/api/appConnections/enums";
import { SecretSync } from "@app/hooks/api/secretSyncs";
import { TRootSecretSync } from "@app/hooks/api/secretSyncs/types/root-sync";
export type TDigitalOceanAppPlatformSync = TRootSecretSync & {
destination: SecretSync.DigitalOceanAppPlatform;
destinationConfig: {
appId: string;
appName: string;
};
connection: {
app: AppConnection.DigitalOcean;
name: string;
id: string;
};
};
@@ -8,11 +8,13 @@ import { TAwsSecretsManagerSync } from "./aws-secrets-manager-sync";
import { TAzureAppConfigurationSync } from "./azure-app-configuration-sync";
import { TAzureDevOpsSync } from "./azure-devops-sync";
import { TAzureKeyVaultSync } from "./azure-key-vault-sync";
import { TBitbucketSync } from "./bitbucket-sync";
import { TCamundaSync } from "./camunda-sync";
import { TChecklySync } from "./checkly-sync";
import { TCloudflarePagesSync } from "./cloudflare-pages-sync";
import { TCloudflareWorkersSync } from "./cloudflare-workers-sync";
import { TDatabricksSync } from "./databricks-sync";
import { TDigitalOceanAppPlatformSync } from "./digital-ocean-app-platform-sync";
import { TFlyioSync } from "./flyio-sync";
import { TGcpSync } from "./gcp-sync";
import { TGitHubSync } from "./github-sync";
@@ -63,7 +65,9 @@ export type TSecretSync =
| TZabbixSync
| TRailwaySync
| TChecklySync
| TSupabaseSync;
| TSupabaseSync
| TDigitalOceanAppPlatformSync
| TBitbucketSync;
export type TListSecretSyncs = { secretSyncs: TSecretSync[] };
+4 -5
View File
@@ -255,12 +255,13 @@ export const useCreateWorkspace = () => {
const queryClient = useQueryClient();
return useMutation<{ data: { project: Workspace } }, object, CreateWorkspaceDTO>({
mutationFn: async ({ projectName, projectDescription, kmsKeyId, template }) =>
mutationFn: async ({ projectName, projectDescription, kmsKeyId, template, type }) =>
createWorkspace({
projectName,
projectDescription,
kmsKeyId,
template
template,
type
}),
onSuccess: () => {
queryClient.invalidateQueries({
@@ -280,8 +281,7 @@ export const useUpdateProject = () => {
newProjectDescription,
newSlug,
secretSharing,
showSnapshotsLegacy,
defaultProduct
showSnapshotsLegacy
}) => {
const { data } = await apiRequest.patch<{ workspace: Workspace }>(
`/api/v1/workspace/${projectID}`,
@@ -289,7 +289,6 @@ export const useUpdateProject = () => {
name: newProjectName,
description: newProjectDescription,
slug: newSlug,
defaultProduct,
secretSharing,
showSnapshotsLegacy
}
+3 -2
View File
@@ -24,7 +24,7 @@ export type Workspace = {
__v: number;
id: string;
name: string;
defaultProduct: ProjectType;
type: ProjectType;
description?: string;
orgId: string;
version: ProjectVersion;
@@ -68,6 +68,7 @@ export type TGetUpgradeProjectStatusDTO = {
// mutation dto
export type CreateWorkspaceDTO = {
projectName: string;
type: ProjectType;
projectDescription?: string;
kmsKeyId?: string;
template?: string;
@@ -80,7 +81,6 @@ export type UpdateProjectDTO = {
newSlug?: string;
secretSharing?: boolean;
showSnapshotsLegacy?: boolean;
defaultProduct?: ProjectType;
};
export type UpdatePitVersionLimitDTO = { projectSlug: string; pitVersionLimit: number };
@@ -184,6 +184,7 @@ export type TSearchProjectsDTO = {
name?: string;
limit?: number;
offset?: number;
type?: ProjectType;
options?: { enabled?: boolean };
orderBy?: ProjectIdentityOrderBy;
orderDirection?: OrderByDirection;