Skip to content

Commit 19af642

Browse files
authored
Merge pull request #146 from Smartling/PARSER-69-import-endpoint
PARSER-69-import-endpoint
2 parents aed21e6 + 6806c9b commit 19af642

7 files changed

Lines changed: 204 additions & 1 deletion

File tree

api/files/dto/imported-file-dto.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
interface TranslationImportErrorDto {
2+
importKey: string;
3+
stringHashcode: string;
4+
fileUri: string;
5+
messages: string[];
6+
}
7+
8+
interface ImportedFileDto {
9+
wordCount: number;
10+
stringCount: number;
11+
translationImportErrors: TranslationImportErrorDto[];
12+
}
13+
14+
export { TranslationImportErrorDto, ImportedFileDto };

api/files/index.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import { FileStatusForAllLocalesDto } from "./dto/file-status-for-all-locales-dt
99
import { SmartlingListResponse } from "../http/smartling-list-response";
1010
import { LastModifiedForLocale } from "./dto/last-modified-for-locale-dto";
1111
import { UploadedFileDto } from "./dto/uploaded-file-dto";
12+
import { ImportFileParameters } from "./params/import-file-parameters";
13+
import { ImportedFileDto } from "./dto/imported-file-dto";
1214
import { FileStatusForProjectDto } from "./dto/file-status-for-project-dto";
1315
import { DownloadFileAllTranslationsParameters } from "./params/download-file-all-translations-parameters";
1416
import { RecentlyUploadedFilesParameters } from "./params/recently-uploaded-files";
@@ -119,6 +121,26 @@ export class SmartlingFilesApi extends SmartlingBaseFileApi {
119121
);
120122
}
121123

124+
async importFile(
125+
projectId: string,
126+
locale: string,
127+
parameters: ImportFileParameters
128+
): Promise<ImportedFileDto> {
129+
const formData = new FormData();
130+
const exported = parameters.export();
131+
Object.keys(exported).forEach((key) => {
132+
formData.append(key, exported[key]);
133+
});
134+
135+
return await this.makeRequest(
136+
"post",
137+
`${this.entrypoint}/${projectId}/locales/${locale}/file/import`,
138+
formData,
139+
false,
140+
SmartlingFilesApi.fixContentTypeHeaderCase(formData)
141+
);
142+
}
143+
122144
async getRecentlyUploadedFiles(
123145
projectId: string,
124146
params: RecentlyUploadedFilesParameters
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import * as fs from "fs";
2+
import string2fileStream from "string-to-file-stream";
3+
import { BaseParameters } from "../../parameters/index";
4+
import { FileType } from "./file-type";
5+
import { TranslationState } from "./translation-state";
6+
import { SmartlingException } from "../../exception";
7+
8+
export class ImportFileParameters extends BaseParameters {
9+
setFileFromLocalFilePath(filePath: string): ImportFileParameters {
10+
this.set("file", fs.createReadStream(
11+
fs.realpathSync(filePath)
12+
));
13+
return this;
14+
}
15+
16+
setFileContent(fileContent: string): ImportFileParameters {
17+
this.set("file", string2fileStream(fileContent));
18+
return this;
19+
}
20+
21+
setFileUri(fileUri: string): ImportFileParameters {
22+
this.set("fileUri", fileUri);
23+
return this;
24+
}
25+
26+
setFileType(fileType: FileType): ImportFileParameters {
27+
this.set("fileType", fileType);
28+
return this;
29+
}
30+
31+
setTranslationState(translationState: TranslationState): ImportFileParameters {
32+
this.set("translationState", translationState);
33+
return this;
34+
}
35+
36+
setOverwrite(overwrite: boolean): ImportFileParameters {
37+
this.set("overwrite", String(overwrite));
38+
return this;
39+
}
40+
41+
setCallbackUrl(callbackUrl: string): ImportFileParameters {
42+
if (callbackUrl && (callbackUrl.length > 255)) {
43+
throw new SmartlingException("File callback URL should be not greater than 255 characters.");
44+
}
45+
46+
this.set("callbackUrl", callbackUrl);
47+
return this;
48+
}
49+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export enum TranslationState {
2+
IN_TRANSLATION = "IN_TRANSLATION",
3+
IN_EDITING = "IN_EDITING",
4+
IN_REVIEW = "IN_REVIEW",
5+
PUBLISHED = "PUBLISHED"
6+
}

index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,13 @@ export * from "./api/files/params/file-type";
4848
export * from "./api/files/params/filename-mode";
4949
export * from "./api/files/params/translation-file-name-mode";
5050
export * from "./api/files/params/upload-file-parameters";
51+
export * from "./api/files/params/import-file-parameters";
52+
export * from "./api/files/params/translation-state";
5153
export * from "./api/files/dto/file-status-for-all-locales-dto";
5254
export * from "./api/files/dto/file-status-for-locale-item-dto";
5355
export * from "./api/files/dto/last-modified-for-locale-dto";
5456
export * from "./api/files/dto/uploaded-file-dto";
57+
export * from "./api/files/dto/imported-file-dto";
5558
export * from "./api/glossaries/index";
5659
export * from "./api/glossaries/dto/glossary-dto";
5760
export * from "./api/glossaries/dto/fallback-locale-dto";

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "smartling-api-sdk-nodejs",
3-
"version": "2.31.0",
3+
"version": "2.32.0",
44
"description": "Package for Smartling API",
55
"main": "built/index.js",
66
"engines": {

test/files.spec.ts

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import { SmartlingException } from "../api/exception";
1919
import { TranslationFileNameMode } from "../api/files/params/translation-file-name-mode";
2020
import { FileLocaleMode } from "../api/files/params/file-locale-mode";
2121
import { FileFilter } from "../api/files/params/file-filter";
22+
import { ImportFileParameters } from "../api/files/params/import-file-parameters";
23+
import { TranslationState } from "../api/files/params/translation-state";
2224

2325
describe("SmartlingFilesApi class tests.", () => {
2426
const projectId = "testProjectId";
@@ -753,5 +755,112 @@ describe("SmartlingFilesApi class tests.", () => {
753755
);
754756
});
755757
});
758+
759+
describe("Import file", () => {
760+
const localeId = "fr-FR";
761+
762+
it("Import file from disk with all parameters", async () => {
763+
const params = new ImportFileParameters();
764+
765+
params
766+
.setFileFromLocalFilePath("./test/data/file.xml")
767+
.setFileUri("test-file-uri")
768+
.setFileType(FileType.XML)
769+
.setTranslationState(TranslationState.PUBLISHED)
770+
.setOverwrite(true)
771+
.setCallbackUrl("https://callback.url");
772+
773+
await filesApi.importFile(projectId, localeId, params);
774+
775+
sinon.assert.calledOnce(filesApiFetchStub);
776+
777+
assert.equal(
778+
filesApiFetchStub.getCall(0).args[0],
779+
`https://test.com/files-api/v2/projects/${projectId}/locales/${localeId}/file/import`
780+
);
781+
782+
assert.equal(
783+
filesApiFetchStub.getCall(0).args[1].method,
784+
"post"
785+
);
786+
787+
assert.equal(
788+
filesApiFetchStub.getCall(0).args[1].headers.Authorization,
789+
"test_token_type test_access_token"
790+
);
791+
792+
assert.equal(
793+
filesApiFetchStub.getCall(0).args[1].headers["User-Agent"],
794+
"test_user_agent"
795+
);
796+
797+
const stringified = JSON.stringify(filesApiFetchStub.getCall(0).args[1].body);
798+
799+
assert.ok(stringified.includes("Content-Disposition: form-data; name=\\\"fileUri\\\"\\r\\n\\r\\n\",\"test-file-uri\""));
800+
assert.ok(stringified.includes("Content-Disposition: form-data; name=\\\"translationState\\\"\\r\\n\\r\\n\",\"PUBLISHED\""));
801+
assert.ok(stringified.includes("Content-Disposition: form-data; name=\\\"overwrite\\\"\\r\\n\\r\\n\",\"true\""));
802+
assert.ok(stringified.includes("Content-Disposition: form-data; name=\\\"fileType\\\"\\r\\n\\r\\n\",\"xml\""));
803+
assert.ok(stringified.includes("Content-Disposition: form-data; name=\\\"callbackUrl\\\"\\r\\n\\r\\n\",\"https://callback.url\""));
804+
805+
assert.equal(
806+
// eslint-disable-next-line no-underscore-dangle
807+
await streamToString(filesApiFetchStub.getCall(0).args[1].body._streams[1]),
808+
fs.readFileSync(
809+
fs.realpathSync("./test/data/file.xml"),
810+
"utf8"
811+
)
812+
);
813+
});
814+
815+
it("Import file from string content", async () => {
816+
const params = new ImportFileParameters();
817+
818+
params
819+
.setFileContent(fs.readFileSync(
820+
fs.realpathSync("./test/data/file.xml"),
821+
"utf8"
822+
))
823+
.setFileUri("test-file-uri")
824+
.setFileType(FileType.XML);
825+
826+
await filesApi.importFile(projectId, localeId, params);
827+
828+
sinon.assert.calledOnce(filesApiFetchStub);
829+
830+
assert.equal(
831+
filesApiFetchStub.getCall(0).args[0],
832+
`https://test.com/files-api/v2/projects/${projectId}/locales/${localeId}/file/import`
833+
);
834+
835+
assert.equal(
836+
filesApiFetchStub.getCall(0).args[1].method,
837+
"post"
838+
);
839+
840+
assert.equal(
841+
filesApiFetchStub.getCall(0).args[1].headers.Authorization,
842+
"test_token_type test_access_token"
843+
);
844+
845+
assert.equal(
846+
filesApiFetchStub.getCall(0).args[1].headers["User-Agent"],
847+
"test_user_agent"
848+
);
849+
850+
const stringified = JSON.stringify(filesApiFetchStub.getCall(0).args[1].body);
851+
852+
assert.ok(stringified.includes("Content-Disposition: form-data; name=\\\"fileUri\\\"\\r\\n\\r\\n\",\"test-file-uri\""));
853+
assert.ok(stringified.includes("Content-Disposition: form-data; name=\\\"fileType\\\"\\r\\n\\r\\n\",\"xml\""));
854+
855+
assert.equal(
856+
// eslint-disable-next-line no-underscore-dangle
857+
await streamToString(filesApiFetchStub.getCall(0).args[1].body._streams[1]),
858+
fs.readFileSync(
859+
fs.realpathSync("./test/data/file.xml"),
860+
"utf8"
861+
)
862+
);
863+
});
864+
});
756865
});
757866
});

0 commit comments

Comments
 (0)