mirror of
https://github.com/sourcebot-dev/sourcebot.git
synced 2025-12-12 04:15:30 +00:00
remove dead code
This commit is contained in:
parent
c56433d8a9
commit
f6d5820ee2
3 changed files with 16 additions and 466 deletions
|
|
@ -5,46 +5,32 @@ import { env } from "@/env.mjs";
|
|||
import { addUserToOrganization, orgHasAvailability } from "@/lib/authUtils";
|
||||
import { ErrorCode } from "@/lib/errorCodes";
|
||||
import { notAuthenticated, notFound, orgNotFound, secretAlreadyExists, ServiceError, ServiceErrorException, unexpectedError } from "@/lib/serviceError";
|
||||
import { CodeHostType, getOrgMetadata, isHttpError, isServiceError } from "@/lib/utils";
|
||||
import { getOrgMetadata, isHttpError, isServiceError } from "@/lib/utils";
|
||||
import { prisma } from "@/prisma";
|
||||
import { render } from "@react-email/components";
|
||||
import * as Sentry from '@sentry/nextjs';
|
||||
import { decrypt, encrypt, generateApiKey, getTokenFromConfig, hashSecret } from "@sourcebot/crypto";
|
||||
import { ApiKey, ConnectionSyncStatus, Org, OrgRole, Prisma, RepoIndexingStatus, RepoJobStatus, RepoJobType, StripeSubscriptionStatus } from "@sourcebot/db";
|
||||
import { encrypt, generateApiKey, getTokenFromConfig, hashSecret } from "@sourcebot/crypto";
|
||||
import { ApiKey, Org, OrgRole, Prisma, RepoJobStatus, RepoJobType, StripeSubscriptionStatus } from "@sourcebot/db";
|
||||
import { createLogger } from "@sourcebot/logger";
|
||||
import { azuredevopsSchema } from "@sourcebot/schemas/v3/azuredevops.schema";
|
||||
import { bitbucketSchema } from "@sourcebot/schemas/v3/bitbucket.schema";
|
||||
import { ConnectionConfig } from "@sourcebot/schemas/v3/connection.type";
|
||||
import { genericGitHostSchema } from "@sourcebot/schemas/v3/genericGitHost.schema";
|
||||
import { gerritSchema } from "@sourcebot/schemas/v3/gerrit.schema";
|
||||
import { giteaSchema } from "@sourcebot/schemas/v3/gitea.schema";
|
||||
import { GiteaConnectionConfig } from "@sourcebot/schemas/v3/gitea.type";
|
||||
import { githubSchema } from "@sourcebot/schemas/v3/github.schema";
|
||||
import { GithubConnectionConfig } from "@sourcebot/schemas/v3/github.type";
|
||||
import { gitlabSchema } from "@sourcebot/schemas/v3/gitlab.schema";
|
||||
import { GitlabConnectionConfig } from "@sourcebot/schemas/v3/gitlab.type";
|
||||
import { getPlan, hasEntitlement } from "@sourcebot/shared";
|
||||
import Ajv from "ajv";
|
||||
import { StatusCodes } from "http-status-codes";
|
||||
import { cookies, headers } from "next/headers";
|
||||
import { createTransport } from "nodemailer";
|
||||
import { Octokit } from "octokit";
|
||||
import { auth } from "./auth";
|
||||
import { getConnection } from "./data/connection";
|
||||
import { getOrgFromDomain } from "./data/org";
|
||||
import { decrementOrgSeatCount, getSubscriptionForOrg } from "./ee/features/billing/serverUtils";
|
||||
import { IS_BILLING_ENABLED } from "./ee/features/billing/stripe";
|
||||
import InviteUserEmail from "./emails/inviteUserEmail";
|
||||
import JoinRequestApprovedEmail from "./emails/joinRequestApprovedEmail";
|
||||
import JoinRequestSubmittedEmail from "./emails/joinRequestSubmittedEmail";
|
||||
import { AGENTIC_SEARCH_TUTORIAL_DISMISSED_COOKIE_NAME, MOBILE_UNSUPPORTED_SPLASH_SCREEN_DISMISSED_COOKIE_NAME, SEARCH_MODE_COOKIE_NAME, SINGLE_TENANT_ORG_DOMAIN, SOURCEBOT_GUEST_USER_ID, SOURCEBOT_SUPPORT_EMAIL } from "./lib/constants";
|
||||
import { AGENTIC_SEARCH_TUTORIAL_DISMISSED_COOKIE_NAME, MOBILE_UNSUPPORTED_SPLASH_SCREEN_DISMISSED_COOKIE_NAME, SINGLE_TENANT_ORG_DOMAIN, SOURCEBOT_GUEST_USER_ID, SOURCEBOT_SUPPORT_EMAIL } from "./lib/constants";
|
||||
import { orgDomainSchema, orgNameSchema, repositoryQuerySchema } from "./lib/schemas";
|
||||
import { ApiKeyPayload, TenancyMode } from "./lib/types";
|
||||
import { withAuthV2, withOptionalAuthV2 } from "./withAuthV2";
|
||||
|
||||
const ajv = new Ajv({
|
||||
validateFormats: false,
|
||||
});
|
||||
import { withOptionalAuthV2 } from "./withAuthV2";
|
||||
|
||||
const logger = createLogger('web-actions');
|
||||
const auditService = getAuditService();
|
||||
|
|
@ -187,31 +173,6 @@ export const withTenancyModeEnforcement = async<T>(mode: TenancyMode, fn: () =>
|
|||
|
||||
////// Actions ///////
|
||||
|
||||
export const createOrg = async (name: string, domain: string): Promise<{ id: number } | ServiceError> => sew(() =>
|
||||
withTenancyModeEnforcement('multi', () =>
|
||||
withAuth(async (userId) => {
|
||||
const org = await prisma.org.create({
|
||||
data: {
|
||||
name,
|
||||
domain,
|
||||
members: {
|
||||
create: {
|
||||
role: "OWNER",
|
||||
user: {
|
||||
connect: {
|
||||
id: userId,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
id: org.id,
|
||||
}
|
||||
})));
|
||||
|
||||
export const updateOrgName = async (name: string, domain: string) => sew(() =>
|
||||
withAuth((userId) =>
|
||||
withOrgMembership(userId, domain, async ({ org }) => {
|
||||
|
|
@ -573,71 +534,6 @@ export const getUserApiKeys = async (domain: string): Promise<{ name: string; cr
|
|||
}));
|
||||
})));
|
||||
|
||||
export const getConnections = async (domain: string, filter: { status?: ConnectionSyncStatus[] } = {}) => sew(() =>
|
||||
withAuth((userId) =>
|
||||
withOrgMembership(userId, domain, async ({ org }) => {
|
||||
const connections = await prisma.connection.findMany({
|
||||
where: {
|
||||
orgId: org.id,
|
||||
...(filter.status ? {
|
||||
syncStatus: { in: filter.status }
|
||||
} : {}),
|
||||
},
|
||||
include: {
|
||||
repos: {
|
||||
include: {
|
||||
repo: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return connections.map((connection) => ({
|
||||
id: connection.id,
|
||||
name: connection.name,
|
||||
syncStatus: connection.syncStatus,
|
||||
syncStatusMetadata: connection.syncStatusMetadata,
|
||||
connectionType: connection.connectionType,
|
||||
updatedAt: connection.updatedAt,
|
||||
syncedAt: connection.syncedAt ?? undefined,
|
||||
linkedRepos: connection.repos.map(({ repo }) => ({
|
||||
id: repo.id,
|
||||
name: repo.name,
|
||||
repoIndexingStatus: repo.repoIndexingStatus,
|
||||
})),
|
||||
}));
|
||||
})
|
||||
));
|
||||
|
||||
export const getConnectionInfo = async (connectionId: number, domain: string) => sew(() =>
|
||||
withAuth((userId) =>
|
||||
withOrgMembership(userId, domain, async ({ org }) => {
|
||||
const connection = await prisma.connection.findUnique({
|
||||
where: {
|
||||
id: connectionId,
|
||||
orgId: org.id,
|
||||
},
|
||||
include: {
|
||||
repos: true,
|
||||
}
|
||||
});
|
||||
|
||||
if (!connection) {
|
||||
return notFound();
|
||||
}
|
||||
|
||||
return {
|
||||
id: connection.id,
|
||||
name: connection.name,
|
||||
syncStatus: connection.syncStatus,
|
||||
syncStatusMetadata: connection.syncStatusMetadata,
|
||||
connectionType: connection.connectionType,
|
||||
updatedAt: connection.updatedAt,
|
||||
syncedAt: connection.syncedAt ?? undefined,
|
||||
numLinkedRepos: connection.repos.length,
|
||||
}
|
||||
})));
|
||||
|
||||
export const getRepos = async ({
|
||||
where,
|
||||
take,
|
||||
|
|
@ -781,54 +677,6 @@ export const getRepoInfoByName = async (repoName: string) => sew(() =>
|
|||
}
|
||||
}));
|
||||
|
||||
export const createConnection = async (name: string, type: CodeHostType, connectionConfig: string, domain: string): Promise<{ id: number } | ServiceError> => sew(() =>
|
||||
withAuth((userId) =>
|
||||
withOrgMembership(userId, domain, async ({ org }) => {
|
||||
if (env.CONFIG_PATH !== undefined) {
|
||||
return {
|
||||
statusCode: StatusCodes.BAD_REQUEST,
|
||||
errorCode: ErrorCode.CONNECTION_CONFIG_PATH_SET,
|
||||
message: "A configuration file has been provided. New connections cannot be added through the web interface.",
|
||||
} satisfies ServiceError;
|
||||
}
|
||||
|
||||
const parsedConfig = parseConnectionConfig(connectionConfig);
|
||||
if (isServiceError(parsedConfig)) {
|
||||
return parsedConfig;
|
||||
}
|
||||
|
||||
const existingConnectionWithName = await prisma.connection.findUnique({
|
||||
where: {
|
||||
name_orgId: {
|
||||
orgId: org.id,
|
||||
name,
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (existingConnectionWithName) {
|
||||
return {
|
||||
statusCode: StatusCodes.BAD_REQUEST,
|
||||
errorCode: ErrorCode.CONNECTION_ALREADY_EXISTS,
|
||||
message: "A connection with this name already exists.",
|
||||
} satisfies ServiceError;
|
||||
}
|
||||
|
||||
const connection = await prisma.connection.create({
|
||||
data: {
|
||||
orgId: org.id,
|
||||
name,
|
||||
config: parsedConfig as unknown as Prisma.InputJsonValue,
|
||||
connectionType: type,
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
id: connection.id,
|
||||
}
|
||||
}, OrgRole.OWNER)
|
||||
));
|
||||
|
||||
export const experimental_addGithubRepositoryByUrl = async (repositoryUrl: string): Promise<{ connectionId: number } | ServiceError> => sew(() =>
|
||||
withOptionalAuthV2(async ({ org, prisma }) => {
|
||||
if (env.EXPERIMENT_SELF_SERVE_REPO_INDEXING_ENABLED !== 'true') {
|
||||
|
|
@ -965,148 +813,6 @@ export const experimental_addGithubRepositoryByUrl = async (repositoryUrl: strin
|
|||
}
|
||||
}));
|
||||
|
||||
export const updateConnectionDisplayName = async (connectionId: number, name: string, domain: string): Promise<{ success: boolean } | ServiceError> => sew(() =>
|
||||
withAuth((userId) =>
|
||||
withOrgMembership(userId, domain, async ({ org }) => {
|
||||
const connection = await getConnection(connectionId, org.id);
|
||||
if (!connection) {
|
||||
return notFound();
|
||||
}
|
||||
|
||||
const existingConnectionWithName = await prisma.connection.findUnique({
|
||||
where: {
|
||||
name_orgId: {
|
||||
orgId: org.id,
|
||||
name,
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (existingConnectionWithName) {
|
||||
return {
|
||||
statusCode: StatusCodes.BAD_REQUEST,
|
||||
errorCode: ErrorCode.CONNECTION_ALREADY_EXISTS,
|
||||
message: "A connection with this name already exists.",
|
||||
} satisfies ServiceError;
|
||||
}
|
||||
|
||||
await prisma.connection.update({
|
||||
where: {
|
||||
id: connectionId,
|
||||
orgId: org.id,
|
||||
},
|
||||
data: {
|
||||
name,
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
}
|
||||
}, OrgRole.OWNER)
|
||||
));
|
||||
|
||||
export const updateConnectionConfigAndScheduleSync = async (connectionId: number, config: string, domain: string): Promise<{ success: boolean } | ServiceError> => sew(() =>
|
||||
withAuth((userId) =>
|
||||
withOrgMembership(userId, domain, async ({ org }) => {
|
||||
const connection = await getConnection(connectionId, org.id);
|
||||
if (!connection) {
|
||||
return notFound();
|
||||
}
|
||||
|
||||
const parsedConfig = parseConnectionConfig(config);
|
||||
if (isServiceError(parsedConfig)) {
|
||||
return parsedConfig;
|
||||
}
|
||||
|
||||
if (connection.syncStatus === "SYNC_NEEDED" ||
|
||||
connection.syncStatus === "IN_SYNC_QUEUE" ||
|
||||
connection.syncStatus === "SYNCING") {
|
||||
return {
|
||||
statusCode: StatusCodes.BAD_REQUEST,
|
||||
errorCode: ErrorCode.CONNECTION_SYNC_ALREADY_SCHEDULED,
|
||||
message: "Connection is already syncing. Please wait for the sync to complete before updating the connection.",
|
||||
} satisfies ServiceError;
|
||||
}
|
||||
|
||||
await prisma.connection.update({
|
||||
where: {
|
||||
id: connectionId,
|
||||
orgId: org.id,
|
||||
},
|
||||
data: {
|
||||
config: parsedConfig as unknown as Prisma.InputJsonValue,
|
||||
syncStatus: "SYNC_NEEDED",
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
}
|
||||
}, OrgRole.OWNER)
|
||||
));
|
||||
|
||||
export const flagConnectionForSync = async (connectionId: number, domain: string): Promise<{ success: boolean } | ServiceError> => sew(() =>
|
||||
withAuth((userId) =>
|
||||
withOrgMembership(userId, domain, async ({ org }) => {
|
||||
const connection = await getConnection(connectionId, org.id);
|
||||
if (!connection || connection.orgId !== org.id) {
|
||||
return notFound();
|
||||
}
|
||||
|
||||
await prisma.connection.update({
|
||||
where: {
|
||||
id: connection.id,
|
||||
},
|
||||
data: {
|
||||
syncStatus: "SYNC_NEEDED",
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
}
|
||||
})
|
||||
));
|
||||
|
||||
export const flagReposForIndex = async (repoIds: number[]) => sew(() =>
|
||||
withAuthV2(async ({ org, prisma }) => {
|
||||
await prisma.repo.updateMany({
|
||||
where: {
|
||||
id: { in: repoIds },
|
||||
orgId: org.id,
|
||||
},
|
||||
data: {
|
||||
repoIndexingStatus: RepoIndexingStatus.NEW,
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
}
|
||||
}));
|
||||
|
||||
export const deleteConnection = async (connectionId: number, domain: string): Promise<{ success: boolean } | ServiceError> => sew(() =>
|
||||
withAuth((userId) =>
|
||||
withOrgMembership(userId, domain, async ({ org }) => {
|
||||
const connection = await getConnection(connectionId, org.id);
|
||||
if (!connection) {
|
||||
return notFound();
|
||||
}
|
||||
|
||||
await prisma.connection.delete({
|
||||
where: {
|
||||
id: connectionId,
|
||||
orgId: org.id,
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
}
|
||||
}, OrgRole.OWNER)
|
||||
));
|
||||
|
||||
export const getCurrentUserRole = async (domain: string): Promise<OrgRole | ServiceError> => sew(() =>
|
||||
withAuth((userId) =>
|
||||
withOrgMembership(userId, domain, async ({ userRole }) => {
|
||||
|
|
@ -1319,13 +1025,6 @@ export const cancelInvite = async (inviteId: string, domain: string): Promise<{
|
|||
}, /* minRequiredRole = */ OrgRole.OWNER)
|
||||
));
|
||||
|
||||
export const getOrgInviteId = async (domain: string) => sew(() =>
|
||||
withAuth(async (userId) =>
|
||||
withOrgMembership(userId, domain, async ({ org }) => {
|
||||
return org.inviteLinkId;
|
||||
}, /* minRequiredRole = */ OrgRole.OWNER)
|
||||
));
|
||||
|
||||
export const getMe = async () => sew(() =>
|
||||
withAuth(async (userId) => {
|
||||
const user = await prisma.user.findUnique({
|
||||
|
|
@ -1662,27 +1361,6 @@ export const leaveOrg = async (domain: string): Promise<{ success: boolean } | S
|
|||
})
|
||||
));
|
||||
|
||||
|
||||
export const getOrgMembership = async (domain: string) => sew(() =>
|
||||
withAuth(async (userId) =>
|
||||
withOrgMembership(userId, domain, async ({ org }) => {
|
||||
const membership = await prisma.userToOrg.findUnique({
|
||||
where: {
|
||||
orgId_userId: {
|
||||
orgId: org.id,
|
||||
userId: userId,
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!membership) {
|
||||
return notFound();
|
||||
}
|
||||
|
||||
return membership;
|
||||
})
|
||||
));
|
||||
|
||||
export const getOrgMembers = async (domain: string) => sew(() =>
|
||||
withAuth(async (userId) =>
|
||||
withOrgMembership(userId, domain, async ({ org }) => {
|
||||
|
|
@ -1878,20 +1556,6 @@ export const setMemberApprovalRequired = async (domain: string, required: boolea
|
|||
)
|
||||
);
|
||||
|
||||
export const getInviteLinkEnabled = async (domain: string): Promise<boolean | ServiceError> => sew(async () => {
|
||||
const org = await prisma.org.findUnique({
|
||||
where: {
|
||||
domain,
|
||||
},
|
||||
});
|
||||
|
||||
if (!org) {
|
||||
return orgNotFound();
|
||||
}
|
||||
|
||||
return org.inviteLinkEnabled;
|
||||
});
|
||||
|
||||
export const setInviteLinkEnabled = async (domain: string, enabled: boolean): Promise<{ success: boolean } | ServiceError> => sew(async () =>
|
||||
withAuth(async (userId) =>
|
||||
withOrgMembership(userId, domain, async ({ org }) => {
|
||||
|
|
@ -2023,10 +1687,6 @@ export const rejectAccountRequest = async (requestId: string, domain: string) =>
|
|||
}, /* minRequiredRole = */ OrgRole.OWNER)
|
||||
));
|
||||
|
||||
export const dismissMobileUnsupportedSplashScreen = async () => sew(async () => {
|
||||
await (await cookies()).set(MOBILE_UNSUPPORTED_SPLASH_SCREEN_DISMISSED_COOKIE_NAME, 'true');
|
||||
return true;
|
||||
});
|
||||
|
||||
export const getSearchContexts = async (domain: string) => sew(() =>
|
||||
withAuth((userId) =>
|
||||
|
|
@ -2179,126 +1839,17 @@ export const setAnonymousAccessStatus = async (domain: string, enabled: boolean)
|
|||
});
|
||||
});
|
||||
|
||||
export async function setSearchModeCookie(searchMode: "precise" | "agentic") {
|
||||
const cookieStore = await cookies();
|
||||
cookieStore.set(SEARCH_MODE_COOKIE_NAME, searchMode, {
|
||||
httpOnly: false, // Allow client-side access
|
||||
});
|
||||
}
|
||||
|
||||
export async function setAgenticSearchTutorialDismissedCookie(dismissed: boolean) {
|
||||
export const setAgenticSearchTutorialDismissedCookie = async (dismissed: boolean) => sew(async () => {
|
||||
const cookieStore = await cookies();
|
||||
cookieStore.set(AGENTIC_SEARCH_TUTORIAL_DISMISSED_COOKIE_NAME, dismissed ? "true" : "false", {
|
||||
httpOnly: false, // Allow client-side access
|
||||
maxAge: 365 * 24 * 60 * 60, // 1 year in seconds
|
||||
});
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
////// Helpers ///////
|
||||
|
||||
const parseConnectionConfig = (config: string) => {
|
||||
let parsedConfig: ConnectionConfig;
|
||||
try {
|
||||
parsedConfig = JSON.parse(config);
|
||||
} catch (_e) {
|
||||
return {
|
||||
statusCode: StatusCodes.BAD_REQUEST,
|
||||
errorCode: ErrorCode.INVALID_REQUEST_BODY,
|
||||
message: "config must be a valid JSON object."
|
||||
} satisfies ServiceError;
|
||||
}
|
||||
|
||||
const connectionType = parsedConfig.type;
|
||||
const schema = (() => {
|
||||
switch (connectionType) {
|
||||
case "github":
|
||||
return githubSchema;
|
||||
case "gitlab":
|
||||
return gitlabSchema;
|
||||
case 'gitea':
|
||||
return giteaSchema;
|
||||
case 'gerrit':
|
||||
return gerritSchema;
|
||||
case 'bitbucket':
|
||||
return bitbucketSchema;
|
||||
case 'azuredevops':
|
||||
return azuredevopsSchema;
|
||||
case 'git':
|
||||
return genericGitHostSchema;
|
||||
}
|
||||
})();
|
||||
|
||||
if (!schema) {
|
||||
return {
|
||||
statusCode: StatusCodes.BAD_REQUEST,
|
||||
errorCode: ErrorCode.INVALID_REQUEST_BODY,
|
||||
message: "invalid connection type",
|
||||
} satisfies ServiceError;
|
||||
}
|
||||
|
||||
const isValidConfig = ajv.validate(schema, parsedConfig);
|
||||
if (!isValidConfig) {
|
||||
return {
|
||||
statusCode: StatusCodes.BAD_REQUEST,
|
||||
errorCode: ErrorCode.INVALID_REQUEST_BODY,
|
||||
message: `config schema validation failed with errors: ${ajv.errorsText(ajv.errors)}`,
|
||||
} satisfies ServiceError;
|
||||
}
|
||||
|
||||
if ('token' in parsedConfig && parsedConfig.token && 'env' in parsedConfig.token) {
|
||||
return {
|
||||
statusCode: StatusCodes.BAD_REQUEST,
|
||||
errorCode: ErrorCode.INVALID_REQUEST_BODY,
|
||||
message: "Environment variables are not supported for connections created in the web UI. Please use a secret instead.",
|
||||
} satisfies ServiceError;
|
||||
}
|
||||
|
||||
const { numRepos, hasToken } = (() => {
|
||||
switch (connectionType) {
|
||||
case "gitea":
|
||||
case "github":
|
||||
case "bitbucket":
|
||||
case "azuredevops": {
|
||||
return {
|
||||
numRepos: parsedConfig.repos?.length,
|
||||
hasToken: !!parsedConfig.token,
|
||||
}
|
||||
}
|
||||
case "gitlab": {
|
||||
return {
|
||||
numRepos: parsedConfig.projects?.length,
|
||||
hasToken: !!parsedConfig.token,
|
||||
}
|
||||
}
|
||||
case "gerrit": {
|
||||
return {
|
||||
numRepos: parsedConfig.projects?.length,
|
||||
hasToken: true, // gerrit doesn't use a token atm
|
||||
}
|
||||
}
|
||||
case "git": {
|
||||
return {
|
||||
numRepos: 1,
|
||||
hasToken: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
if (!hasToken && numRepos && numRepos > env.CONFIG_MAX_REPOS_NO_TOKEN) {
|
||||
return {
|
||||
statusCode: StatusCodes.BAD_REQUEST,
|
||||
errorCode: ErrorCode.INVALID_REQUEST_BODY,
|
||||
message: `You must provide a token to sync more than ${env.CONFIG_MAX_REPOS_NO_TOKEN} repositories.`,
|
||||
} satisfies ServiceError;
|
||||
}
|
||||
|
||||
return parsedConfig;
|
||||
}
|
||||
|
||||
export const encryptValue = async (value: string) => {
|
||||
return encrypt(value);
|
||||
}
|
||||
|
||||
export const decryptValue = async (iv: string, encryptedValue: string) => {
|
||||
return decrypt(iv, encryptedValue);
|
||||
}
|
||||
export const dismissMobileUnsupportedSplashScreen = async () => sew(async () => {
|
||||
const cookieStore = await cookies();
|
||||
cookieStore.set(MOBILE_UNSUPPORTED_SPLASH_SCREEN_DISMISSED_COOKIE_NAME, 'true');
|
||||
return true;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -32,13 +32,13 @@ export const NavigationItems = ({
|
|||
<NavigationMenuList className="gap-2">
|
||||
<NavigationMenuItem className="relative">
|
||||
<NavigationMenuLink
|
||||
href={`/${domain}`}
|
||||
href={`/${domain}/search`}
|
||||
className={cn(navigationMenuTriggerStyle(), "gap-2")}
|
||||
>
|
||||
<SearchIcon className="w-4 h-4 mr-1" />
|
||||
Search
|
||||
</NavigationMenuLink>
|
||||
{isActive(`/${domain}`) && <ActiveIndicator />}
|
||||
{((isActive(`/${domain}`) || isActive(`/${domain}/search`)) && <ActiveIndicator />)}
|
||||
</NavigationMenuItem>
|
||||
<NavigationMenuItem className="relative">
|
||||
<NavigationMenuLink
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ export const TEAM_FEATURES = [
|
|||
]
|
||||
|
||||
export const MOBILE_UNSUPPORTED_SPLASH_SCREEN_DISMISSED_COOKIE_NAME = 'sb.mobile-unsupported-splash-screen-dismissed';
|
||||
export const SEARCH_MODE_COOKIE_NAME = 'sb.search-mode';
|
||||
export const AGENTIC_SEARCH_TUTORIAL_DISMISSED_COOKIE_NAME = 'sb.agentic-search-tutorial-dismissed';
|
||||
|
||||
// NOTE: changing SOURCEBOT_GUEST_USER_ID may break backwards compatibility since this value is used
|
||||
|
|
|
|||
Loading…
Reference in a new issue