From 64e41370bebbb08a5a022e267a207c08754b46d1 Mon Sep 17 00:00:00 2001 From: Curry Yang <1019yanglu@gmail.com> Date: Tue, 14 Oct 2025 17:24:54 +0800 Subject: [PATCH] feat: report user local git project count --- ...ganizationId.project.$projectId.delete.tsx | 3 ++ ...ganizationId.project.$projectId.update.tsx | 7 ++++ ...ganization.$organizationId.project.new.tsx | 34 ++++++++++++++++++- 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.delete.tsx b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.delete.tsx index c3519bf0a8..4a5432d579 100644 --- a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.delete.tsx +++ b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.delete.tsx @@ -3,6 +3,7 @@ import { href, redirect } from 'react-router'; import { database } from '~/common/database'; import { projectLock } from '~/common/project'; import * as models from '~/models'; +import { reportGitProjectCount } from '~/routes/organization.$organizationId.project.new'; import { insomniaFetch } from '~/ui/insomniaFetch'; import { invariant } from '~/utils/invariant'; import { createFetcherSubmitHook, getInitialRouteForOrganization } from '~/utils/router'; @@ -53,6 +54,8 @@ export async function clientAction({ params }: Route.ClientActionArgs) { await database.flushChanges(bufferId); + project.gitRepositoryId && reportGitProjectCount(organizationId, sessionId); + // When redirect to `/organizations/:organizationId`, it sometimes doesn't reload the index loader, so manually redirect to the initial route for the organization const initialOrganizationRoute = await getInitialRouteForOrganization({ organizationId }); return redirect(initialOrganizationRoute); diff --git a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.update.tsx b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.update.tsx index fe29bfc143..5702e521d3 100644 --- a/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.update.tsx +++ b/packages/insomnia/src/routes/organization.$organizationId.project.$projectId.update.tsx @@ -7,6 +7,7 @@ import type { OauthProviderName } from '~/models/git-credentials'; import type { GitCredentials } from '~/models/git-repository'; import { EMPTY_GIT_PROJECT_ID } from '~/models/project'; import type { WorkspaceMeta } from '~/models/workspace-meta'; +import { reportGitProjectCount } from '~/routes/organization.$organizationId.project.new'; import { SegmentEvent } from '~/ui/analytics'; import { insomniaFetch } from '~/ui/insomniaFetch'; import { invariant } from '~/utils/invariant'; @@ -179,6 +180,8 @@ export async function clientAction({ request, params }: Route.ClientActionArgs) } await models.project.update(project, { name, remoteId: newCloudProject.id, gitRepositoryId: null }); + + project.gitRepositoryId && reportGitProjectCount(organizationId, sessionId); return { success: true, }; @@ -278,6 +281,8 @@ export async function clientAction({ request, params }: Route.ClientActionArgs) } } + reportGitProjectCount(organizationId, sessionId); + return { success: true, }; @@ -290,6 +295,8 @@ export async function clientAction({ request, params }: Route.ClientActionArgs) gitRepository && (await models.gitRepository.remove(gitRepository)); await models.project.update(project, { name, gitRepositoryId: null }); + reportGitProjectCount(organizationId, sessionId); + return { success: true, }; diff --git a/packages/insomnia/src/routes/organization.$organizationId.project.new.tsx b/packages/insomnia/src/routes/organization.$organizationId.project.new.tsx index b9f97773f0..99bf0a7e4c 100644 --- a/packages/insomnia/src/routes/organization.$organizationId.project.new.tsx +++ b/packages/insomnia/src/routes/organization.$organizationId.project.new.tsx @@ -1,9 +1,11 @@ import { href, redirect } from 'react-router'; +import { database } from '~/common/database'; +import { isNotNullOrUndefined } from '~/common/misc'; import { projectLock } from '~/common/project'; import * as models from '~/models'; import type { GitCredentials, OauthProviderName } from '~/models/git-repository'; -import { EMPTY_GIT_PROJECT_ID } from '~/models/project'; +import { EMPTY_GIT_PROJECT_ID, type Project } from '~/models/project'; import { SegmentEvent } from '~/ui/analytics'; import { insomniaFetch } from '~/ui/insomniaFetch'; import { invariant } from '~/utils/invariant'; @@ -29,6 +31,34 @@ export interface CreateProjectData { connectRepositoryLater?: boolean; } +export const reportGitProjectCount = async (organizationId: string, sessionId: string, maxRetries = 3) => { + const projects = await database.find(models.project.type, { + parentId: organizationId, + }); + const gitRepositoryIds = projects.map(p => p.gitRepositoryId).filter(isNotNullOrUndefined); + const gitProjectsCount = gitRepositoryIds.length; + for (let attempt = 1; attempt <= maxRetries; attempt++) { + try { + await insomniaFetch({ + method: 'PATCH', + path: `/v1/organizations/${organizationId}/git-projects`, + sessionId, + onlyResolveOnSuccess: true, + data: { + count: gitProjectsCount, + }, + }); + return; + } catch (err) { + if (attempt < maxRetries) { + await new Promise(resolve => setTimeout(resolve, attempt * 1000)); + } + } + } + + console.warn('Report git project count failed'); +}; + export const createProject = async (organizationId: string, newProjectData: CreateProjectData) => { const createProjectImpl = async (organizationId: string, newProjectData: CreateProjectData) => { const user = await models.userSession.getOrCreate(); @@ -51,6 +81,7 @@ export const createProject = async (organizationId: string, newProjectData: Crea parentId: organizationId, gitRepositoryId: EMPTY_GIT_PROJECT_ID, }); + reportGitProjectCount(organizationId, sessionId); return project._id; } @@ -91,6 +122,7 @@ export const createProject = async (organizationId: string, newProjectData: Crea if (errors) { throw new Error(errors.join(', ')); } + reportGitProjectCount(organizationId, sessionId); return projectId; }