Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/production' into staging
Browse files Browse the repository at this point in the history
  • Loading branch information
daneryl committed Oct 4, 2024
2 parents 747334f + b92eb5c commit 0ce23d5
Show file tree
Hide file tree
Showing 19 changed files with 131 additions and 166 deletions.
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
import { DefaultTransactionManager } from 'api/common.v2/database/data_source_defaults';
import { getConnection } from 'api/common.v2/database/getConnectionForCurrentTenant';
import { DefaultEntitiesDataSource } from 'api/entities.v2/database/data_source_defaults';
import { entityInputDataSchema } from 'api/entities.v2/EntityInputDataSchema';
import { EntityInputData } from 'api/entities.v2/EntityInputDataType';
import { EventsBus } from 'api/eventsbus';
import { TaskManager } from 'api/services/tasksmanager/TaskManager';
import { DefaultSettingsDataSource } from 'api/settings.v2/database/data_source_defaults';
import { DefaultTemplatesDataSource } from 'api/templates.v2/database/data_source_defaults';
import { MongoTemplatesDataSource } from 'api/templates.v2/database/MongoTemplatesDataSource';
import { ATEntityCreationListener } from './adapters/driving/ATEntityCreationListener';
import { GenerateAutomaticTranslationsCofig } from './GenerateAutomaticTranslationConfig';
import { AJVATConfigValidator } from './infrastructure/AJVATConfigValidator';
import { AJVTranslationResultValidator } from './infrastructure/AJVTranslationResultValidator';
import { ATExternalAPI } from './infrastructure/ATExternalAPI';
import { AJVEntityInputValidator } from './infrastructure/EntityInputValidator';
import { MongoATConfigDataSource } from './infrastructure/MongoATConfigDataSource';
import { Validator } from './infrastructure/Validator';
import { ATTaskMessage, RequestEntityTranslation } from './RequestEntityTranslation';
import { SaveEntityTranslations } from './SaveEntityTranslations';
import { ATConfigService } from './services/GetAutomaticTranslationConfig';
import { SemanticConfig, semanticConfigSchema } from './types/SemanticConfig';
import { TranslationResult, translationResultSchema } from './types/TranslationResult';

const AutomaticTranslationFactory = {
defaultGenerateATConfig() {
return new GenerateAutomaticTranslationsCofig(
new MongoATConfigDataSource(getConnection(), DefaultTransactionManager()),
new MongoTemplatesDataSource(getConnection(), DefaultTransactionManager()),
new AJVATConfigValidator()
new Validator<SemanticConfig>(semanticConfigSchema)
);
},

Expand All @@ -31,7 +33,7 @@ const AutomaticTranslationFactory = {
return new SaveEntityTranslations(
DefaultTemplatesDataSource(transactionManager),
DefaultEntitiesDataSource(transactionManager),
new AJVTranslationResultValidator()
new Validator<TranslationResult>(translationResultSchema)
);
},

Expand All @@ -52,7 +54,7 @@ const AutomaticTranslationFactory = {
}),
DefaultTemplatesDataSource(DefaultTransactionManager()),
AutomaticTranslationFactory.defaultATConfigService(),
new AJVEntityInputValidator()
new Validator<EntityInputData>(entityInputDataSchema)
);
},

Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,30 @@
import { TemplatesDataSource } from 'api/templates.v2/contracts/TemplatesDataSource';
import { ATConfigDataSource } from './contracts/ATConfigDataSource';
import { GenerateATConfigError } from './errors/generateATErrors';
import { Validator } from './infrastructure/Validator';
import { ATTemplateConfig } from './model/ATConfig';
import { RawATConfig } from './model/RawATConfig';
import { GenerateATConfigError, InvalidInputDataFormat } from './errors/generateATErrors';
import { ATConfigValidator } from './contracts/ATConfigValidator';
import { SemanticConfig } from './types/SemanticConfig';

export class GenerateAutomaticTranslationsCofig {
private atuomaticTranslationConfigDS: ATConfigDataSource;

private templatsDS: TemplatesDataSource;

private validator: ATConfigValidator;
private validator: Validator<SemanticConfig>;

constructor(
atuomaticTranslationConfigDS: ATConfigDataSource,
templatesDS: TemplatesDataSource,
validator: ATConfigValidator
validator: Validator<SemanticConfig>
) {
this.atuomaticTranslationConfigDS = atuomaticTranslationConfigDS;
this.templatsDS = templatesDS;
this.validator = validator;
}

async execute(semanticConfig: SemanticConfig | unknown) {
if (!this.validator.validate(semanticConfig)) {
throw new InvalidInputDataFormat(this.validator.getErrors()[0]);
}
this.validator.ensure(semanticConfig);

const templatesData = await this.templatsDS
.getByNames(semanticConfig.templates.map(t => t.template))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ import { getTenant } from 'api/common.v2/database/getConnectionForCurrentTenant'
import { TaskManager } from 'api/services/tasksmanager/TaskManager';
import { TemplatesDataSource } from 'api/templates.v2/contracts/TemplatesDataSource';
import { EntityInputData } from 'api/entities.v2/EntityInputDataType';
import { EntityInputValidator } from './contracts/EntityInputValidator';
import { ATConfigService } from './services/GetAutomaticTranslationConfig';
import { InvalidInputDataFormat } from './errors/generateATErrors';
import { Validator } from './infrastructure/Validator';

export type ATTaskMessage = {
key: string[];
Expand All @@ -22,13 +21,13 @@ export class RequestEntityTranslation {

private aTConfigService: ATConfigService;

private inputValidator: EntityInputValidator;
private inputValidator: Validator<EntityInputData>;

constructor(
taskManager: TaskManager<ATTaskMessage>,
templatesDS: TemplatesDataSource,
aTConfigService: ATConfigService,
inputValidator: EntityInputValidator
inputValidator: Validator<EntityInputData>
) {
this.taskManager = taskManager;
this.templatesDS = templatesDS;
Expand All @@ -38,9 +37,7 @@ export class RequestEntityTranslation {

// eslint-disable-next-line max-statements
async execute(entity: EntityInputData | unknown) {
if (!this.inputValidator.validate(entity)) {
throw new InvalidInputDataFormat(this.inputValidator.getErrors()[0]);
}
this.inputValidator.ensure(entity);
const atConfig = await this.aTConfigService.get();
const atTemplateConfig = atConfig.templates.find(
t => t.template === entity.template?.toString()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { EntitiesDataSource } from 'api/entities.v2/contracts/EntitiesDataSource';
import { TemplatesDataSource } from 'api/templates.v2/contracts/TemplatesDataSource';
import { ATTranslationResultValidator } from './contracts/ATTranslationResultValidator';
import { InvalidInputDataFormat } from './errors/generateATErrors';
import { TranslationResult } from './types/TranslationResult';
import { Validator } from './infrastructure/Validator';

export class SaveEntityTranslations {
static AITranslatedText = '(AI translated)';
Expand All @@ -11,22 +10,20 @@ export class SaveEntityTranslations {

private templatesDS: TemplatesDataSource;

private validator: ATTranslationResultValidator;
private validator: Validator<TranslationResult>;

constructor(
templatesDS: TemplatesDataSource,
entitiesDS: EntitiesDataSource,
validator: ATTranslationResultValidator
validator: Validator<TranslationResult>
) {
this.entitiesDS = entitiesDS;
this.templatesDS = templatesDS;
this.validator = validator;
}

async execute(translationResult: TranslationResult | unknown) {
if (!this.validator.validate(translationResult)) {
throw new InvalidInputDataFormat(this.validator.getErrors()[0]);
}
this.validator.ensure(translationResult);

const [, entitySharedId, propertyId] = translationResult.key;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
import { tenants } from 'api/tenants';
import { TaskManager } from 'api/services/tasksmanager/TaskManager';
import { permissionsContext } from 'api/permissions/permissionsContext';
import { ATTranslationResultValidator } from '../../contracts/ATTranslationResultValidator';
import { AJVTranslationResultValidator } from '../../infrastructure/AJVTranslationResultValidator';
import { InvalidATServerResponse } from '../../errors/generateATErrors';
import { AutomaticTranslationFactory } from '../../AutomaticTranslationFactory';
import { Validator } from '../../infrastructure/Validator';
import { TranslationResult, translationResultSchema } from '../../types/TranslationResult';

export class ATServiceListener {
static SERVICE_NAME = 'translations';

private taskManager: TaskManager;

constructor(ATFactory: typeof AutomaticTranslationFactory = AutomaticTranslationFactory) {
const validator: ATTranslationResultValidator = new AJVTranslationResultValidator();
const validator = new Validator<TranslationResult>(translationResultSchema);
this.taskManager = new TaskManager({
serviceName: ATServiceListener.SERVICE_NAME,
processResults: async result => {
if (!validator.validate(result)) {
throw new InvalidATServerResponse(validator.getErrors()[0]);
throw new InvalidATServerResponse(validator.getErrors()[0].message, {
cause: validator.getErrors()[0],
});
}

await tenants.run(async () => {
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable max-classes-per-file */
export class GenerateATConfigError extends Error {}
export class InvalidInputDataFormat extends Error {}
export class InvalidATServerResponse extends Error {}

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import Ajv, { ValidateFunction } from 'ajv';
import { Schema } from 'ajv/dist/core';

export class ValidationError extends Error {}

export class Validator<T> {
private errors: ValidationError[] = [];

private validateFunction: ValidateFunction;

constructor(schema: Schema) {
const ajv = new Ajv({ strict: false });
this.validateFunction = ajv.compile<T>(schema);
}

getErrors() {
return this.errors;
}

validate(data: unknown): data is T {
const result = this.validateFunction(data);
this.errors = this.validateFunction.errors
? this.validateFunction.errors.map(e => new ValidationError(e.message, { cause: e }))
: [];
return result;
}

ensure(data: unknown): asserts data is T {
this.validateFunction(data);
this.errors = this.validateFunction.errors
? this.validateFunction.errors.map(e => new ValidationError(e.message, { cause: e }))
: [];
if (this.errors.length) {
throw this.errors[0];
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { DefaultTransactionManager } from 'api/common.v2/database/data_source_de
import { MongoTemplatesDataSource } from 'api/templates.v2/database/MongoTemplatesDataSource';
import { GenerateAutomaticTranslationsCofig } from '../GenerateAutomaticTranslationConfig';
import { MongoATConfigDataSource } from '../infrastructure/MongoATConfigDataSource';
import { GenerateATConfigError, InvalidInputDataFormat } from '../errors/generateATErrors';
import { SemanticConfig } from '../types/SemanticConfig';
import { AJVATConfigValidator } from '../infrastructure/AJVATConfigValidator';
import { GenerateATConfigError } from '../errors/generateATErrors';
import { SemanticConfig, semanticConfigSchema } from '../types/SemanticConfig';
import { ValidationError, Validator } from '../infrastructure/Validator';

const factory = getFixturesFactory();

Expand Down Expand Up @@ -83,7 +83,7 @@ describe('GenerateAutomaticTranslationConfig', () => {
generateAutomaticTranslationConfig = new GenerateAutomaticTranslationsCofig(
automaticTranslationConfigDS,
new MongoTemplatesDataSource(getConnection(), DefaultTransactionManager()),
new AJVATConfigValidator()
new Validator<SemanticConfig>(semanticConfigSchema)
);
});

Expand Down Expand Up @@ -160,8 +160,11 @@ describe('GenerateAutomaticTranslationConfig', () => {

it('should validate input has proper shape at runtime', async () => {
const invalidConfig = { invalid_prop: true };
await expect(generateAutomaticTranslationConfig.execute(invalidConfig)).rejects.toBeInstanceOf(
ValidationError
);
await expect(generateAutomaticTranslationConfig.execute(invalidConfig)).rejects.toEqual(
new InvalidInputDataFormat('{"additionalProperty":"invalid_prop"}')
new ValidationError('must NOT have additional properties')
);
});
});
Loading

0 comments on commit 0ce23d5

Please sign in to comment.