Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

fastify-txstate

Package Overview
Dependencies
Maintainers
3
Versions
78
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fastify-txstate - npm Package Compare versions

Comparing version
3.6.7
to
3.6.8
+31
lib/filestorage.d.ts
import { type Readable } from 'stream';
export interface FileHandler {
init: () => Promise<void>;
put: (stream: Readable) => Promise<{
checksum: string;
size: number;
}>;
get: (checksum: string) => Readable;
remove: (checksum: string) => Promise<void>;
}
export declare class FileSystemHandler implements FileHandler {
#private;
options: {
tmpdir: string;
permdir: string;
};
constructor(options?: {
tmpdir?: string;
permdir?: string;
});
init(): Promise<void>;
get(checksum: string): import("fs").ReadStream;
exists(checksum: string): Promise<boolean>;
fileSize(checksum: string): Promise<number>;
put(stream: Readable): Promise<{
checksum: string;
size: number;
}>;
remove(checksum: string): Promise<void>;
}
export declare const fileHandler: FileSystemHandler;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.fileHandler = exports.FileSystemHandler = void 0;
const crypto_1 = require("crypto");
const fs_1 = require("fs");
const promises_1 = require("fs/promises");
const path_1 = require("path");
const promises_2 = require("stream/promises");
const txstate_utils_1 = require("txstate-utils");
class FileSystemHandler {
options;
constructor(options = {}) {
this.options = {
tmpdir: options.tmpdir ?? '/files/tmp/',
permdir: options.permdir ?? '/files/storage/'
};
if (!this.options.tmpdir.endsWith('/'))
this.options.tmpdir += '/';
if (!this.options.permdir.endsWith('/'))
this.options.permdir += '/';
}
#getTmpLocation() {
return `${this.options.tmpdir}${(0, txstate_utils_1.randomid)(12)}`;
}
#getFileLocation(checksum) {
return `${this.options.permdir}${checksum.slice(0, 1)}/${checksum.slice(1, 2)}/${checksum.slice(2)}`;
}
async #moveToPerm(tmp, checksum) {
const checksumpath = this.#getFileLocation(checksum);
await (0, promises_1.mkdir)((0, path_1.dirname)(checksumpath), { recursive: true });
await (0, promises_1.rename)(tmp, checksumpath);
}
async init() {
await (0, promises_1.mkdir)(this.options.tmpdir, { recursive: true });
await (0, promises_1.mkdir)(this.options.permdir, { recursive: true });
}
get(checksum) {
const filepath = this.#getFileLocation(checksum);
const stream = (0, fs_1.createReadStream)(filepath);
return stream;
}
async exists(checksum) {
const filepath = this.#getFileLocation(checksum);
return (await (0, txstate_utils_1.rescue)((0, promises_1.access)(filepath, promises_1.constants.R_OK), false)) ?? true;
}
async fileSize(checksum) {
const filepath = this.#getFileLocation(checksum);
const info = await (0, promises_1.stat)(filepath);
return info.size;
}
async put(stream) {
const tmp = this.#getTmpLocation();
const hash = (0, crypto_1.createHash)('sha256');
let size = 0;
stream.on('data', (data) => { hash.update(data); size += data.length; });
try {
const out = (0, fs_1.createWriteStream)(tmp);
const flushedPromise = new Promise((resolve, reject) => {
out.on('close', resolve);
out.on('error', reject);
});
await (0, promises_2.pipeline)(stream, out);
await flushedPromise;
const checksum = hash.digest('base64url');
const rereadhash = (0, crypto_1.createHash)('sha256');
const read = (0, fs_1.createReadStream)(tmp);
for await (const chunk of read) {
rereadhash.update(chunk);
}
const rereadsum = rereadhash.digest('base64url');
if (rereadsum !== checksum)
throw new Error('File did not write to disk correctly. Please try uploading again.');
await this.#moveToPerm(tmp, checksum);
return { checksum, size };
}
catch (e) {
await (0, txstate_utils_1.rescue)((0, promises_1.unlink)(tmp));
throw e;
}
}
async remove(checksum) {
const filepath = this.#getFileLocation(checksum);
try {
await (0, promises_1.unlink)(filepath);
}
catch (e) {
if (e.code === 'ENOENT')
console.warn('Tried to delete file with checksum', checksum, 'but it did not exist.');
else
console.warn(e);
}
}
}
exports.FileSystemHandler = FileSystemHandler;
exports.fileHandler = new FileSystemHandler();
+2
-0

@@ -18,2 +18,4 @@ import ftxst from '../lib/index.js'

export const readableToWebReadable = ftxst.readableToWebReadable
export const FileSystemHandler = ftxst.FileSystemHandler
export const fileHandler = ftxst.fileHandler
export default ftxst.default

@@ -192,3 +192,4 @@ import { type FastifyDynamicSwaggerOptions } from '@fastify/swagger';

export * from './error';
export * from './filestorage';
export * from './unified-auth';
export * from './postformdata';

@@ -420,3 +420,4 @@ "use strict";

__exportStar(require("./error"), exports);
__exportStar(require("./filestorage"), exports);
__exportStar(require("./unified-auth"), exports);
__exportStar(require("./postformdata"), exports);
+2
-2
{
"name": "fastify-txstate",
"version": "3.6.7",
"version": "3.6.8",
"description": "A small wrapper for fastify providing a set of common conventions & utility functions we use.",

@@ -40,3 +40,3 @@ "exports": {

"@types/mocha": "^10.0.0",
"@types/node": "^22.0.0",
"@types/node": "^24.0.0",
"axios": "^1.6.8",

@@ -43,0 +43,0 @@ "chai": "^4.2.0",