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

@jiayang-cloud/client

v0.1.1

Published

Call the Jiayang Cloud API from code: deploy, share, read the audit log and manage tokens.

Readme

@jiayang-cloud/client

Call the Jiayang Cloud API from code: deploy, share apps, read the audit log and manage tokens. Full docs: https://jiayang.cloud/docs/sdks/client/

To check who is calling your app, you want @jiayang-cloud/sdk instead.

npm install @jiayang-cloud/client

It runs on Node 20 or newer, Deno, Bun and Workers, with no dependencies.

Sign in

The client uses a CLI session. Run jiayang login once on the computer, and the client finds the session it saved:

import { Jiayang } from "@jiayang-cloud/client";

const jy = new Jiayang();
const me = await jy.me();
console.log(me.email, me.workspaces.map((w) => w.slug));

It looks for a token in this order:

  1. new Jiayang({ token })
  2. JIAYANG_TOKEN
  3. The session jiayang login saved, in the same place the CLI keeps it

A CLI session lasts 30 days. A GitHub Actions run's deploy credential works too, for deploying the one app it was made for. An app's bypass token doesn't: it calls the app, not the API.

The API's address is baseUrl, then JIAYANG_API, then https://api.jiayang.cloud. The session jiayang login saved goes only to the API it was made by: with baseUrl or JIAYANG_API set to anywhere else, the client throws instead of sending it. The client sends a token only over https, or plain http to this machine. Behind a company proxy that inspects TLS, point NODE_EXTRA_CA_CERTS at the proxy's certificate.

Deploy

const version = await jy.deploy.site("acme", "handbook", {
	files: [
		{ path: "/index.html", content: "<h1>Handbook</h1>" },
		{ path: "/logo.png", content: await readFile("logo.png") },
	],
});
console.log(`version ${version.number} is live`);

Only files the platform hasn't got are uploaded. A Worker goes up as the modules you built:

await jy.deploy.worker("acme", "hello", {
	main_module: "index.js",
	compatibility_date: "2026-09-01",
	modules: { "index.js": { content: await readFile("dist/index.js", "utf8") } },
});

Both wait until the version is live and return it, or throw DeployFailedError saying why it isn't. Pass { preview: true } to put it up at a preview address instead, and { wait: false } to return as soon as it's on its way. Container apps are built and pushed by jiayang deploy.

Every deploy is scanned. To have its packages checked for vulnerabilities, pass the lock files that pin them, whole, with the project's .jiayang-allow if it has one: { scan: { lockfiles: [{ path: "package-lock.json", text }], allow } }. Without them no package is checked.

Share

await jy.access.share("acme", "hello", "[email protected]", { role: "editor" });
await jy.access.shareDomain("acme", "hello", "acme.com");
const { still_shared_by } = await jy.access.unshare("acme", "hello", "[email protected]");

Read the audit log

audit.iterate goes back through every page for you:

for await (const entry of jy.audit.iterate("acme", { app: "hello", decision: "deny" })) {
	console.log(entry.at, entry.action, entry.reason);
}

audit.list reads one page, for when you keep your own place.

Bypass tokens

const { secret, url } = await jy.tokens.create("acme", "hello", { name: "nightly", role: "viewer", expires_in_days: 30 });
// secret is shown once. Send it as `Authorization: Bearer <secret>` to url.
await jy.tokens.revoke("acme", "hello", tokenId);

Errors

Every error is a JiayangError. An error answer from the API is an ApiError with status, code and message, and a class for its status: BadRequestError, AuthenticationError, PermissionDeniedError (and PlanLimitError with the limit hit), NotFoundError, ConflictError, PayloadTooLargeError, RateLimitError and ServerError. ConnectionFailedError and RequestTimeoutError mean no answer came.

Reads, and changes that are safe to repeat, are tried again after a failure on our side or a lost connection (twice by default, maxRetries), and after a 429 once its Retry-After has passed. Any other change is never sent twice: after a 429 it throws RateLimitError. Nor is a deploy: when its answer doesn't arrive, or after a 429, the client looks for the version made of what it sent.

Licence

Apache-2.0.