From b31832b8e3439598fff277d91444237b0e8a82ba Mon Sep 17 00:00:00 2001 From: Dobrunia Kostrigin <48620984+Dobrunia@users.noreply.github.com> Date: Sun, 8 Feb 2026 01:53:00 +0300 Subject: [PATCH 1/7] chore: Replace BreadcrumbLevel and BreadcrumbType enums with String to accept arbitrary SDK values --- package.json | 2 +- src/typeDefs/event.ts | 35 ++++++++--------------------------- 2 files changed, 9 insertions(+), 28 deletions(-) diff --git a/package.json b/package.json index 4572039e..76aa78a7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hawk.api", - "version": "1.4.3", + "version": "1.4.4", "main": "index.ts", "license": "BUSL-1.1", "scripts": { diff --git a/src/typeDefs/event.ts b/src/typeDefs/event.ts index c2ac3a2d..c200de96 100644 --- a/src/typeDefs/event.ts +++ b/src/typeDefs/event.ts @@ -116,29 +116,6 @@ type EventUser { photo: String } -""" -Breadcrumb severity level -""" -enum BreadcrumbLevel { - fatal - error - warning - info - debug -} - -""" -Breadcrumb type - controls categorization and UI appearance -""" -enum BreadcrumbType { - default - request - ui - navigation - logic - error -} - """ Single breadcrumb entry - represents an event that occurred before the error """ @@ -149,9 +126,11 @@ type Breadcrumb { timestamp: Float! """ - Type of breadcrumb - controls UI categorization + Type of breadcrumb - controls UI categorization. + Common values: default, request, ui, navigation, logic, error. + Accepts any string since SDK users may send custom types. """ - type: BreadcrumbType + type: String """ Category of the event - more specific than type @@ -164,9 +143,11 @@ type Breadcrumb { message: String """ - Severity level of the breadcrumb + Severity level of the breadcrumb. + Common values: fatal, error, warning, info, debug. + Accepts any string since SDK users may send custom levels. """ - level: BreadcrumbLevel + level: String """ Arbitrary key-value data associated with the breadcrumb From 6fbc666a9d13b6f31f5e77e33261d5883b6f2a5c Mon Sep 17 00:00:00 2001 From: Dobrunia Kostrigin <48620984+Dobrunia@users.noreply.github.com> Date: Tue, 10 Feb 2026 14:10:55 +0300 Subject: [PATCH 2/7] fix: tests --- src/integrations/github/__mocks__/service.ts | 5 +++++ src/integrations/github/routes.ts | 8 ++++---- src/resolvers/project.js | 2 +- test/integrations/github-routes.test.ts | 6 +++--- test/resolvers/project.test.ts | 9 +++++++++ 5 files changed, 22 insertions(+), 8 deletions(-) create mode 100644 src/integrations/github/__mocks__/service.ts diff --git a/src/integrations/github/__mocks__/service.ts b/src/integrations/github/__mocks__/service.ts new file mode 100644 index 00000000..04ff8529 --- /dev/null +++ b/src/integrations/github/__mocks__/service.ts @@ -0,0 +1,5 @@ +export const deleteInstallationMock = jest.fn().mockResolvedValue(undefined); + +export const GitHubService = jest.fn().mockImplementation(() => ({ + deleteInstallation: deleteInstallationMock, +})); diff --git a/src/integrations/github/routes.ts b/src/integrations/github/routes.ts index f000ca24..8144ec34 100644 --- a/src/integrations/github/routes.ts +++ b/src/integrations/github/routes.ts @@ -522,15 +522,15 @@ export function createGitHubRouter(factories: ContextFactories): express.Router * just log query parameters and respond with 200 without signature validation. */ if (req.method !== 'POST') { + // eslint-disable-next-line @typescript-eslint/camelcase, camelcase const { code, installation_id, setup_action, state, ...restQuery } = req.query as Record; + // eslint-disable-next-line @typescript-eslint/camelcase, camelcase if (code || installation_id || state || setup_action) { - // eslint-disable-next-line @typescript-eslint/camelcase, camelcase log('info', `${WEBHOOK_LOG_PREFIX}Received non-POST request on /webhook with OAuth-like params`, { - // eslint-disable-next-line @typescript-eslint/camelcase, camelcase code, - installation_id, - setup_action, + installation_id, // eslint-disable-line @typescript-eslint/camelcase, camelcase + setup_action, // eslint-disable-line @typescript-eslint/camelcase, camelcase state, query: restQuery, }); diff --git a/src/resolvers/project.js b/src/resolvers/project.js index aa16734e..c1a2767c 100644 --- a/src/resolvers/project.js +++ b/src/resolvers/project.js @@ -421,7 +421,7 @@ module.exports = { */ const taskManager = project.taskManager; - if (taskManager && taskManager.type === 'github' && taskManager.config?.installationId) { + if (taskManager && taskManager.type === 'github' && taskManager.config && taskManager.config.installationId) { const githubService = new GitHubService(); await githubService.deleteInstallation(taskManager.config.installationId); diff --git a/test/integrations/github-routes.test.ts b/test/integrations/github-routes.test.ts index 81094183..03eacc94 100644 --- a/test/integrations/github-routes.test.ts +++ b/test/integrations/github-routes.test.ts @@ -480,7 +480,7 @@ describe('GitHub Routes - /integration/github/connect', () => { expect(response.status).toBe(302); expect(response.body).toContain('http://localhost:8080/'); - expect(response.body).toContain('error=Missing+or+invalid+OAuth+code'); + expect(response.body).toContain('apiError=Missing+or+invalid+OAuth+code'); }); it('should redirect with error when state is missing', async () => { @@ -501,7 +501,7 @@ describe('GitHub Routes - /integration/github/connect', () => { expect(response.status).toBe(302); expect(response.body).toContain('http://localhost:8080/'); - expect(response.body).toContain('error=Missing+or+invalid+state'); + expect(response.body).toContain('apiError=Missing+or+invalid+state'); }); it('should redirect with error when state is invalid or expired', async () => { @@ -525,7 +525,7 @@ describe('GitHub Routes - /integration/github/connect', () => { expect(response.status).toBe(302); expect(response.body).toContain('http://localhost:8080/'); - expect(response.body).toContain('error=Invalid+or+expired+state'); + expect(response.body).toContain('apiError=Invalid+or+expired+state'); expect(mockGetState).toHaveBeenCalledWith(state); }); diff --git a/test/resolvers/project.test.ts b/test/resolvers/project.test.ts index bda54a40..9e763bce 100644 --- a/test/resolvers/project.test.ts +++ b/test/resolvers/project.test.ts @@ -3,6 +3,11 @@ import { ObjectId } from 'mongodb'; import { ProjectDBScheme, ProjectTaskManagerConfig } from '@hawk.so/types'; import { ResolverContextWithUser } from '../../src/types/graphql'; import { ApolloError, UserInputError } from 'apollo-server-express'; + +jest.mock('../../src/integrations/github/service'); +// eslint-disable-next-line @typescript-eslint/no-var-requires +const { deleteInstallationMock, GitHubService } = require('../../src/integrations/github/service'); + // @ts-expect-error - CommonJS module, TypeScript can't infer types properly import projectResolverModule from '../../src/resolvers/project'; @@ -141,6 +146,8 @@ describe('Project Resolver - Task Manager Mutations', () => { )) as { taskManager: ProjectTaskManagerConfig | null }; expect(context.factories.projectsFactory.findById).toHaveBeenCalledWith(mockProject._id.toString()); + expect(GitHubService).toHaveBeenCalledTimes(1); + expect(deleteInstallationMock).toHaveBeenCalledWith('123456'); expect(mockProject.updateProject).toHaveBeenCalledWith({ taskManager: null, }); @@ -217,6 +224,8 @@ describe('Project Resolver - Task Manager Mutations', () => { context )) as { taskManager: ProjectTaskManagerConfig | null }; + expect(GitHubService).not.toHaveBeenCalled(); + expect(deleteInstallationMock).not.toHaveBeenCalled(); expect(mockProject.updateProject).toHaveBeenCalledWith({ taskManager: null, }); From c56ad1b5fca791d025b4443521c8bced08f265b1 Mon Sep 17 00:00:00 2001 From: Dobrunia Kostrigin <48620984+Dobrunia@users.noreply.github.com> Date: Tue, 10 Feb 2026 14:14:02 +0300 Subject: [PATCH 3/7] refactor: remove GitHub service mock --- .../__mocks__/service.ts => test/__mocks__/github-service.ts | 0 test/resolvers/project.test.ts | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/integrations/github/__mocks__/service.ts => test/__mocks__/github-service.ts (100%) diff --git a/src/integrations/github/__mocks__/service.ts b/test/__mocks__/github-service.ts similarity index 100% rename from src/integrations/github/__mocks__/service.ts rename to test/__mocks__/github-service.ts diff --git a/test/resolvers/project.test.ts b/test/resolvers/project.test.ts index 9e763bce..4a46fd0d 100644 --- a/test/resolvers/project.test.ts +++ b/test/resolvers/project.test.ts @@ -4,9 +4,9 @@ import { ProjectDBScheme, ProjectTaskManagerConfig } from '@hawk.so/types'; import { ResolverContextWithUser } from '../../src/types/graphql'; import { ApolloError, UserInputError } from 'apollo-server-express'; -jest.mock('../../src/integrations/github/service'); +jest.mock('../../src/integrations/github/service', () => require('../__mocks__/github-service')); // eslint-disable-next-line @typescript-eslint/no-var-requires -const { deleteInstallationMock, GitHubService } = require('../../src/integrations/github/service'); +const { deleteInstallationMock, GitHubService } = require('../__mocks__/github-service'); // @ts-expect-error - CommonJS module, TypeScript can't infer types properly import projectResolverModule from '../../src/resolvers/project'; From be71f5d70323ed9cb6f50c1cd4abbea62cd97cf0 Mon Sep 17 00:00:00 2001 From: Dobrunia Kostrigin <48620984+Dobrunia@users.noreply.github.com> Date: Tue, 10 Feb 2026 14:21:44 +0300 Subject: [PATCH 4/7] fix: import --- test/resolvers/project.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/resolvers/project.test.ts b/test/resolvers/project.test.ts index 4a46fd0d..8f50acbc 100644 --- a/test/resolvers/project.test.ts +++ b/test/resolvers/project.test.ts @@ -6,7 +6,7 @@ import { ApolloError, UserInputError } from 'apollo-server-express'; jest.mock('../../src/integrations/github/service', () => require('../__mocks__/github-service')); // eslint-disable-next-line @typescript-eslint/no-var-requires -const { deleteInstallationMock, GitHubService } = require('../__mocks__/github-service'); +import { deleteInstallationMock, GitHubService } from '../__mocks__/github-service'; // @ts-expect-error - CommonJS module, TypeScript can't infer types properly import projectResolverModule from '../../src/resolvers/project'; From 97a6eb510e056c1df4c0738d860dbed668c917d3 Mon Sep 17 00:00:00 2001 From: Dobrunia Kostrigin <48620984+Dobrunia@users.noreply.github.com> Date: Tue, 10 Feb 2026 15:18:32 +0300 Subject: [PATCH 5/7] chore: remove-amplitude --- .env.sample | 2 -- package.json | 1 - src/models/usersFactory.ts | 10 +--------- src/models/workspacesFactory.ts | 9 --------- src/utils/analytics/amplitude.ts | 27 ------------------------- src/utils/analytics/events.ts | 17 ---------------- src/utils/analytics/index.ts | 2 -- yarn.lock | 34 +------------------------------- 8 files changed, 2 insertions(+), 100 deletions(-) delete mode 100644 src/utils/analytics/amplitude.ts delete mode 100644 src/utils/analytics/events.ts delete mode 100644 src/utils/analytics/index.ts diff --git a/.env.sample b/.env.sample index 87180a6a..bb7e7e22 100644 --- a/.env.sample +++ b/.env.sample @@ -77,8 +77,6 @@ CLOUDPAYMENTS_SECRET= # INN of legal entity for CloudKassir LEGAL_ENTITY_INN= -# Token for Amplitude analytics -AMPLITUDE_TOKEN= # AWS S3 Bucket Configuration AWS_S3_ACCESS_KEY_ID= diff --git a/package.json b/package.json index 76aa78a7..46e1dc90 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,6 @@ }, "dependencies": { "@ai-sdk/openai": "^2.0.64", - "@amplitude/node": "^1.10.0", "@graphql-tools/merge": "^8.3.1", "@graphql-tools/schema": "^8.5.1", "@graphql-tools/utils": "^8.9.0", diff --git a/src/models/usersFactory.ts b/src/models/usersFactory.ts index ba3ee1de..29eb7b69 100644 --- a/src/models/usersFactory.ts +++ b/src/models/usersFactory.ts @@ -3,7 +3,7 @@ import UserModel from './user'; import { Collection, Db, OptionalId } from 'mongodb'; import DataLoaders from '../dataLoaders'; import { UserDBScheme } from '@hawk.so/types'; -import { Analytics, AnalyticsEventTypes } from '../utils/analytics'; + /** * Users factory to work with User Model @@ -91,14 +91,6 @@ export default class UsersFactory extends AbstractModelFactory - */ - logEvent: (event: AnalyticsEvent): Promise => { - return amplitude.logEvent(event); - }, -}; diff --git a/src/utils/analytics/events.ts b/src/utils/analytics/events.ts deleted file mode 100644 index b5342660..00000000 --- a/src/utils/analytics/events.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Event } from '@amplitude/node'; - -/** - * Define available metrics - */ -export enum AnalyticsEventTypes { - NEW_USER_REGISTERED = 'new user registered', - - WORKSPACE_CREATED = 'workspace created', - - PROJECT_CREATED = 'project created', -} - -/** - * Define analytics event type - */ -export type AnalyticsEvent = Omit & { 'event_type': AnalyticsEventTypes }; diff --git a/src/utils/analytics/index.ts b/src/utils/analytics/index.ts deleted file mode 100644 index 40d26b1a..00000000 --- a/src/utils/analytics/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { Analytics } from './amplitude'; -export { AnalyticsEventTypes } from './events'; diff --git a/yarn.lock b/yarn.lock index 2c63c92b..be966091 100644 --- a/yarn.lock +++ b/yarn.lock @@ -35,38 +35,6 @@ dependencies: json-schema "^0.4.0" -"@amplitude/identify@^1.10.0": - version "1.10.0" - resolved "https://registry.yarnpkg.com/@amplitude/identify/-/identify-1.10.0.tgz#d62b8b6785c29350c368810475a6fc7b04985210" - integrity sha512-BshMDcZX9qO4mgGBR45HmiHxfcPCDY/eBOE/MTUZBW+y9+N61aKmNY3YJsAUfRPzieDiyfqs8rNm7quVkaNzJQ== - dependencies: - "@amplitude/types" "^1.10.0" - "@amplitude/utils" "^1.10.0" - tslib "^1.9.3" - -"@amplitude/node@^1.10.0": - version "1.10.0" - resolved "https://registry.yarnpkg.com/@amplitude/node/-/node-1.10.0.tgz#33f84ddf82b31471fce53e6fa60b688d4bc62ee4" - integrity sha512-Jh8w1UpxhonWe0kCALVvqiBE3vo5NYmbNZbZrrI9Lfa/1HbGboZlGdg0I7/WtihbZvEjpfcfTOf8OkmtZh6vsQ== - dependencies: - "@amplitude/identify" "^1.10.0" - "@amplitude/types" "^1.10.0" - "@amplitude/utils" "^1.10.0" - tslib "^1.9.3" - -"@amplitude/types@^1.10.0": - version "1.10.0" - resolved "https://registry.yarnpkg.com/@amplitude/types/-/types-1.10.0.tgz#dfaf7cc25f533a1e2b0ef0ad675371b396733c0f" - integrity sha512-xN0gnhutztv6kqHaZ2bre18anQV5GDmMXOeipTvI670g2VjNbPfOzMwu1LN4p1NadYq+GqYI223UcZrXR+R4Pw== - -"@amplitude/utils@^1.10.0": - version "1.10.0" - resolved "https://registry.yarnpkg.com/@amplitude/utils/-/utils-1.10.0.tgz#138b0ba4e5755540a9e4abf426b7a25d045418a9" - integrity sha512-/R8j8IzFH0GYfA6ehQDm5IEzt71gIeMdiYYFIzZp6grERQlgJcwNJMAiza0o2JwwTDIruzqdB3c/vLVjuakp+w== - dependencies: - "@amplitude/types" "^1.10.0" - tslib "^1.9.3" - "@apollo/protobufjs@1.2.4": version "1.2.4" resolved "https://registry.yarnpkg.com/@apollo/protobufjs/-/protobufjs-1.2.4.tgz#d913e7627210ec5efd758ceeb751c776c68ba133" @@ -6662,7 +6630,7 @@ tsconfig@^7.0.0: strip-bom "^3.0.0" strip-json-comments "^2.0.0" -tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: +tslib@^1.8.1, tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== From 4be9d840b64e8be27f6ef0beb5d38d5eec398bf4 Mon Sep 17 00:00:00 2001 From: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:24:39 +0000 Subject: [PATCH 6/7] Bump version up to 1.4.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 46e1dc90..4e0ee4ae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hawk.api", - "version": "1.4.4", + "version": "1.4.5", "main": "index.ts", "license": "BUSL-1.1", "scripts": { From fbb52aa7476ff89f5350d79e2330ed44539ecb4a Mon Sep 17 00:00:00 2001 From: Dobrunia Kostrigin <48620984+Dobrunia@users.noreply.github.com> Date: Tue, 10 Feb 2026 16:06:42 +0300 Subject: [PATCH 7/7] fix: lint --- src/models/usersFactory.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/models/usersFactory.ts b/src/models/usersFactory.ts index 29eb7b69..8e1869f8 100644 --- a/src/models/usersFactory.ts +++ b/src/models/usersFactory.ts @@ -4,7 +4,6 @@ import { Collection, Db, OptionalId } from 'mongodb'; import DataLoaders from '../dataLoaders'; import { UserDBScheme } from '@hawk.so/types'; - /** * Users factory to work with User Model */