Skip to content

Commit

Permalink
feat(crowdinfiles): delete document if Crowdin API returns 404 (#213)
Browse files Browse the repository at this point in the history
  • Loading branch information
thompsonsj authored Oct 28, 2024
1 parent 59bd404 commit 3976a33
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import payload from 'payload';
import { initPayloadTest } from '../helpers/config';
import nock from 'nock';
import { mockCrowdinClient } from 'plugin/src/lib/api/mock/crowdin-api-responses';
import { pluginConfig } from '../helpers/plugin-config';
import { getFilesByDocumentID, payloadCrowdinSyncTranslationsApi } from 'payload-crowdin-sync';

const pluginOptions = pluginConfig();
const mockClient = mockCrowdinClient(pluginOptions);

describe('Lexical editor with multiple blocks', () => {
beforeAll(async () => {
await initPayloadTest({});
});

afterEach((done) => {
if (!nock.isDone()) {
throw new Error(
`Not all nock interceptors were used: ${JSON.stringify(
nock.pendingMocks()
)}`
);
}
nock.cleanAll();
done();
});

afterAll(async () => {
if (typeof payload?.db?.destroy === 'function') {
await payload.db.destroy(payload);
}
});

it('removes CrowdinFile Payload documents if the Crowdin API responds with a 404', async () => {
nock('https://api.crowdin.com')
.post(
`/api/v2/projects/${pluginOptions.projectId}/directories`
)
.twice()
.reply(200, mockClient.createDirectory({}))
.post(
`/api/v2/storages`
)
.reply(200, mockClient.addStorage())
.post(
`/api/v2/projects/${pluginOptions.projectId}/files`
)
.reply(
200,
mockClient.createFile({
fileId: 94100,
})
)
// translation
.post(
`/api/v2/projects/${
pluginOptions.projectId
}/translations/builds/files/${94100}`,
{
targetLanguageId: 'fr',
}
)
.reply(
404,
{
code: 404,
}
)

const post = await payload.create({
collection: "localized-posts-with-condition",
data: {
title: "Test post",
translateWithCrowdin: true,
},
});

const crowdinFiles = await getFilesByDocumentID(`${post.id}`, payload);

expect(crowdinFiles.length).toEqual(1)

const translationsApi = new payloadCrowdinSyncTranslationsApi(
pluginOptions,
payload
);

await translationsApi.updateTranslation({
documentId: `${post.id}`,
collection: 'localized-posts-with-condition',
dryRun: false,
excludeLocales: ['de_DE'],
});

const refreshedCrowdinFiles = await getFilesByDocumentID(`${post.id}`, payload);

expect(refreshedCrowdinFiles.length).toEqual(0)
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ describe("Collection: Localized Posts With Conditon", () => {
expect(Object.prototype.hasOwnProperty.call(result, 'crowdinArticleDirectory')).toBeFalsy();
});

it("creates an article directory if the conditon is met", async () => {
it("creates an article directory if the condition is met", async () => {
nock('https://api.crowdin.com')
.post(
`/api/v2/projects/${pluginOptions.projectId}/directories`
Expand Down
4 changes: 2 additions & 2 deletions plugin/src/lib/api/payload-crowdin-sync/files/by-document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class filesApiByDocument {
directoryId?: number;
document: Document
articleDirectory: CrowdinArticleDirectory
collectionSlug: keyof Config['collections'] | "globals";
collectionSlug: keyof Config['collections'] | keyof Config['globals'];
global: boolean;
pluginOptions: PluginOptions;
req: PayloadRequest;
Expand All @@ -44,7 +44,7 @@ export class filesApiByDocument {
parent,
}: {
document: Document,
collectionSlug: keyof Config['collections'] | "globals",
collectionSlug: keyof Config['collections'] | keyof Config['globals'],
global: boolean,
pluginOptions: PluginOptions,
req: PayloadRequest,
Expand Down
48 changes: 41 additions & 7 deletions plugin/src/lib/api/payload-crowdin-sync/translations.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import crowdin, {
Credentials,
CrowdinError,
Translations,
} from "@crowdin/crowdin-api-client";
import { Payload } from "payload";
Expand Down Expand Up @@ -73,6 +74,7 @@ export class payloadCrowdinSyncTranslationsApi {
localeMap: PluginOptions["localeMap"];
sourceLocale: PluginOptions["sourceLocale"];
htmlToSlateConfig: PluginOptions["htmlToSlateConfig"];
disableSelfClean?: PluginOptions["disableSelfClean"]

constructor(pluginOptions: PluginOptions, payload: Payload) {
// credentials
Expand All @@ -88,6 +90,7 @@ export class payloadCrowdinSyncTranslationsApi {
this.localeMap = pluginOptions.localeMap;
this.sourceLocale = pluginOptions.sourceLocale;
this.htmlToSlateConfig = pluginOptions.htmlToSlateConfig
this.disableSelfClean = pluginOptions.disableSelfClean
}

async updateTranslation({
Expand Down Expand Up @@ -376,13 +379,13 @@ export class payloadCrowdinSyncTranslationsApi {
return;
}
try {
const response = await this.translationsApi.buildProjectFileTranslation(
this.projectId,
file.originalId as number,
{
targetLanguageId: this.localeMap[locale].crowdinId,
}
);
const response = await this.buildTranslationFile({
file,
locale
})
if (!response) {
return
}
const data = await this.getFileDataFromUrl(response.data.url);
if (file.type === "html") {
const allFields = collection ? collection.fields : fields
Expand Down Expand Up @@ -458,6 +461,37 @@ export class payloadCrowdinSyncTranslationsApi {
}
}

private async buildTranslationFile({
file,
locale
}: {
file: CrowdinFile,
locale: string
}) {
try {
const response = await this.translationsApi.buildProjectFileTranslation(
this.projectId,
file.originalId as number,
{
targetLanguageId: this.localeMap[locale].crowdinId,
}
);
return response
}
catch (error: unknown) {
if (this.disableSelfClean) {
return undefined
}
if (error instanceof CrowdinError && error.code === 404) {
await this.payload.delete({
id: file.id,
collection: "crowdin-files",
})
}
return undefined
}
}

private async getBlockTranslations({
blockConfig,
file,
Expand Down
2 changes: 2 additions & 0 deletions plugin/src/lib/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ export const crowdinSync =
pluginCollectionAdmin: Joi.object(),
tabbedUI: Joi.boolean(),
lexicalBlockFolderPrefix: Joi.string(),
/** Prevent the plugin deleting Payload documents it has created in response to Crowdin API responses. */
disableSelfClean: Joi.boolean(),
});

const validate = schema.validate(pluginOptions);
Expand Down
1 change: 1 addition & 0 deletions plugin/src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export interface PluginOptions {
pluginCollectionAdmin?: CollectionConfig["admin"];
tabbedUI?: boolean
lexicalBlockFolderPrefix?: string
disableSelfClean?: boolean
}

export type FieldWithName = Field & { name: string };
Expand Down

0 comments on commit 3976a33

Please sign in to comment.