-
Notifications
You must be signed in to change notification settings - Fork 80
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Automatic translation config schema (#7112)
* Automatic translation config schema * WIP, GetAutomaticTranslationConfig * Wip, GetAutomaticTranslationConfig service * Filter out wrong configs - Filter out configs belonging to non existent templates - Filter out properties belonging to other templates * GetAutomaticTranslation filters languages. Filters configured languages by the languages supported by the external service * Typo and naming fix * Moved service to externalIntegrations folder * Fixed ESLint suggestion * Create Models for the service and refined tests * Fixed Typo * Moved logic to model and updated type definitions * Implemented getByNames method. * Prepared script for Generating AT Config from Semantic data * commonProperties on the Template model * Fix Test * Remove AT config from settingsDS moved responsability to the new AutomaticTranslationConfigDS * WIP Red test to implement invalid config test case * AutomaticTranslationConfigDataSource fix now returns and accepts domain object instead of a db raw type * GenerateAutomaticTranslationConfig use case * generateAutomaticTranslation cli script - scripts.v2 included in tsconfig * tenants tearDown, closes mongo model change stream * Fixed type errors * WIP, input data shape validation * Renamed to AT most of the internal module files. * Moved validator to own contract * Changed Validator to return array of strings * Return all error params. * Implemented typeguard for validator * Fixed prettier desync with ESLint * Fixed eslint errors * Removed prettier exceptions * Removed extra eslintrc rule. --------- Co-authored-by: RafaPolit <rafaelpolit@gmail.com>
- Loading branch information
Showing
32 changed files
with
805 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
app/api/externalIntegrations.v2/automaticTranslation/AutomaticTranslationFactory.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { DefaultTransactionManager } from 'api/common.v2/database/data_source_defaults'; | ||
import { getConnection } from 'api/common.v2/database/getConnectionForCurrentTenant'; | ||
import { MongoTemplatesDataSource } from 'api/templates.v2/database/MongoTemplatesDataSource'; | ||
import { GenerateAutomaticTranslationsCofig } from './GenerateAutomaticTranslationConfig'; | ||
import { MongoATConfigDataSource } from './infrastructure/MongoATConfigDataSource'; | ||
import { AJVATConfigValidator } from './infrastructure/AJVATConfigValidator'; | ||
|
||
const AutomaticTranslationFactory = { | ||
defaultGenerateATConfig() { | ||
return new GenerateAutomaticTranslationsCofig( | ||
new MongoATConfigDataSource(getConnection(), DefaultTransactionManager()), | ||
new MongoTemplatesDataSource(getConnection(), DefaultTransactionManager()), | ||
new AJVATConfigValidator() | ||
); | ||
}, | ||
}; | ||
|
||
export { AutomaticTranslationFactory }; |
63 changes: 63 additions & 0 deletions
63
app/api/externalIntegrations.v2/automaticTranslation/GenerateAutomaticTranslationConfig.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import { TemplatesDataSource } from 'api/templates.v2/contracts/TemplatesDataSource'; | ||
import { ATConfigDataSource } from './contracts/ATConfigDataSource'; | ||
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; | ||
|
||
constructor( | ||
atuomaticTranslationConfigDS: ATConfigDataSource, | ||
templatesDS: TemplatesDataSource, | ||
validator: ATConfigValidator | ||
) { | ||
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]); | ||
} | ||
|
||
const templatesData = await this.templatsDS | ||
.getByNames(semanticConfig.templates.map(t => t.template)) | ||
.all(); | ||
|
||
const templates = semanticConfig.templates.map(configData => { | ||
const templateData = templatesData.find(t => t.name === configData.template); | ||
if (!templateData) { | ||
throw new GenerateATConfigError(`Template not found: ${configData.template}`); | ||
} | ||
return new ATTemplateConfig( | ||
templateData?.id, | ||
(configData.properties || []).map(label => { | ||
const foundProperty = templateData.properties.find(p => p.label === label); | ||
if (!foundProperty) { | ||
throw new GenerateATConfigError(`Property not found: ${label}`); | ||
} | ||
return foundProperty.id; | ||
}), | ||
(configData.commonProperties || []).map(label => { | ||
const foundProperty = templateData?.commonProperties.find(p => p.label === label); | ||
if (!foundProperty) { | ||
throw new GenerateATConfigError(`Common property not found: ${label}`); | ||
} | ||
return foundProperty.id; | ||
}) | ||
); | ||
}); | ||
|
||
return this.atuomaticTranslationConfigDS.update( | ||
new RawATConfig(semanticConfig.active, templates) | ||
); | ||
} | ||
} |
6 changes: 6 additions & 0 deletions
6
app/api/externalIntegrations.v2/automaticTranslation/contracts/ATConfigDataSource.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { RawATConfig } from '../model/RawATConfig'; | ||
|
||
export interface ATConfigDataSource { | ||
get(): Promise<RawATConfig>; | ||
update(config: RawATConfig): Promise<RawATConfig>; | ||
} |
6 changes: 6 additions & 0 deletions
6
app/api/externalIntegrations.v2/automaticTranslation/contracts/ATConfigValidator.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { SemanticConfig } from '../types/SemanticConfig'; | ||
|
||
export interface ATConfigValidator { | ||
getErrors(): string[]; | ||
validate(data: unknown): data is SemanticConfig; | ||
} |
5 changes: 5 additions & 0 deletions
5
app/api/externalIntegrations.v2/automaticTranslation/contracts/ATGateway.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { LanguageISO6391 } from 'shared/types/commonTypes'; | ||
|
||
export interface ATGateway { | ||
supportedLanguages(): Promise<LanguageISO6391[]>; | ||
} |
3 changes: 3 additions & 0 deletions
3
app/api/externalIntegrations.v2/automaticTranslation/errors/generateATErrors.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
/* eslint-disable max-classes-per-file */ | ||
export class GenerateATConfigError extends Error {} | ||
export class InvalidInputDataFormat extends Error {} |
38 changes: 38 additions & 0 deletions
38
app/api/externalIntegrations.v2/automaticTranslation/infrastructure/AJVATConfigValidator.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { Ajv } from 'ajv'; | ||
import { JTDSchemaType } from 'ajv/dist/core'; | ||
import { ATConfigValidator } from '../contracts/ATConfigValidator'; | ||
import { SemanticConfig } from '../types/SemanticConfig'; | ||
|
||
const schema: JTDSchemaType<SemanticConfig> = { | ||
additionalProperties: false, | ||
properties: { | ||
active: { type: 'boolean' }, | ||
templates: { | ||
elements: { | ||
properties: { | ||
template: { type: 'string' }, | ||
}, | ||
optionalProperties: { | ||
properties: { elements: { type: 'string' } }, | ||
commonProperties: { elements: { type: 'string' } }, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}; | ||
|
||
export class AJVATConfigValidator implements ATConfigValidator { | ||
private errors: string[] = []; | ||
|
||
getErrors() { | ||
return this.errors; | ||
} | ||
|
||
validate(data: unknown) { | ||
const ajv = new Ajv({ strict: false }); | ||
const validate = ajv.compile<SemanticConfig>(schema); | ||
const result = validate(data); | ||
this.errors = validate.errors ? validate.errors?.map(e => JSON.stringify(e.params)) : []; | ||
return result; | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
app/api/externalIntegrations.v2/automaticTranslation/infrastructure/ATExternalAPI.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { LanguageISO6391 } from 'shared/types/commonTypes'; | ||
import { ATGateway } from '../contracts/ATGateway'; | ||
|
||
export class ATExternalAPI implements ATGateway { | ||
// eslint-disable-next-line class-methods-use-this | ||
async supportedLanguages() { | ||
const result: LanguageISO6391[] = ['ru', 'en', 'fr', 'es']; | ||
return result; | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
...pi/externalIntegrations.v2/automaticTranslation/infrastructure/MongoATConfigDataSource.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { MongoDataSource } from 'api/common.v2/database/MongoDataSource'; | ||
import { Settings as SettingsType } from 'shared/types/settingsType'; | ||
import { ATConfigDataSource } from '../contracts/ATConfigDataSource'; | ||
import { RawATConfig } from '../model/RawATConfig'; | ||
import { ATTemplateConfig } from '../model/ATConfig'; | ||
|
||
export class MongoATConfigDataSource | ||
extends MongoDataSource<SettingsType> | ||
implements ATConfigDataSource | ||
{ | ||
protected collectionName = 'settings'; | ||
|
||
async get() { | ||
const settings = await this.getCollection().findOne(); | ||
const config = settings?.features?.automaticTranslation ?? { active: false }; | ||
|
||
return new RawATConfig( | ||
config.active, | ||
(config.templates || []).map( | ||
t => new ATTemplateConfig(t.template, t.properties || [], t.commonProperties) | ||
) | ||
); | ||
} | ||
|
||
async update(config: RawATConfig) { | ||
await this.getCollection().findOneAndUpdate( | ||
{}, | ||
{ $set: { 'features.automaticTranslation': config } } | ||
); | ||
return this.get(); | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
app/api/externalIntegrations.v2/automaticTranslation/model/ATConfig.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/* eslint-disable max-classes-per-file */ | ||
import { LanguageISO6391 } from 'shared/types/commonTypes'; | ||
|
||
class ATTemplateConfig { | ||
readonly template: string; | ||
|
||
readonly commonProperties: string[]; | ||
|
||
readonly properties: string[]; | ||
|
||
constructor(template: string, properties: string[], commonProperties: string[] = []) { | ||
this.template = template; | ||
this.commonProperties = commonProperties; | ||
this.properties = properties; | ||
} | ||
} | ||
|
||
class ATConfig { | ||
readonly active: boolean; | ||
|
||
readonly languages: LanguageISO6391[]; | ||
|
||
readonly templates: ATTemplateConfig[]; | ||
|
||
constructor(active: boolean, languages: LanguageISO6391[], templates: ATTemplateConfig[]) { | ||
this.active = active; | ||
this.languages = languages; | ||
this.templates = templates.filter(t => t.commonProperties.length || t.properties.length); | ||
} | ||
} | ||
|
||
export { ATConfig, ATTemplateConfig }; |
44 changes: 44 additions & 0 deletions
44
app/api/externalIntegrations.v2/automaticTranslation/model/RawATConfig.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { LanguageISO6391 } from 'shared/types/commonTypes'; | ||
import { Property } from 'api/templates.v2/model/Property'; | ||
import { ATConfig, ATTemplateConfig } from './ATConfig'; | ||
|
||
class RawATConfig { | ||
readonly active: boolean; | ||
|
||
readonly templates: ATTemplateConfig[]; | ||
|
||
constructor(active: boolean, templates: ATTemplateConfig[]) { | ||
this.active = active; | ||
this.templates = templates; | ||
} | ||
|
||
getCompleteConfig(languages: LanguageISO6391[], validProperties: Property[]): ATConfig { | ||
const validPropertiesMap = validProperties.reduce( | ||
(memo, property) => { | ||
// eslint-disable-next-line no-param-reassign | ||
memo[property.id] = property; | ||
return memo; | ||
}, | ||
{} as { [k: string]: Property } | ||
); | ||
|
||
const validPropertiesIds = Object.keys(validPropertiesMap); | ||
|
||
const templates = (this.templates || []).map( | ||
templateConfig => | ||
new ATTemplateConfig( | ||
templateConfig.template, | ||
(templateConfig.properties || []).filter( | ||
propertyId => | ||
validPropertiesIds.includes(propertyId) && | ||
validPropertiesMap[propertyId].template === templateConfig.template | ||
), | ||
templateConfig.commonProperties | ||
) | ||
); | ||
|
||
return new ATConfig(this.active, languages, templates); | ||
} | ||
} | ||
|
||
export { RawATConfig }; |
39 changes: 39 additions & 0 deletions
39
...pi/externalIntegrations.v2/automaticTranslation/services/GetAutomaticTranslationConfig.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { SettingsDataSource } from 'api/settings.v2/contracts/SettingsDataSource'; | ||
import { TemplatesDataSource } from 'api/templates.v2/contracts/TemplatesDataSource'; | ||
import { ATGateway } from '../contracts/ATGateway'; | ||
import { ATConfigDataSource } from '../contracts/ATConfigDataSource'; | ||
|
||
export class GetAutomaticTranslationConfig { | ||
private settings: SettingsDataSource; | ||
|
||
private config: ATConfigDataSource; | ||
|
||
private templates: TemplatesDataSource; | ||
|
||
private automaticTranslation: ATGateway; | ||
|
||
constructor( | ||
settings: SettingsDataSource, | ||
config: ATConfigDataSource, | ||
templates: TemplatesDataSource, | ||
automaticTranslation: ATGateway | ||
) { | ||
this.settings = settings; | ||
this.config = config; | ||
this.templates = templates; | ||
this.automaticTranslation = automaticTranslation; | ||
} | ||
|
||
async execute() { | ||
const config = await this.config.get(); | ||
|
||
const validProperties = await this.templates.getAllTextProperties().all(); | ||
const configuredLanguages = await this.settings.getLanguageKeys(); | ||
const supportedLanguages = await this.automaticTranslation.supportedLanguages(); | ||
|
||
return config.getCompleteConfig( | ||
configuredLanguages.filter(languageKey => supportedLanguages.includes(languageKey)), | ||
validProperties | ||
); | ||
} | ||
} |
Oops, something went wrong.