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

@nerdstackgrp/ark-server

v1.0.9

Published

Ark backend SDK — REST and S3-compatible access to Ark storage.

Readme

@nerdstackgrp/ark-server

The Ark backend SDK. One package, two ways in: Ark's REST API, or any S3-compatible tooling.

import { Ark, ArkS3 } from "@nerdstackgrp/ark-server";

Install

npm install @nerdstackgrp/ark-server

Runtimes: Node 20+, Bun. Signing uses WebCrypto, so Deno and Cloudflare Workers also work for the ArkS3 client; Ark's upload-from-path helper is the only Node-specific part.

REST API

const ark = new Ark({ token: process.env.ARK_API_TOKEN! });

const file = await ark.files.upload("./photo.jpg", { folderId });
const files = await ark.files.list({ limit: 50 });
const url = await ark.files.getDownloadUrl(file.id);
await ark.files.delete(file.id);

await ark.folders.create({ name: "Products" });
const usage = await ark.usage();

Ark Streams

The REST client exposes Ark Streams' control plane. create returns the Ark TUS facade endpoint for a browser or TUS client; import asks Ark's video provider to fetch a remote URL without routing the video through your server.

const { stream, upload } = await ark.streams.create({
  appId,
  title: "Product launch",
  sizeBytes,
});

await ark.streams.import({ appId, title: "Remote video", url });
const current = await ark.streams.get(stream.id, { appId });
const page = await ark.streams.list({ appId, limit: 50 });
await ark.streams.refreshUploadUrl(stream.id, { appId });
await ark.streams.delete(stream.id, { appId });

Use @nerdstackgrp/ark-client when you want the SDK to perform the complete browser TUS transfer and report progress automatically.

upload accepts a path, a Uint8Array, or a Blob, and handles multipart transparently. Paths and blobs are streamed in bounded ranges rather than read into memory in full.

For a custom Node or Web stream, provide its exact size so Ark can reserve quota and plan multipart uploads before transferring bytes:

import { createReadStream } from "node:fs";
import { stat } from "node:fs/promises";

const path = "./large-video.mp4";
const { size } = await stat(path);
const file = await ark.files.uploadStream(createReadStream(path), {
  size,
  filename: "large-video.mp4",
  contentType: "video/mp4",
});

The stream must produce exactly size bytes. Ark rejects underflow or overflow and aborts the server-side upload session so its quota reservation is released.

Browser sessions

To let your frontend upload directly without exposing your token:

const session = await ark.createClientSession({ ttlSeconds: 900 });
// Hand session.token to the browser, use it with @nerdstackgrp/ark-client.

S3-compatible API

const s3 = new ArkS3({
  endpoint: "https://ark.nerdstackgrp.com/s3",
  accessKeyId: process.env.ARK_ACCESS_KEY_ID!,
  secretAccessKey: process.env.ARK_SECRET_ACCESS_KEY!,
  bucket: "product-media",
});

const stored = await s3.putObject("photo.jpg", bytes, { contentType: "image/jpeg" });
// `stored.url` is Ark's stable delivery URL. It uses the canonical physical
// object identity, not the logical S3 key supplied above.
console.log(stored.url, stored.assetId, stored.objectKey);
const data = await s3.getObject("photo.jpg");
const meta = await s3.headObject("photo.jpg");
const { objects } = await s3.listObjects({ prefix: "photos/", delimiter: "/" });
await s3.deleteObject("photo.jpg");

These are Ark credentials, issued in your Ark dashboard. They are not credentials for any underlying storage provider, and they authenticate only against Ark.

Multipart

const { uploadId } = await s3.createMultipartUpload("big.mp4");
const part = await s3.uploadPart({ key: "big.mp4", uploadId, partNumber: 1, body: chunk });
await s3.completeMultipartUpload({ key: "big.mp4", uploadId, parts: [part] });

Presigned URLs

const url = await s3.presignGet("photo.jpg", { expiresInSeconds: 900 });
const put = await s3.presignPut("upload.bin", { expiresInSeconds: 900 });

Using the standard AWS SDK

Ark's S3 endpoint works with the official AWS SDK, the AWS CLI, and rclone — you are not required to use this package:

import { S3Client } from "@aws-sdk/client-s3";

const client = new S3Client({
  endpoint: "https://ark.nerdstackgrp.com/s3",
  region: "auto",
  credentials: {
    accessKeyId: process.env.ARK_ACCESS_KEY_ID!,
    secretAccessKey: process.env.ARK_SECRET_ACCESS_KEY!,
  },
  forcePathStyle: true,
});
aws s3 ls s3://product-media --endpoint-url https://ark.nerdstackgrp.com/s3

Supported operations: PutObject, GetObject, HeadObject, DeleteObject, ListObjectsV2, CreateBucket, DeleteBucket, ListBuckets, the four multipart operations, and presigned GET/PUT. Not supported yet: CopyObject, object versioning, ACLs, bucket policies, lifecycle rules, and tagging.

Errors

import { ArkError } from "@nerdstackgrp/ark-server";

try {
  await s3.getObject("missing.jpg");
} catch (error) {
  if (error instanceof ArkError && error.code === "NO_SUCH_KEY") { /* ... */ }
}

Both surfaces normalize into ArkError — the REST API's JSON envelope and the S3 API's XML errors alike — so mixing them means handling one error type.

Buckets

An Ark bucket is a logical container scoped to your app, not a physical bucket at a storage provider. Object keys are yours; the physical location is Ark's concern and can change (for example when you upgrade your plan) without your bucket names, keys, or credentials changing.

Security

  • Ark never issues you provider credentials, and never receives yours.
  • Secrets are shown once at creation. Store them immediately.
  • Rotate with an overlap window so a deploy never races an in-flight process: the old key stays valid for a grace period after the new one is issued.

License

MIT. Derived in part from s3mini (MIT, © 2026 thinking.tools) — its AWS SigV4 construction was adapted for Ark's client and gateway. See LICENSE and LICENSE.upstream.