From ad5a3a1fe49c15f6529d01ca8e0fdac7576fdfa8 Mon Sep 17 00:00:00 2001 From: Edouard Demotes Date: Tue, 23 Jan 2024 17:51:02 -0500 Subject: [PATCH] feat: handle translations collection --- README.md | 5 ++- packages/cli/src/lib/loader.ts | 2 + .../cli/src/lib/services/collections/index.ts | 1 + .../collections/translations/collection.ts | 43 +++++++++++++++++++ .../collections/translations/constants.ts | 1 + .../collections/translations/data-client.ts | 36 ++++++++++++++++ .../collections/translations/data-differ.ts | 31 +++++++++++++ .../collections/translations/data-loader.ts | 20 +++++++++ .../collections/translations/data-mapper.ts | 15 +++++++ .../translations/id-mapper-client.ts | 11 +++++ .../collections/translations/index.ts | 8 ++++ .../collections/translations/interfaces.ts | 4 ++ .../cli/src/lib/services/config/schema.ts | 1 + 13 files changed, 176 insertions(+), 2 deletions(-) create mode 100644 packages/cli/src/lib/services/collections/translations/collection.ts create mode 100644 packages/cli/src/lib/services/collections/translations/constants.ts create mode 100644 packages/cli/src/lib/services/collections/translations/data-client.ts create mode 100644 packages/cli/src/lib/services/collections/translations/data-differ.ts create mode 100644 packages/cli/src/lib/services/collections/translations/data-loader.ts create mode 100644 packages/cli/src/lib/services/collections/translations/data-mapper.ts create mode 100644 packages/cli/src/lib/services/collections/translations/id-mapper-client.ts create mode 100644 packages/cli/src/lib/services/collections/translations/index.ts create mode 100644 packages/cli/src/lib/services/collections/translations/interfaces.ts diff --git a/README.md b/README.md index 168303cd..47200d76 100644 --- a/README.md +++ b/README.md @@ -156,7 +156,7 @@ going to Directus. Hooks are defined in the configuration file using the `hooks` property. Under this property, you can define the collection name and the hook function to be executed. -Available collection names are: `dashboards`, `flows`, `operations`, `panels`, `permissions`, `roles`, `settings`, +Available collection names are: `dashboards`, `flows`, `operations`, `panels`, `permissions`, `roles`, `settings`, `translations`, and `webhooks`. For each collection, available hook functions are: `onQuery`, `onLoad`, `onSave`, and `onDump`. @@ -333,6 +333,7 @@ flowchart - permissions - roles - settings +- translations - webhooks For these collections, data changes are committed to the code, allowing for replication on other Directus instances. A @@ -362,7 +363,7 @@ configurations and schema within Directus. Here is a step-by-step explanation of Upon execution of the `pull` command, `directus-sync` will: 1. Scan the specified Directus collections, which include dashboards, flows, operations, panels, permissions, roles, - settings, and webhooks. + settings, translations and webhooks. 2. Assign a SyncID to each element within these collections if it doesn't already have one. 3. Commit the data of these collections into code, allowing for versioning and tracking of configuration changes. diff --git a/packages/cli/src/lib/loader.ts b/packages/cli/src/lib/loader.ts index e06e6c3b..df13e488 100644 --- a/packages/cli/src/lib/loader.ts +++ b/packages/cli/src/lib/loader.ts @@ -7,6 +7,7 @@ import { PermissionsCollection, RolesCollection, SettingsCollection, + TranslationsCollection, WebhooksCollection, } from './services'; import { createDumpFolders } from './helpers'; @@ -62,6 +63,7 @@ export function loadCollections() { // The collections are populated in the same order return [ Container.get(SettingsCollection), + Container.get(TranslationsCollection), Container.get(WebhooksCollection), Container.get(FlowsCollection), Container.get(OperationsCollection), diff --git a/packages/cli/src/lib/services/collections/index.ts b/packages/cli/src/lib/services/collections/index.ts index 1fa2bc22..aba7a3ca 100644 --- a/packages/cli/src/lib/services/collections/index.ts +++ b/packages/cli/src/lib/services/collections/index.ts @@ -1,6 +1,7 @@ export * from './base'; export * from './flows'; export * from './settings'; +export * from './translations'; export * from './webhooks'; export * from './operations'; export * from './roles'; diff --git a/packages/cli/src/lib/services/collections/translations/collection.ts b/packages/cli/src/lib/services/collections/translations/collection.ts new file mode 100644 index 00000000..a07d4218 --- /dev/null +++ b/packages/cli/src/lib/services/collections/translations/collection.ts @@ -0,0 +1,43 @@ +import { DirectusCollection } from '../base'; +import pino from 'pino'; +import { Inject, Service } from 'typedi'; +import { TranslationsDataLoader } from './data-loader'; +import { TranslationsDataClient } from './data-client'; +import { TranslationsIdMapperClient } from './id-mapper-client'; +import { TranslationsDataDiffer } from './data-differ'; +import { getChildLogger } from '../../../helpers'; +import { TRANSLATIONS_COLLECTION } from './constants'; +import { TranslationsDataMapper } from './data-mapper'; +import { LOGGER } from '../../../constants'; +import { DirectusTranslation } from './interfaces'; +import { ConfigService } from '../../config'; +import { MigrationClient } from '../../migration-client'; + +@Service() +export class TranslationsCollection extends DirectusCollection { + protected readonly enableCreate = true; + protected readonly enableUpdate = true; + protected readonly enableDelete = true; + + constructor( + @Inject(LOGGER) baseLogger: pino.Logger, + dataDiffer: TranslationsDataDiffer, + dataLoader: TranslationsDataLoader, + dataClient: TranslationsDataClient, + dataMapper: TranslationsDataMapper, + idMapper: TranslationsIdMapperClient, + config: ConfigService, + migrationClient: MigrationClient, + ) { + super( + getChildLogger(baseLogger, TRANSLATIONS_COLLECTION), + dataDiffer, + dataLoader, + dataClient, + dataMapper, + idMapper, + migrationClient, + config.getHooksConfig(TRANSLATIONS_COLLECTION), + ); + } +} diff --git a/packages/cli/src/lib/services/collections/translations/constants.ts b/packages/cli/src/lib/services/collections/translations/constants.ts new file mode 100644 index 00000000..4432d974 --- /dev/null +++ b/packages/cli/src/lib/services/collections/translations/constants.ts @@ -0,0 +1 @@ +export const TRANSLATIONS_COLLECTION = 'translations'; diff --git a/packages/cli/src/lib/services/collections/translations/data-client.ts b/packages/cli/src/lib/services/collections/translations/data-client.ts new file mode 100644 index 00000000..3b9dfd61 --- /dev/null +++ b/packages/cli/src/lib/services/collections/translations/data-client.ts @@ -0,0 +1,36 @@ +import { DataClient, Query, WithoutIdAndSyncId } from '../base'; +import { + createTranslation, + deleteTranslation, + readTranslations, + updateTranslation, +} from '@directus/sdk'; +import { Service } from 'typedi'; +import { MigrationClient } from '../../migration-client'; +import { DirectusTranslation } from './interfaces'; + +@Service() +export class TranslationsDataClient extends DataClient { + constructor(migrationClient: MigrationClient) { + super(migrationClient); + } + + protected getDeleteCommand(itemId: number) { + return deleteTranslation(itemId); + } + + protected getInsertCommand(item: WithoutIdAndSyncId) { + return createTranslation(item); + } + + protected getQueryCommand(query: Query) { + return readTranslations(query); + } + + protected getUpdateCommand( + itemId: number, + diffItem: Partial>, + ) { + return updateTranslation(itemId, diffItem); + } +} diff --git a/packages/cli/src/lib/services/collections/translations/data-differ.ts b/packages/cli/src/lib/services/collections/translations/data-differ.ts new file mode 100644 index 00000000..4a6edc7f --- /dev/null +++ b/packages/cli/src/lib/services/collections/translations/data-differ.ts @@ -0,0 +1,31 @@ +import { DataDiffer } from '../base'; + +import { Inject, Service } from 'typedi'; +import { TRANSLATIONS_COLLECTION } from './constants'; +import pino from 'pino'; +import { TranslationsDataLoader } from './data-loader'; +import { TranslationsDataClient } from './data-client'; +import { TranslationsIdMapperClient } from './id-mapper-client'; +import { getChildLogger } from '../../../helpers'; +import { TranslationsDataMapper } from './data-mapper'; +import { LOGGER } from '../../../constants'; +import { DirectusTranslation } from './interfaces'; + +@Service() +export class TranslationsDataDiffer extends DataDiffer { + constructor( + @Inject(LOGGER) baseLogger: pino.Logger, + dataLoader: TranslationsDataLoader, + dataClient: TranslationsDataClient, + dataMapper: TranslationsDataMapper, + idMapper: TranslationsIdMapperClient, + ) { + super( + getChildLogger(baseLogger, TRANSLATIONS_COLLECTION), + dataLoader, + dataClient, + dataMapper, + idMapper, + ); + } +} diff --git a/packages/cli/src/lib/services/collections/translations/data-loader.ts b/packages/cli/src/lib/services/collections/translations/data-loader.ts new file mode 100644 index 00000000..1cf184e9 --- /dev/null +++ b/packages/cli/src/lib/services/collections/translations/data-loader.ts @@ -0,0 +1,20 @@ +import { DataLoader } from '../base'; + +import { Service } from 'typedi'; +import { TRANSLATIONS_COLLECTION } from './constants'; +import path from 'path'; +import { DirectusTranslation } from './interfaces'; +import { ConfigService } from '../../config'; +import { MigrationClient } from '../../migration-client'; + +@Service() +export class TranslationsDataLoader extends DataLoader { + constructor(config: ConfigService, migrationClient: MigrationClient) { + const filePath = path.join( + config.getCollectionsConfig().dumpPath, + `${TRANSLATIONS_COLLECTION}.json`, + ); + const hooks = config.getHooksConfig(TRANSLATIONS_COLLECTION); + super(filePath, migrationClient, hooks); + } +} diff --git a/packages/cli/src/lib/services/collections/translations/data-mapper.ts b/packages/cli/src/lib/services/collections/translations/data-mapper.ts new file mode 100644 index 00000000..73be526d --- /dev/null +++ b/packages/cli/src/lib/services/collections/translations/data-mapper.ts @@ -0,0 +1,15 @@ +import { DataMapper } from '../base'; + +import { Inject, Service } from 'typedi'; +import pino from 'pino'; +import { getChildLogger } from '../../../helpers'; +import { LOGGER } from '../../../constants'; +import { TRANSLATIONS_COLLECTION } from './constants'; +import { DirectusTranslation } from './interfaces'; + +@Service() +export class TranslationsDataMapper extends DataMapper { + constructor(@Inject(LOGGER) baseLogger: pino.Logger) { + super(getChildLogger(baseLogger, TRANSLATIONS_COLLECTION)); + } +} diff --git a/packages/cli/src/lib/services/collections/translations/id-mapper-client.ts b/packages/cli/src/lib/services/collections/translations/id-mapper-client.ts new file mode 100644 index 00000000..18e12a88 --- /dev/null +++ b/packages/cli/src/lib/services/collections/translations/id-mapper-client.ts @@ -0,0 +1,11 @@ +import { IdMapperClient } from '../base'; +import { Service } from 'typedi'; +import { TRANSLATIONS_COLLECTION } from './constants'; +import { MigrationClient } from '../../migration-client'; + +@Service() +export class TranslationsIdMapperClient extends IdMapperClient { + constructor(migrationClient: MigrationClient) { + super(migrationClient, TRANSLATIONS_COLLECTION); + } +} diff --git a/packages/cli/src/lib/services/collections/translations/index.ts b/packages/cli/src/lib/services/collections/translations/index.ts new file mode 100644 index 00000000..203e6c76 --- /dev/null +++ b/packages/cli/src/lib/services/collections/translations/index.ts @@ -0,0 +1,8 @@ +export * from './interfaces'; +export * from './constants'; +export * from './collection'; +export * from './data-client'; +export * from './data-differ'; +export * from './data-mapper'; +export * from './data-loader'; +export * from './id-mapper-client'; diff --git a/packages/cli/src/lib/services/collections/translations/interfaces.ts b/packages/cli/src/lib/services/collections/translations/interfaces.ts new file mode 100644 index 00000000..45a07899 --- /dev/null +++ b/packages/cli/src/lib/services/collections/translations/interfaces.ts @@ -0,0 +1,4 @@ +import { DirectusTranslation as BaseDirectusTranslation } from '@directus/sdk'; +import { BaseSchema } from '../base'; + +export type DirectusTranslation = BaseDirectusTranslation; diff --git a/packages/cli/src/lib/services/config/schema.ts b/packages/cli/src/lib/services/config/schema.ts index 18161b0a..40c06f34 100644 --- a/packages/cli/src/lib/services/config/schema.ts +++ b/packages/cli/src/lib/services/config/schema.ts @@ -15,6 +15,7 @@ export const OptionsHooksSchema = z.object({ permissions: HooksSchema.optional(), roles: HooksSchema.optional(), settings: HooksSchema.optional(), + translations: HooksSchema.optional(), webhooks: HooksSchema.optional(), });