Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@tus/server

Package Overview
Dependencies
Maintainers
3
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tus/server - npm Package Compare versions

Comparing version 1.3.0 to 1.4.0

8

dist/handlers/BaseHandler.d.ts

@@ -5,5 +5,5 @@ /// <reference types="node" />

import type { ServerOptions } from '../types';
import type { DataStore, CancellationContext } from '../models';
import type { DataStore, CancellationContext } from '@tus/utils';
import type http from 'node:http';
import { Upload } from '../models';
import { Upload } from '@tus/utils';
export declare class BaseHandler extends EventEmitter {

@@ -20,4 +20,4 @@ options: ServerOptions;

};
protected getLocker(req: http.IncomingMessage): Promise<import("../models").Locker>;
protected acquireLock(req: http.IncomingMessage, id: string, context: CancellationContext): Promise<import("../models").Lock>;
protected getLocker(req: http.IncomingMessage): Promise<import("@tus/utils").Locker>;
protected acquireLock(req: http.IncomingMessage, id: string, context: CancellationContext): Promise<import("@tus/utils").Lock>;
protected writeToStore(req: http.IncomingMessage, id: string, offset: number, maxFileSize: number, context: CancellationContext): Promise<number>;

@@ -24,0 +24,0 @@ getConfiguredMaxSize(req: http.IncomingMessage, id: string | null): number | Promise<number>;

@@ -8,6 +8,5 @@ "use strict";

const node_events_1 = __importDefault(require("node:events"));
const constants_1 = require("../constants");
const utils_1 = require("@tus/utils");
const promises_1 = __importDefault(require("node:stream/promises"));
const stream_1 = require("stream");
const StreamLimiter_1 = require("../models/StreamLimiter");
const reExtractFileID = /([^/]+)\/?$/;

@@ -102,3 +101,3 @@ const reForwardedHost = /host="?([^";]+)/;

if (context.signal.aborted) {
reject(constants_1.ERRORS.ABORTED);
reject(utils_1.ERRORS.ABORTED);
return;

@@ -112,7 +111,9 @@ }

req.unpipe(proxy);
reject(err.name === 'AbortError' ? constants_1.ERRORS.ABORTED : err);
reject(err.name === 'AbortError' ? utils_1.ERRORS.ABORTED : err);
});
req.on('error', (err) => {
req.on('error', () => {
if (!proxy.closed) {
proxy.destroy(err);
// we end the stream gracefully here so that we can upload the remaining bytes to the store
// as an incompletePart
proxy.end();
}

@@ -124,3 +125,3 @@ });

promises_1.default
.pipeline(req.pipe(proxy), new StreamLimiter_1.StreamLimiter(maxFileSize), async (stream) => {
.pipeline(req.pipe(proxy), new utils_1.StreamLimiter(maxFileSize), async (stream) => {
return this.store.write(stream, id, offset);

@@ -156,3 +157,3 @@ })

offset + length > configuredMaxSize) {
throw constants_1.ERRORS.ERR_SIZE_EXCEEDED;
throw utils_1.ERRORS.ERR_SIZE_EXCEEDED;
}

@@ -168,3 +169,3 @@ if (hasConfiguredMaxSizeSet) {

if (offset + length > (file.size || 0)) {
throw constants_1.ERRORS.ERR_SIZE_EXCEEDED;
throw utils_1.ERRORS.ERR_SIZE_EXCEEDED;
}

@@ -171,0 +172,0 @@ if (hasContentLengthSet) {

/// <reference types="node" />
import { BaseHandler } from './BaseHandler';
import { CancellationContext } from '../models';
import { CancellationContext } from '@tus/utils';
import type http from 'node:http';

@@ -5,0 +5,0 @@ export declare class DeleteHandler extends BaseHandler {

@@ -5,3 +5,3 @@ "use strict";

const BaseHandler_1 = require("./BaseHandler");
const constants_1 = require("../constants");
const utils_1 = require("@tus/utils");
class DeleteHandler extends BaseHandler_1.BaseHandler {

@@ -11,3 +11,3 @@ async send(req, res, context) {

if (!id) {
throw constants_1.ERRORS.FILE_NOT_FOUND;
throw utils_1.ERRORS.FILE_NOT_FOUND;
}

@@ -22,3 +22,3 @@ if (this.options.onIncomingRequest) {

if (upload.offset === upload.size) {
throw constants_1.ERRORS.INVALID_TERMINATION;
throw utils_1.ERRORS.INVALID_TERMINATION;
}

@@ -32,3 +32,3 @@ }

const writtenRes = this.write(res, 204, {});
this.emit(constants_1.EVENTS.POST_TERMINATE, req, writtenRes, id);
this.emit(utils_1.EVENTS.POST_TERMINATE, req, writtenRes, id);
return writtenRes;

@@ -35,0 +35,0 @@ }

@@ -9,3 +9,3 @@ "use strict";

const BaseHandler_1 = require("./BaseHandler");
const constants_1 = require("../constants");
const utils_1 = require("@tus/utils");
class GetHandler extends BaseHandler_1.BaseHandler {

@@ -30,7 +30,7 @@ constructor() {

if (!('read' in this.store)) {
throw constants_1.ERRORS.FILE_NOT_FOUND;
throw utils_1.ERRORS.FILE_NOT_FOUND;
}
const id = this.getFileIdFromRequest(req);
if (!id) {
throw constants_1.ERRORS.FILE_NOT_FOUND;
throw utils_1.ERRORS.FILE_NOT_FOUND;
}

@@ -42,3 +42,3 @@ if (this.options.onIncomingRequest) {

if (!stats || stats.offset !== stats.size) {
throw constants_1.ERRORS.FILE_NOT_FOUND;
throw utils_1.ERRORS.FILE_NOT_FOUND;
}

@@ -45,0 +45,0 @@ // @ts-expect-error exists if supported

/// <reference types="node" />
import { BaseHandler } from './BaseHandler';
import { CancellationContext } from '../models';
import { CancellationContext } from '@tus/utils';
import type http from 'node:http';

@@ -5,0 +5,0 @@ export declare class HeadHandler extends BaseHandler {

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

const BaseHandler_1 = require("./BaseHandler");
const constants_1 = require("../constants");
const models_1 = require("../models");
const utils_1 = require("@tus/utils");
class HeadHandler extends BaseHandler_1.BaseHandler {

@@ -12,3 +11,3 @@ async send(req, res, context) {

if (!id) {
throw constants_1.ERRORS.FILE_NOT_FOUND;
throw utils_1.ERRORS.FILE_NOT_FOUND;
}

@@ -35,3 +34,3 @@ if (this.options.onIncomingRequest) {

now > new Date(new Date(file.creation_date).getTime() + this.store.getExpiration())) {
throw constants_1.ERRORS.FILE_NO_LONGER_EXISTS;
throw utils_1.ERRORS.FILE_NO_LONGER_EXISTS;
}

@@ -59,3 +58,3 @@ // The Server MUST prevent the client and/or proxies from

// as specified by the Client during the creation.
res.setHeader('Upload-Metadata', models_1.Metadata.stringify(file.metadata));
res.setHeader('Upload-Metadata', utils_1.Metadata.stringify(file.metadata));
}

@@ -62,0 +61,0 @@ return res.end();

@@ -5,3 +5,3 @@ "use strict";

const BaseHandler_1 = require("./BaseHandler");
const constants_1 = require("../constants");
const utils_1 = require("@tus/utils");
// A successful response indicated by the 204 No Content status MUST contain

@@ -15,6 +15,6 @@ // the Tus-Version header. It MAY include the Tus-Extension and Tus-Max-Size headers.

}
const allowedHeaders = [...constants_1.HEADERS, ...(this.options.allowedHeaders ?? [])];
res.setHeader('Access-Control-Allow-Methods', constants_1.ALLOWED_METHODS);
const allowedHeaders = [...utils_1.HEADERS, ...(this.options.allowedHeaders ?? [])];
res.setHeader('Access-Control-Allow-Methods', utils_1.ALLOWED_METHODS);
res.setHeader('Access-Control-Allow-Headers', allowedHeaders.join(', '));
res.setHeader('Access-Control-Max-Age', constants_1.MAX_AGE);
res.setHeader('Access-Control-Max-Age', utils_1.MAX_AGE);
if (this.store.extensions.length > 0) {

@@ -21,0 +21,0 @@ res.setHeader('Tus-Extension', this.store.extensions.join(','));

/// <reference types="node" />
import { BaseHandler } from './BaseHandler';
import type http from 'node:http';
import { CancellationContext } from '../models';
import { CancellationContext } from '@tus/utils';
export declare class PatchHandler extends BaseHandler {

@@ -6,0 +6,0 @@ /**

@@ -9,3 +9,3 @@ "use strict";

const BaseHandler_1 = require("./BaseHandler");
const constants_1 = require("../constants");
const utils_1 = require("@tus/utils");
const log = (0, debug_1.default)('tus-node-server:handlers:patch');

@@ -20,7 +20,7 @@ class PatchHandler extends BaseHandler_1.BaseHandler {

if (!id) {
throw constants_1.ERRORS.FILE_NOT_FOUND;
throw utils_1.ERRORS.FILE_NOT_FOUND;
}
// The request MUST include a Upload-Offset header
if (req.headers['upload-offset'] === undefined) {
throw constants_1.ERRORS.MISSING_OFFSET;
throw utils_1.ERRORS.MISSING_OFFSET;
}

@@ -31,3 +31,3 @@ const offset = Number.parseInt(req.headers['upload-offset'], 10);

if (content_type === undefined) {
throw constants_1.ERRORS.INVALID_CONTENT_TYPE;
throw utils_1.ERRORS.INVALID_CONTENT_TYPE;
}

@@ -55,3 +55,3 @@ if (this.options.onIncomingRequest) {

now > expiration) {
throw constants_1.ERRORS.FILE_NO_LONGER_EXISTS;
throw utils_1.ERRORS.FILE_NO_LONGER_EXISTS;
}

@@ -61,3 +61,3 @@ if (upload.offset !== offset) {

log(`[PatchHandler] send: Incorrect offset - ${offset} sent but file is ${upload.offset}`);
throw constants_1.ERRORS.INVALID_OFFSET;
throw utils_1.ERRORS.INVALID_OFFSET;
}

@@ -70,13 +70,13 @@ // The request MUST validate upload-length related headers

if (!this.store.hasExtension('creation-defer-length')) {
throw constants_1.ERRORS.UNSUPPORTED_CREATION_DEFER_LENGTH_EXTENSION;
throw utils_1.ERRORS.UNSUPPORTED_CREATION_DEFER_LENGTH_EXTENSION;
}
// Throw error if upload-length is already set.
if (upload.size !== undefined) {
throw constants_1.ERRORS.INVALID_LENGTH;
throw utils_1.ERRORS.INVALID_LENGTH;
}
if (size < upload.offset) {
throw constants_1.ERRORS.INVALID_LENGTH;
throw utils_1.ERRORS.INVALID_LENGTH;
}
if (maxFileSize > 0 && size > maxFileSize) {
throw constants_1.ERRORS.ERR_MAX_SIZE_EXCEEDED;
throw utils_1.ERRORS.ERR_MAX_SIZE_EXCEEDED;
}

@@ -93,3 +93,3 @@ await this.store.declareUploadLength(id, size);

upload.offset = newOffset;
this.emit(constants_1.EVENTS.POST_RECEIVE, req, res, upload);
this.emit(utils_1.EVENTS.POST_RECEIVE, req, res, upload);
if (newOffset === upload.size && this.options.onUploadFinish) {

@@ -119,3 +119,3 @@ try {

if (newOffset === upload.size) {
this.emit(constants_1.EVENTS.POST_FINISH, req, writtenRes, upload);
this.emit(utils_1.EVENTS.POST_FINISH, req, writtenRes, upload);
}

@@ -122,0 +122,0 @@ return writtenRes;

/// <reference types="node" />
import { BaseHandler } from './BaseHandler';
import { DataStore, CancellationContext } from '@tus/utils';
import type http from 'node:http';
import type { ServerOptions, WithRequired } from '../types';
import { DataStore, CancellationContext } from '../models';
export declare class PostHandler extends BaseHandler {

@@ -7,0 +7,0 @@ options: WithRequired<ServerOptions, 'namingFunction'>;

@@ -9,5 +9,4 @@ "use strict";

const BaseHandler_1 = require("./BaseHandler");
const models_1 = require("../models");
const utils_1 = require("@tus/utils");
const HeaderValidator_1 = require("../validators/HeaderValidator");
const constants_1 = require("../constants");
const log = (0, debug_1.default)('tus-node-server:handlers:post');

@@ -20,3 +19,3 @@ class PostHandler extends BaseHandler_1.BaseHandler {

if (!options.namingFunction) {
options.namingFunction = models_1.Uid.rand;
options.namingFunction = utils_1.Uid.rand;
}

@@ -30,3 +29,3 @@ super(store, options);

if ('upload-concat' in req.headers && !this.store.hasExtension('concatentation')) {
throw constants_1.ERRORS.UNSUPPORTED_CONCATENATION_EXTENSION;
throw utils_1.ERRORS.UNSUPPORTED_CONCATENATION_EXTENSION;
}

@@ -38,6 +37,6 @@ const upload_length = req.headers['upload-length'];

!this.store.hasExtension('creation-defer-length')) {
throw constants_1.ERRORS.UNSUPPORTED_CREATION_DEFER_LENGTH_EXTENSION;
throw utils_1.ERRORS.UNSUPPORTED_CREATION_DEFER_LENGTH_EXTENSION;
}
if ((upload_length === undefined) === (upload_defer_length === undefined)) {
throw constants_1.ERRORS.INVALID_LENGTH;
throw utils_1.ERRORS.INVALID_LENGTH;
}

@@ -47,6 +46,6 @@ let metadata;

try {
metadata = models_1.Metadata.parse(upload_metadata);
metadata = utils_1.Metadata.parse(upload_metadata);
}
catch {
throw constants_1.ERRORS.INVALID_METADATA;
throw utils_1.ERRORS.INVALID_METADATA;
}

@@ -56,3 +55,3 @@ }

try {
id = this.options.namingFunction(req, metadata);
id = await this.options.namingFunction(req, metadata);
}

@@ -67,3 +66,3 @@ catch (error) {

Number.parseInt(upload_length, 10) > maxFileSize) {
throw constants_1.ERRORS.ERR_MAX_SIZE_EXCEEDED;
throw utils_1.ERRORS.ERR_MAX_SIZE_EXCEEDED;
}

@@ -73,3 +72,3 @@ if (this.options.onIncomingRequest) {

}
const upload = new models_1.Upload({
const upload = new utils_1.Upload({
id,

@@ -96,3 +95,3 @@ size: upload_length ? Number.parseInt(upload_length, 10) : undefined,

url = this.generateUrl(req, upload.id);
this.emit(constants_1.EVENTS.POST_CREATE, req, res, upload, url);
this.emit(utils_1.EVENTS.POST_CREATE, req, res, upload, url);
isFinal = upload.size === 0 && !upload.sizeIsDeferred;

@@ -139,3 +138,3 @@ headers = {};

if (isFinal) {
this.emit(constants_1.EVENTS.POST_FINISH, req, writtenRes, upload);
this.emit(utils_1.EVENTS.POST_FINISH, req, writtenRes, upload);
}

@@ -142,0 +141,0 @@ return writtenRes;

export { Server } from './server';
export * from './types';
export * from './models';
export * from './lockers';
export * from './constants';
export * from './kvstores';
export * from '@tus/utils';

@@ -21,5 +21,3 @@ "use strict";

__exportStar(require("./types"), exports);
__exportStar(require("./models"), exports);
__exportStar(require("./lockers"), exports);
__exportStar(require("./constants"), exports);
__exportStar(require("./kvstores"), exports);
__exportStar(require("@tus/utils"), exports);
/// <reference types="node" />
import { Lock, Locker, RequestRelease } from '../models';
import { Lock, Locker, RequestRelease } from '@tus/utils';
/**

@@ -4,0 +4,0 @@ * MemoryLocker is an implementation of the Locker interface that manages locks in memory.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MemoryLocker = void 0;
const constants_1 = require("../constants");
const utils_1 = require("@tus/utils");
class MemoryLocker {

@@ -29,3 +29,3 @@ constructor(options) {

if (!lock) {
throw constants_1.ERRORS.ERR_LOCK_TIMEOUT;
throw utils_1.ERRORS.ERR_LOCK_TIMEOUT;
}

@@ -32,0 +32,0 @@ }

@@ -13,6 +13,6 @@ /// <reference types="node" />

import { DeleteHandler } from './handlers/DeleteHandler';
import { EVENTS } from './constants';
import { EVENTS } from '@tus/utils';
import type stream from 'node:stream';
import type { ServerOptions, RouteHandler, WithOptional } from './types';
import type { DataStore, Upload, CancellationContext } from './models';
import type { DataStore, Upload, CancellationContext } from '@tus/utils';
type Handlers = {

@@ -19,0 +19,0 @@ GET: InstanceType<typeof GetHandler>;

@@ -17,3 +17,3 @@ "use strict";

const HeaderValidator_1 = require("./validators/HeaderValidator");
const constants_1 = require("./constants");
const utils_1 = require("@tus/utils");
const lockers_1 = require("./lockers");

@@ -58,3 +58,3 @@ const log = (0, debug_1.default)('tus-node-server');

this.datastore.removeListener(event, listener);
for (const method of constants_1.REQUEST_METHODS) {
for (const method of utils_1.REQUEST_METHODS) {
this.handlers[method].removeListener(event, listener);

@@ -67,3 +67,3 @@ }

this.datastore.on(event, listener);
for (const method of constants_1.REQUEST_METHODS) {
for (const method of utils_1.REQUEST_METHODS) {
this.handlers[method].on(event, listener);

@@ -91,4 +91,4 @@ }

const onError = async (error) => {
let status_code = error.status_code || constants_1.ERRORS.UNKNOWN_ERROR.status_code;
let body = error.body || `${constants_1.ERRORS.UNKNOWN_ERROR.body}${error.message || ''}\n`;
let status_code = error.status_code || utils_1.ERRORS.UNKNOWN_ERROR.status_code;
let body = error.body || `${utils_1.ERRORS.UNKNOWN_ERROR.body}${error.message || ''}\n`;
if (this.options.onResponseError) {

@@ -110,3 +110,3 @@ const errorMapping = await this.options.onResponseError(req, res, error);

// of the protocol used by the Client or the Server.
res.setHeader('Tus-Resumable', constants_1.TUS_RESUMABLE);
res.setHeader('Tus-Resumable', utils_1.TUS_RESUMABLE);
if (req.method !== 'OPTIONS' && req.headers['tus-resumable'] === undefined) {

@@ -138,3 +138,3 @@ return this.write(context, req, res, 412, 'Tus-Resumable Required\n');

// Enable CORS
res.setHeader('Access-Control-Expose-Headers', constants_1.EXPOSED_HEADERS);
res.setHeader('Access-Control-Expose-Headers', utils_1.EXPOSED_HEADERS);
if (req.headers.origin) {

@@ -183,3 +183,3 @@ res.setHeader('Access-Control-Allow-Origin', req.headers.origin);

if (!this.datastore.hasExtension('expiration')) {
throw constants_1.ERRORS.UNSUPPORTED_EXPIRATION_EXTENSION;
throw utils_1.ERRORS.UNSUPPORTED_EXPIRATION_EXTENSION;
}

@@ -210,3 +210,3 @@ return this.datastore.deleteExpired();

if (!requestAbortController.signal.aborted) {
requestAbortController.abort(constants_1.ERRORS.ABORTED);
requestAbortController.abort(utils_1.ERRORS.ABORTED);
}

@@ -217,3 +217,3 @@ },

if (!abortWithDelayController.signal.aborted) {
abortWithDelayController.abort(constants_1.ERRORS.ABORTED);
abortWithDelayController.abort(utils_1.ERRORS.ABORTED);
}

@@ -220,0 +220,0 @@ },

/// <reference types="node" />
import type http from 'node:http';
import type { Locker, Upload } from './models';
import type { Locker, Upload } from '@tus/utils';
/**

@@ -52,3 +52,3 @@ * Represents the configuration options for a server.

*/
namingFunction?: (req: http.IncomingMessage, metadata?: Record<string, string | null>) => string;
namingFunction?: (req: http.IncomingMessage, metadata?: Record<string, string | null>) => string | Promise<string>;
/**

@@ -55,0 +55,0 @@ * The Lock interface defines methods for implementing a locking mechanism.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateHeader = exports.validators = void 0;
const constants_1 = require("../constants");
const models_1 = require("../models");
const utils_1 = require("@tus/utils");
exports.validators = new Map([

@@ -43,3 +42,3 @@ [

try {
models_1.Metadata.parse(value);
utils_1.Metadata.parse(value);
return true;

@@ -67,3 +66,3 @@ }

// @ts-expect-error we can compare a literal
return constants_1.TUS_VERSION.includes(value);
return utils_1.TUS_VERSION.includes(value);
},

@@ -79,3 +78,3 @@ ],

function (value) {
return value === constants_1.TUS_RESUMABLE;
return value === utils_1.TUS_RESUMABLE;
},

@@ -82,0 +81,0 @@ ],

{
"$schema": "https://json.schemastore.org/package.json",
"name": "@tus/server",
"version": "1.3.0",
"version": "1.4.0",
"description": "Tus resumable upload protocol in Node.js",

@@ -24,2 +24,3 @@ "main": "dist/index.js",

"dependencies": {
"@tus/utils": "workspace:*",
"debug": "^4.3.4"

@@ -34,3 +35,3 @@ },

"eslint": "^8.56.0",
"eslint-config-custom": "0.0.0",
"eslint-config-custom": "workspace:*",
"mocha": "^10.2.0",

@@ -42,3 +43,2 @@ "node-mocks-http": "^1.14.1",

"ts-node": "^10.9.2",
"tsconfig": "*",
"typescript": "^5.3.3"

@@ -52,2 +52,2 @@ },

}
}
}

@@ -107,3 +107,3 @@ # `@tus/server`

Control how you want to name files (`(req, metadata) => string`)
Control how you want to name files (`(req, metadata) => string | Promise<string>`)

@@ -110,0 +110,0 @@ In `@tus/server`, the upload ID in the URL is the same as the file name.

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc