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

tplink-tapo

v0.0.2

Published

Zod-first Tapo discovery and control hub (cloud + LAN, KLAP-aware, TPAP-explicit)

Readme

tplink-tapo

Zod-first Tapo discovery + control hub for Bun/TypeScript: cloud inventory, ARP IP merge, and first-party local KLAP (handshake + AES session via axios / node:crypto). No runtime dependency on tp-link-tapo-connect.

Current release: 0.0.2

When a plug is on TP-Link’s newer TPAP lock (or third-party local access is off), this package detects and throws TapoTpapBlockedError — it never pretends control succeeded. Open-source stacks implement KLAP/AES only; TPAP RE is out of scope for now.

Built with Bun + Zod v4.

Confirmed working (lab)

Private lab, 2026-08-09/10. Prefer discovery encrypt_type over firmware guessing — not every 1.4.x unit is TPAP.

| Lab name | Model | FW | Local encrypt | Package control | |----------|-------|-----|---------------|-----------------| | Bedroom Lamp | P100(AU) | 1.4.6 | KLAP | Yes — native on / off / info (loginKlapByIp, CLI, live tests) | | HomeNuc | P100(AU) | 1.2.5 class | KLAP (lv 2) | Yes — native KLAP (also verified historically via connect-lib) |

Also working in package (not device-specific): cloud login + device list, ARP table merge (local-devices or arp -a), typed TPAP/403 short-circuit, HTTPS-by-default KLAP sessions with response authentication, bounded requests, and inject hooks for offline tests.

| Not confirmed / blocked | Notes | |-------------------------|--------| | Other P100 1.4.x on TPAP | handshake1 403 until app Third-Party Compatibility restores KLAP | | P110 1.4.0 class | Often same 403/TPAP family — probe per unit | | L530 / colour bulbs | Schemas + actions ready; no live lab row yet | | Cameras, sensors, streaming | Out of scope |

TPAP remediation: enable Third-Party Compatibility in the Tapo app, power-cycle the device, and retry discovery/control.

Status

Native KLAP / cloud / ARP path — layouts, schemas, first-party transports, offline unit tests + opt-in live hardware tests.

| Area | State | |------|--------| | Zod schemas (Device, Action, credentials, discovery) | Done | | Cloud list + ARP merge | Done (native tplink-cloud + loadArpTable; inject for tests) | | KLAP control + TPAP/403 errors | Done (native crypto/session, HTTPS default, response validation; inject for tests) | | Live lab: P100 1.2.5 + P100 1.4.6 KLAP | Confirmed | | UDP discovery transport | Stub (fixture mapping ready) | | TPAP reverse-engineering | Out of scope | | Device inventory persistence | Later |

Install

bun install

Optional: local-devices for richer ARP on some platforms (package falls back to parsing arp -a).

Usage

import {
  listDevices,
  controlByIp,
  openDevice,
  discoveryRecordToLanDevice,
  TapoTpapBlockedError,
} from "tplink-tapo";

const credentials = {
  email: process.env.TAPO_EMAIL!,
  password: process.env.TAPO_PASSWORD!,
};

// Cloud inventory (inject cloudList in tests)
const devices = await listDevices(credentials, {
  cloudList: async () => rawCloudArray,
  arp: [{ ip: "192.168.1.10", mac: "aa:bb:cc:dd:ee:ff" }],
});

// Local control — fails with TapoTpapBlockedError on TPAP / handshake 403
// HTTPS is the default. Legacy HTTP-only devices require:
// { klapOptions: { protocol: "http" } } on the control call.
try {
  await controlByIp(credentials, "192.168.1.42", { type: "on" });
} catch (e) {
  if (e instanceof TapoTpapBlockedError) {
    console.error("Unsupported local protocol", e.ip);
  }
  throw e;
}

const handle = openDevice(devices[0]!, { credentials });
await handle.toggle();

CLI (smoke)

cp .env.example .env   # set TAPO_EMAIL / TAPO_PASSWORD
bun run src/cli.ts list
bun run src/cli.ts on --ip 192.168.1.50
bun run src/cli.ts info --ip 192.168.1.50

Scripts

| Command | Purpose | |---------|---------| | bun test | Unit tests (fixtures, no network) | | bun run typecheck | tsc --noEmit | | bun run build | Bundle library + .d.ts into dist/ (no CLI) | | bun run cli | Smoke CLI via source (src/cli.ts) | | bun run scripts/klap-audit.ts | One-handshake local KLAP security audit | | bun run clean | Remove dist/ |

Layout

src/
  schemas/       Zod contracts
  cloud/         Native cloud login/list + listDevices facade
  discovery/     LAN UDP discovery (+ fixture mapping)
  local/         Native KLAP crypto/session + control + TPAP gates
  devices/       DeviceHandle facade
  util/          MAC, nickname, merge, ARP
  errors.ts      Typed error hierarchy
  cli.ts         Smoke CLI
  index.ts       Public exports
test/
  fixtures/      Cloud list + KLAP/TPAP discovery samples
  unit/          Offline unit tests
  live/          Opt-in hardware tests (TAPO_LIVE_TESTS=1)

Design rules

  1. KLAP first for local control; do not claim TPAP support until reverse-engineered.
  2. Detect TPAP early (mgt_encrypt_schm.encrypt_type, HTTP 403 on /app/handshake*).
  3. Typed errors — TapoTpapBlockedError is distinct from auth/network failures.
  4. Stable identity — prefer cloud deviceId, match LAN via normalized MAC.
  5. Inject transports in tests; keep unit suite offline. Default runtime path is native (no peer required).
  6. Secure transport by default — use HTTPS and validate KLAP response signatures; opt into HTTP only for legacy isolated-LAN devices.

Next (P1)

  • UDP discovery implementation (or thin python-kasa bridge)
  • Controllability probe helper (probeLocal(ip) → handshake status)
  • AES legacy securePassthrough fallback for older devices
  • Colour named-map polish for bulbs