🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more →

@lokalise/file-storage-service-sdk

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@lokalise/file-storage-service-sdk - npm Package Compare versions

Comparing version

to
6.2.0

import type { ErrorReporter } from '@lokalise/node-core';
import type { TempFilePathResolver } from './fileStorageClient';
export interface FileStorageClientConfig {

@@ -6,2 +7,4 @@ baseUrl: string;

errorReporter?: ErrorReporter;
tempFilePathResolver?: TempFilePathResolver;
createDefaultContentDirectory?: boolean;
}

@@ -8,0 +11,0 @@ export interface RetryConfig {

/// <reference types="node" />
import type { Either } from '@lokalise/node-core/dist/src/errors/either';
import type { Either } from '@lokalise/node-core';
import type { FileStorageClientConfig } from './configModels';
import type { DownloadError, FileData, FileMetadata, FileUploadData, HttpRequestContext } from './model';
import type { ContentHeaders, ErrorResponse, UseCaseEnum } from './schema/storageSchemas';
export type TempFilePathResolver = (fileData: FileData) => Promise<string>;
export declare const defaultTempFilePathResolver: TempFilePathResolver;
export declare class FileStorageClient {

@@ -10,2 +12,3 @@ private readonly retryConfig;

private readonly fileStorageHttpClient;
private readonly tempFilePathResolver;
constructor(config: FileStorageClientConfig);

@@ -12,0 +15,0 @@ uploadFile(ownerId: string, useCase: UseCaseEnum, fileData: FileData, contentHeaders: ContentHeaders, requestContext: HttpRequestContext): Promise<Either<ErrorResponse, string>>;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FileStorageClient = void 0;
exports.FileStorageClient = exports.defaultTempFilePathResolver = void 0;
const node_fs_1 = require("node:fs");
const node_path_1 = require("node:path");
const node_core_1 = require("@lokalise/node-core");
const tmp_1 = require("tmp");
const configModels_1 = require("./configModels");
const errorHandling_1 = require("./errorHandling");
const restUtils_1 = require("./utils/restUtils");
const DEFAULT_UPLOAD_FILES_SUBDIR = 'fss-uploads';
const defaultTempFilePathResolver = () => {
return new Promise((resolve, reject) => {
(0, tmp_1.tmpName)({
dir: DEFAULT_UPLOAD_FILES_SUBDIR,
}, (err, filepath) => {
if (err) {
return reject(err);
}
return resolve(filepath);
});
});
};
exports.defaultTempFilePathResolver = defaultTempFilePathResolver;
function isReadableStream(obj) {
return obj != null && typeof obj === 'object' && typeof obj.pipe === 'function';
}
class FileStorageClient {

@@ -12,2 +32,3 @@ retryConfig;

fileStorageHttpClient;
tempFilePathResolver;
constructor(config) {

@@ -17,2 +38,12 @@ this.fileStorageHttpClient = (0, node_core_1.buildClient)(config.baseUrl);

this.errorReporter = config.errorReporter;
this.tempFilePathResolver = config.tempFilePathResolver ?? exports.defaultTempFilePathResolver;
if (config.createDefaultContentDirectory !== false) {
const filePath = (0, tmp_1.tmpNameSync)({
dir: DEFAULT_UPLOAD_FILES_SUBDIR,
});
const dirPath = (0, node_path_1.dirname)(filePath);
if (!(0, node_fs_1.existsSync)(dirPath)) {
(0, node_fs_1.mkdirSync)(dirPath, { recursive: true });
}
}
}

@@ -23,2 +54,15 @@ async uploadFile(ownerId, useCase, fileData, contentHeaders, requestContext) {

return { error: uploadUrlResponse.error };
let contentToSend = fileData.file;
let contentLength = undefined;
let contentProvider;
// This is necessary because S3 requires 'Content-Length' header for streams
if (isReadableStream(fileData.file)) {
const tempFilePath = await this.tempFilePathResolver(fileData);
contentProvider = await node_core_1.FsReadableProvider.persistReadableToFs({
sourceReadable: fileData.file,
targetFile: tempFilePath,
});
contentLength = await contentProvider.getContentLength();
contentToSend = await contentProvider.createStream();
}
const headers = (0, node_core_1.copyWithoutUndefined)({

@@ -28,2 +72,3 @@ 'Content-Type': contentHeaders.contentType,

'Content-Disposition': contentHeaders.contentDisposition,
'Content-Length': contentLength,
});

@@ -34,3 +79,3 @@ const uploadUrlObject = new URL(uploadUrlResponse.result.uploadUrl);

// eslint-disable-next-line @typescript-eslint/no-unsafe-argument,@typescript-eslint/no-unsafe-call
(0, node_core_1.buildClient)(uploadBaseUrl), uploadUrlObject.pathname, fileData.file, {
(0, node_core_1.buildClient)(uploadBaseUrl), uploadUrlObject.pathname, contentToSend, {
headers,

@@ -41,2 +86,5 @@ safeParseJson: true,

});
if (contentProvider) {
await contentProvider.destroy();
}
if (response.error) {

@@ -43,0 +91,0 @@ this.maybeReportWithErrorReporter(response.error);

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const node_stream_1 = require("node:stream");
const mockttp_1 = require("mockttp");

@@ -80,2 +81,34 @@ const testFs_1 = require("../../test/fixtures/testFs");

});
it('Attempts to upload a file as a Readable correctly', async () => {
expect.assertions(3);
const uploadHost = 'http://localhost:8086';
const uploadPath = '/upload-files-here';
const uploadUrl = `${uploadHost}${uploadPath}`;
const fileId = 777;
const postReply = {
data: {
uploadUrl,
fileId,
},
};
await mockServer.forPost(testStorageClient_1.uploadInterceptData.path).thenReply(200, JSON.stringify(postReply), {
'content-type': 'application/json',
});
await mockStorageServer.forPut(uploadPath).thenCallback((req) => {
expect(req.headers).toEqual({
connection: 'keep-alive',
'content-length': '22',
'content-type': 'application/json',
host: expect.any(String),
});
return { statusCode: 200 };
});
await expect(fileStorageClient.uploadFile(testFs_1.FS_TEST_DATA.PROJECT_ID, 'import', {
...testFs_1.FS_TEST_DATA.FILE_DESCRIPTION,
file: node_stream_1.Readable.from(node_stream_1.Readable.from(testFs_1.FS_TEST_DATA.FILE_DESCRIPTION.file.toString())),
}, {
contentType: 'application/json',
}, testFs_1.FS_TEST_DATA.REQUEST_CONTEXT)).resolves.toEqual({ result: fileId });
expect(reportFunction).not.toHaveBeenCalled();
});
it('Attempts to upload a file correctly with query params', async () => {

@@ -82,0 +115,0 @@ const uploadHost = 'http://localhost:8086';

@@ -67,4 +67,4 @@ import z from 'zod';

}, "strip", z.ZodTypeAny, {
filename: string;
status: "uploading" | "uploaded" | "deleting" | "deleted";
filename: string;
mimeType: string;

@@ -76,4 +76,4 @@ metadata: {} & {

}, {
filename: string;
status: "uploading" | "uploaded" | "deleting" | "deleted";
filename: string;
mimeType: string;

@@ -87,4 +87,4 @@ metadata: {} & {

data: {
filename: string;
status: "uploading" | "uploaded" | "deleting" | "deleted";
filename: string;
mimeType: string;

@@ -98,4 +98,4 @@ metadata: {} & {

data: {
filename: string;
status: "uploading" | "uploaded" | "deleting" | "deleted";
filename: string;
mimeType: string;

@@ -102,0 +102,0 @@ metadata: {} & {

{
"name": "@lokalise/file-storage-service-sdk",
"version": "6.1.0",
"version": "6.2.0",
"description": "SDK for file-storage-service",

@@ -43,31 +43,30 @@ "author": {

"test:ci": "npm run lint && npm run test:coverage",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"format": "prettier --write .",
"lint": "eslint . --cache --max-warnings=0 && prettier --check --log-level warn lib test \"**/*.{json,md}\" && tsc --noEmit",
"lint:fix": "eslint . --fix && prettier --write lib test \"**/*.{json,md}\"",
"version": "auto-changelog -p && git add CHANGELOG.md"
},
"dependencies": {
"@lokalise/node-core": "^9.0.0",
"@lokalise/zod-extras": "^1.3.1",
"undici": "^6.0.1",
"zod": "^3.19.1"
"@lokalise/node-core": "^9.22.0",
"@lokalise/zod-extras": "^2.1.0",
"tmp": "^0.2.3",
"undici": "^6.18.2",
"zod": "^3.23.8"
},
"devDependencies": {
"@types/jest": "^29.4.0",
"@types/node": "^18.13.0",
"@typescript-eslint/eslint-plugin": "^6.6.0",
"@typescript-eslint/parser": "^6.6.0",
"@types/node": "^20.13.0",
"@types/tmp": "^0.2.6",
"@typescript-eslint/eslint-plugin": "^7.11.0",
"@typescript-eslint/parser": "^7.11.0",
"auto-changelog": "^2.4.0",
"eslint": "^8.34.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-jest": "^27.2.1",
"eslint-plugin-prettier": "^4.2.1",
"jest": "^29.4.3",
"mockttp": "^3.6.3",
"prettier": "^2.8.4",
"eslint": "^8.57.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jest": "^28.5.0",
"jest": "^29.7.0",
"mockttp": "^3.11.0",
"prettier": "^3.3.0",
"shx": "^0.3.4",
"ts-jest": "^29.0.5",
"ts-node": "^10.9.1",
"typescript": "5.3.3"
"ts-jest": "^29.1.4",
"ts-node": "^10.9.2",
"typescript": "5.4.5"
},

@@ -74,0 +73,0 @@ "engines": {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet