npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dilnaka

v0.0.3

Published

TypeScript SDK for Dilnaka file uploads

Readme

Dilnaka TypeScript SDK

TypeScript SDK for uploading files through the Dilnaka Upload API.

The SDK uses the fixed Dilnaka API base URL https://dilnaka.storage.tsnc.tech. It reads the API key and timeout from explicit constructor options first, then environment variables. It requests a presigned S3 upload URL from your Dilnaka backend, uploads the file directly to S3, and calls the completion endpoint.

Small files use a single presigned PUT. Large files (at or above multipartThreshold, 100 MB by default) automatically use a resumable S3 multipart upload that streams the file in chunks and retries a failed part instead of discarding the whole transfer.

Install

npm install dilnaka

Configure

You can pass configuration directly to new Dilnaka(...), or set environment variables for your application.

Configuration precedence is:

  1. Explicit constructor options such as new Dilnaka({ apiKey: "...", timeout: 30 })
  2. Existing process environment variables such as DILNAKA_TIMEOUT
  3. Values loaded from .env
  4. Built-in defaults

If you use a .env file, create it in your application project:

DILNAKA_API_KEY=dlk_dev_your_api_key_here
DILNAKA_TIMEOUT=60
DILNAKA_MULTIPART_THRESHOLD=104857600
DILNAKA_UPLOAD_TIMEOUT=300

The SDK always uses https://dilnaka.storage.tsnc.tech as its base URL.

  • DILNAKA_TIMEOUT (default 60): timeout in seconds for JSON API calls (presign, complete, list, etc.).
  • DILNAKA_MULTIPART_THRESHOLD (default 104857600, i.e. 100 MB): files at or above this size use the multipart flow.
  • DILNAKA_UPLOAD_TIMEOUT (default 300): per-request transfer timeout in seconds for the single PUT or each multipart part. This is deliberately larger than DILNAKA_TIMEOUT so large chunks over slow links do not time out.

Basic upload

import { Dilnaka } from "dilnaka";

const client = new Dilnaka();

const uploaded = await client.upload("./test-upload.txt");

console.log(uploaded.id);
console.log(uploaded.key);
console.log(uploaded.status);

Explicit configuration

import { Dilnaka } from "dilnaka";

const client = new Dilnaka({
  apiKey: "dlk_dev_your_api_key_here"
});

const uploaded = await client.upload("./avatar.png", {
  folder: "avatars"
});

console.log(uploaded);

Large file uploads

upload(...) picks the transfer strategy automatically based on file size, so the call is identical for small and large files:

import { Dilnaka } from "dilnaka";

const client = new Dilnaka();

// Uses multipart automatically when the file is >= the threshold (100 MB default).
const uploaded = await client.upload("./course-bundle.zip");
console.log(uploaded.id, uploaded.status);

You can tune the behavior per call or per client:

// Force multipart for anything over 25 MB and give each part 10 minutes.
const uploaded = await client.upload("./course-bundle.zip", {
  multipartThreshold: 25 * 1024 * 1024,
  uploadTimeout: 600
});

The lower-level multipart methods are also available if you need direct control: createMultipartUpload(...), presignMultipartParts(...), completeMultipartUpload(...), and abortMultipartUpload(...). A failed multipart transfer is aborted automatically so it does not leave a dangling upload on the bucket.

Request a file access URL

Use getFileAccessUrl(...) when you need a URL for downloading or opening a file.

import { Dilnaka } from "dilnaka";

const client = new Dilnaka();

const access = await client.getFileAccessUrl("file_123");

console.log(access.fileId);
console.log(access.url);
console.log(access.expiresIn);
console.log(access.isTemporary);

Pass expiresIn to request a temporary URL from the backend:

const temporaryAccess = await client.getFileAccessUrl("file_123", 600);

console.log(temporaryAccess.url);
console.log(temporaryAccess.expiresIn);   // 600
console.log(temporaryAccess.isTemporary); // true

expiresIn must be greater than 0. If you omit it, the SDK requests the default access URL returned by your backend.

The method returns a FileAccessUrl object with:

  • fileId: Dilnaka file ID
  • url: Access URL returned by the API
  • expiresIn: Expiration time in seconds when the backend returns a temporary URL
  • isTemporary: true when the backend marks the URL as temporary, or when an expiration is present

API

const client = new Dilnaka({
  apiKey?: string;
  timeout?: number;
  envFile?: string;
  fetch?: typeof fetch;
  multipartThreshold?: number;
  uploadTimeout?: number;
});

Available methods:

  • upload(filePath, options?)
  • createPresignedUpload(options)
  • completeUpload(fileId)
  • createMultipartUpload(options)
  • presignMultipartParts(fileId, partNumbers)
  • completeMultipartUpload(fileId, parts)
  • abortMultipartUpload(fileId)
  • listFiles()
  • getFile(fileId)
  • getFileAccessUrl(fileId, expiresIn?)
  • deleteFile(fileId)

Python-style aliases are also available for migration convenience:

  • create_presigned_upload(...)
  • complete_upload(...)
  • create_multipart_upload(...)
  • presign_multipart_parts(...)
  • complete_multipart_upload(...)
  • abort_multipart_upload(...)
  • list_files()
  • get_file(...)
  • get_file_access_url(...)
  • delete_file(...)

Expected backend endpoints

The SDK expects your Caspian backend to expose:

POST /v1/uploads/presign
POST /v1/uploads/complete
POST /v1/uploads/multipart/create
POST /v1/uploads/multipart/parts
POST /v1/uploads/multipart/complete
POST /v1/uploads/multipart/abort
GET  /v1/files
GET  /v1/files/{file_id}
GET  /v1/files/{file_id}/access-url
DELETE /v1/files/{file_id}

When a temporary URL is requested, the SDK sends:

GET /v1/files/{file_id}/access-url?expiresIn=600

Security model

The SDK never receives AWS credentials. It only receives a temporary presigned upload URL from your Dilnaka backend.

Your backend remains responsible for API key validation, scope checking, file validation, S3 key generation, metadata persistence, and upload completion verification.