Skip to content

Commit

Permalink
Merge branch 'next' into polish_copy_button
Browse files Browse the repository at this point in the history
  • Loading branch information
SokratisVidros authored Feb 25, 2025
2 parents 17a6028 + 139d7dc commit 8d27d3c
Show file tree
Hide file tree
Showing 61 changed files with 1,535 additions and 946 deletions.
1 change: 1 addition & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"EQAs",
"analagous",
"addrs",
"Tiering",
"subscriberpayloaddto",
"adresses",
"APIJSON",
Expand Down
9 changes: 1 addition & 8 deletions .idea/runConfigurations/RUN_LOCAL_ENV.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .source
9 changes: 2 additions & 7 deletions apps/api/e2e/setup.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { testServer, TestingQueueService, JobsService } from '@novu/testing';
import { JobsService, TestingQueueService, testServer } from '@novu/testing';
import sinon from 'sinon';
import chai from 'chai';
import mongoose from 'mongoose';
Expand Down Expand Up @@ -67,12 +67,7 @@ afterEach(async function () {
sinon.restore();

try {
await Promise.race([
cleanup(),
timeoutPromise(TIMEOUT).then(() => {
console.warn('Cleanup operation timed out after 5000ms - continuing with tests');
}),
]);
await Promise.race([cleanup(), timeoutPromise(TIMEOUT).then(() => {})]);
} catch (error) {
console.error('Error during cleanup:', error);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
/* eslint-disable global-require */
import sinon from 'sinon';
import { expect } from 'chai';
import { ApiServiceLevelEnum } from '@novu/shared';
// eslint-disable-next-line no-restricted-imports
import { StripeBillingIntervalEnum } from '@novu/ee-billing/src/stripe/types';
import { ApiServiceLevelEnum, StripeBillingIntervalEnum } from '@novu/shared';

const mockCheckoutSessionCompletedEvent = {
type: 'checkout.session.completed',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
/* eslint-disable global-require */
import sinon from 'sinon';
import { expect } from 'chai';
// eslint-disable-next-line no-restricted-imports
import { StripeBillingIntervalEnum } from '@novu/ee-billing/src/stripe/types';
import { ApiServiceLevelEnum } from '@novu/shared';

import { ApiServiceLevelEnum, StripeBillingIntervalEnum } from '@novu/shared';

const checkoutSessionCreateParamsMock = {
mode: 'subscription',
Expand Down
8 changes: 2 additions & 6 deletions apps/api/src/app/billing/e2e/create-subscription.e2e-ee.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
/* eslint-disable global-require */
import sinon from 'sinon';
import { expect } from 'chai';
import { ApiServiceLevelEnum } from '@novu/shared';
import { ApiServiceLevelEnum, StripeBillingIntervalEnum } from '@novu/shared';
// eslint-disable-next-line no-restricted-imports
import {
StripeBillingIntervalEnum,
StripeUsageTypeEnum,
StripeSubscriptionStatusEnum,
} from '@novu/ee-billing/src/stripe/types';
import { StripeSubscriptionStatusEnum, StripeUsageTypeEnum } from '@novu/ee-billing/src/stripe/types';

describe('CreateSubscription #novu-v2', () => {
const eeBilling = require('@novu/ee-billing');
Expand Down
4 changes: 2 additions & 2 deletions apps/api/src/app/billing/e2e/create-usage-records.e2e-ee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
import { Logger } from '@nestjs/common';
import sinon from 'sinon';
import { expect } from 'chai';
import { ApiServiceLevelEnum } from '@novu/shared';
import { ApiServiceLevelEnum, StripeBillingIntervalEnum } from '@novu/shared';
// eslint-disable-next-line no-restricted-imports
import { StripeBillingIntervalEnum, StripeUsageTypeEnum } from '@novu/ee-billing/src/stripe/types';
import { StripeUsageTypeEnum } from '@novu/ee-billing/src/stripe/types';

const mockMonthlyBusinessSubscription = {
id: 'subscription_id',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
/* eslint-disable global-require */
import sinon from 'sinon';
import { expect } from 'chai';
import { ApiServiceLevelEnum } from '@novu/shared';
// eslint-disable-next-line no-restricted-imports
import { StripeBillingIntervalEnum } from '@novu/ee-billing/src/stripe/types';
import { ApiServiceLevelEnum, StripeBillingIntervalEnum } from '@novu/shared';

const mockCustomerSubscriptionCreatedEvent = {
data: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
/* eslint-disable global-require */
import sinon from 'sinon';
import { expect } from 'chai';
import { ApiServiceLevelEnum } from '@novu/shared';
// eslint-disable-next-line no-restricted-imports
import { StripeBillingIntervalEnum } from '@novu/ee-billing/src/stripe/types';
import { ApiServiceLevelEnum, StripeBillingIntervalEnum } from '@novu/shared';

const verifyCustomerMock = {
customer: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import sinon from 'sinon';
import { Test } from '@nestjs/testing';
import { CacheService, MockCacheService } from '@novu/application-generic';
import { ApiServiceLevelEnum, GetSubscriptionDto } from '@novu/shared';
import { GetEventResourceUsage, GetPlatformNotificationUsage, GetSubscription } from '@novu/ee-billing';
import { GetEventResourceUsage, GetSubscription } from '@novu/ee-billing';
import { randomUUID } from 'node:crypto';
import { AppModule } from '../../../app.module';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/* eslint-disable global-require */
import sinon from 'sinon';
import { expect } from 'chai';
import { EnvironmentRepository, NotificationRepository, CommunityOrganizationRepository } from '@novu/dal';
import { CommunityOrganizationRepository, EnvironmentRepository, NotificationRepository } from '@novu/dal';
import { UserSession } from '@novu/testing';
import { ApiServiceLevelEnum, isClerkEnabled } from '@novu/shared';

Expand Down
4 changes: 1 addition & 3 deletions apps/api/src/app/billing/e2e/get-prices.e2e-ee.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
/* eslint-disable global-require */
import sinon from 'sinon';
import { expect } from 'chai';
import { ApiServiceLevelEnum } from '@novu/shared';
// eslint-disable-next-line no-restricted-imports
import { StripeBillingIntervalEnum } from '@novu/ee-billing/src/stripe/types';
import { ApiServiceLevelEnum, StripeBillingIntervalEnum } from '@novu/shared';

describe('GetPrices #novu-v2', () => {
const eeBilling = require('@novu/ee-billing');
Expand Down
10 changes: 5 additions & 5 deletions apps/api/src/app/bridge/bridge.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@ import {
CreateMessageTemplate,
CreateWorkflow,
DeleteMessageTemplate,
DeletePreferencesUseCase,
DeleteWorkflowUseCase,
GetPreferences,
GetWorkflowByIdsUseCase,
ResourceValidatorService,
TierRestrictionsValidateUsecase,
UpdateChange,
UpdateMessageTemplate,
UpdateWorkflow,
UpsertControlValuesUseCase,
UpsertPreferences,
DeletePreferencesUseCase,
TierRestrictionsValidateUsecase,
ResourceValidatorService,
} from '@novu/application-generic';
import { CommunityOrganizationRepository, PreferencesRepository } from '@novu/dal';
import { SharedModule } from '../shared/shared.module';
import { BridgeController } from './bridge.controller';
import { USECASES } from './usecases';
import { BuildVariableSchemaUsecase } from '../workflows-v2/usecases/build-variable-schema';
import { BuildVariableSchemaUsecase } from '../workflows-v2/usecases';
import { ExtractVariables } from '../workflows-v2/usecases/extract-variables/extract-variables.usecase';
import { BuildStepIssuesUsecase } from '../workflows-v2/usecases/build-step-issues/build-step-issues.usecase';

Expand All @@ -41,11 +41,11 @@ const PROVIDERS = [
DeletePreferencesUseCase,
UpsertControlValuesUseCase,
BuildVariableSchemaUsecase,
TierRestrictionsValidateUsecase,
CommunityOrganizationRepository,
ExtractVariables,
BuildStepIssuesUsecase,
ResourceValidatorService,
TierRestrictionsValidateUsecase,
];

@Module({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { RegenerateApiKeys } from './usecases/regenerate-api-keys/regenerate-api
import { UpdateEnvironmentCommand } from './usecases/update-environment/update-environment.command';
import { UpdateEnvironment } from './usecases/update-environment/update-environment.usecase';
import { RolesGuard } from '../auth/framework/roles.guard';

/**
* @deprecated use EnvironmentsControllerV2
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,17 @@ import { expect } from 'chai';

import { EnvironmentRepository } from '@novu/dal';
import { UserSession } from '@novu/testing';
import { NOVU_ENCRYPTION_SUB_MASK } from '@novu/shared';
import { ApiServiceLevelEnum, NOVU_ENCRYPTION_SUB_MASK } from '@novu/shared';

async function createEnv(name: string, session) {
const demoEnvironment = {
name,
color: '#3A7F5C',
};
const { body } = await session.testAgent.post('/v1/environments').send(demoEnvironment);

return { demoEnvironment, body };
}

describe('Create Environment - /environments (POST)', async () => {
let session: UserSession;
Expand All @@ -12,11 +22,13 @@ describe('Create Environment - /environments (POST)', async () => {
await session.initialize({
noEnvironment: true,
});
session.updateOrganizationServiceLevel(ApiServiceLevelEnum.BUSINESS);
});

it('should create environment entity correctly', async () => {
const demoEnvironment = {
name: 'Hello App',
color: '#3A7F5C',
};
const { body } = await session.testAgent.post('/v1/environments').send(demoEnvironment).expect(201);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ export class CreateEnvironment {
_organizationId: command.organizationId,
});

if (environmentCount >= 10) {
throw new BadRequestException('Organization cannot have more than 10 environments');
}
const normalizedName = command.name.trim();

if (!command.system) {
Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/app/environments-v1/usecases/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { GetMxRecord } from '../../inbound-parse/usecases/get-mx-record/get-mx-record.usecase';
import { CreateEnvironment } from './create-environment/create-environment.usecase';
import { DeleteEnvironment } from './delete-environment/delete-environment.usecase';
import { DeleteEnvironment } from './delete-environment';
import { GenerateUniqueApiKey } from './generate-unique-api-key/generate-unique-api-key.usecase';
import { GetApiKeys } from './get-api-keys/get-api-keys.usecase';
import { GetEnvironment } from './get-environment';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { EnvironmentRepository, IntegrationRepository, CommunityOrganizationRepository } from '@novu/dal';
import { CommunityOrganizationRepository, EnvironmentRepository, IntegrationRepository } from '@novu/dal';
import { UserSession } from '@novu/testing';
import { expect } from 'chai';
import {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { CommunityOrganizationRepository, EnvironmentRepository } from '@novu/dal';
import { UserSession } from '@novu/testing';
import { ApiRateLimitCategoryEnum, ApiServiceLevelEnum } from '@novu/shared';
import {
ApiRateLimitCategoryEnum,
ApiRateLimitCategoryToFeatureName,
ApiServiceLevelEnum,
FeatureFlagsKeysEnum,
getFeatureForTierAsNumber,
} from '@novu/shared';
import { expect } from 'chai';
import sinon from 'sinon';
import { Test } from '@nestjs/testing';
import { CacheService, MockCacheService } from '@novu/application-generic';
import { GetApiRateLimitMaximum, GetApiRateLimitMaximumCommand } from './index';
import { SharedModule } from '../../../shared/shared.module';
import { GetApiRateLimitServiceMaximumConfig } from '../get-api-rate-limit-service-maximum-config';
import { RateLimitingModule } from '../../rate-limiting.module';
import { CUSTOM_API_SERVICE_LEVEL } from './get-api-rate-limit-maximum.dto';

Expand All @@ -29,11 +34,9 @@ describe('GetApiRateLimitMaximum', async () => {
let session: UserSession;
let organizationRepository: CommunityOrganizationRepository;
let environmentRepository: EnvironmentRepository;
let getDefaultApiRateLimits: GetApiRateLimitServiceMaximumConfig;

let findOneEnvironmentStub: sinon.SinonStub;
let findOneOrganizationStub: sinon.SinonStub;
let defaultApiRateLimits: sinon.SinonStub;

beforeEach(async () => {
const moduleRef = await Test.createTestingModule({
Expand All @@ -43,18 +46,17 @@ describe('GetApiRateLimitMaximum', async () => {
.overrideProvider(CacheService)
.useValue(MockCacheService.createClient())
.compile();
await moduleRef.init(); // Trigger OnModuleInit

session = new UserSession();
await session.initialize();

useCase = moduleRef.get<GetApiRateLimitMaximum>(GetApiRateLimitMaximum);
organizationRepository = moduleRef.get<CommunityOrganizationRepository>(CommunityOrganizationRepository);
environmentRepository = moduleRef.get<EnvironmentRepository>(EnvironmentRepository);
getDefaultApiRateLimits = moduleRef.get<GetApiRateLimitServiceMaximumConfig>(GetApiRateLimitServiceMaximumConfig);

findOneEnvironmentStub = sinon.stub(environmentRepository, 'findOne');
findOneOrganizationStub = sinon.stub(organizationRepository, 'findById');
defaultApiRateLimits = sinon.stub(getDefaultApiRateLimits, 'default').value(mockDefaultApiRateLimits);
});

afterEach(() => {
Expand Down Expand Up @@ -135,8 +137,12 @@ describe('GetApiRateLimitMaximum', async () => {
});

it('should return default api rate limit for the organizations apiServiceLevel when apiServiceLevel IS set on organization', async () => {
const defaultApiRateLimit = mockDefaultApiRateLimits[mockApiServiceLevel][mockApiRateLimitCategory];

const defaultApiRateLimit = getFeatureForTierAsNumber(
ApiRateLimitCategoryToFeatureName[mockApiRateLimitCategory],
mockApiServiceLevel,
{ [FeatureFlagsKeysEnum.IS_2025_Q1_TIERING_ENABLED]: true },
false
);
const [rateLimit] = await useCase.execute(
GetApiRateLimitMaximumCommand.create({
organizationId: session.organization._id,
Expand Down Expand Up @@ -169,7 +175,12 @@ describe('GetApiRateLimitMaximum', async () => {
});

it('should return default api rate limit for the UNLIMITED service level when apiServiceLevel IS NOT set on organization', async () => {
const defaultApiRateLimit = mockDefaultApiRateLimits[ApiServiceLevelEnum.UNLIMITED][mockApiRateLimitCategory];
const defaultApiRateLimit = getFeatureForTierAsNumber(
ApiRateLimitCategoryToFeatureName[mockApiRateLimitCategory],
ApiServiceLevelEnum.UNLIMITED,
{ [FeatureFlagsKeysEnum.IS_2025_Q1_TIERING_ENABLED]: true },
false
);

const [rateLimit] = await useCase.execute(
GetApiRateLimitMaximumCommand.create({
Expand Down
Loading

0 comments on commit 8d27d3c

Please sign in to comment.