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

@hideyukimori/nene2-client

v1.4.0

Published

TypeScript client ecosystem for NENE2 JSON APIs (OpenAPI-aligned)

Readme

nene2-js

License: MIT npm version Node TypeScript

TypeScript ecosystem for NENE2: OpenAPI-aligned types, HTTP client helpers, and Problem Details utilities for apps that consume NENE2 JSON APIs.

Documentation: https://hideyukimori.github.io/nene2-js/ (English, 日本語, Français, 中文, Português, Deutsch)

This repository is not a Node.js port of the PHP framework. The PHP runtime stays in NENE2. MCP stdio servers in PHP live in nene-mcp.

What this repo is for

  • Typed fetch wrappers and shared client boundaries derived from NENE2 OpenAPI
  • RFC 9457 Problem Details parsing and validation-error helpers for TypeScript consumers
  • Optional codegen scripts and published npm packages (@hideyukimori/nene2-client, scoped subpackages later)
  • Documentation and tooling that follow the same Issue-driven workflow as NENE2

What this repo is not for

  • Replacing NENE2 PHP HTTP runtime, routing, middleware, or DI
  • Duplicating nene-mcp (stdio MCP server in PHP)
  • React/Vite starter UI (that remains in NENE2 frontend/ unless explicitly extracted later)
  • Direct database access from AI tools or SDK code
  • Application-specific business logic (belongs in consumer projects and NENE2-FT style trials)

See docs/scope.md for the full in-scope / out-of-scope matrix.

Install (consumers)

Use the published package from your app’s project root (React/Vite frontend, Node script, etc.). You do not clone nene2-js or lay it out next to NENE2 for normal usage.

cd your-app
npm install @hideyukimori/nene2-client@^1.0.0

Requires Node 22+ (native fetch) or a browser with fetch. TypeScript consumers get .d.ts from the package.

import { createNene2Client } from '@hideyukimori/nene2-client';

const client = createNene2Client({
  baseUrl: process.env.NENE2_JS_API_BASE_URL!,
});

More examples: howto/consume-client.md · VitePress tutorial.

Develop this repository (contributors)

Optional sibling layout when working on nene2-js itself (OpenAPI sync, codegen, tests) next to NENE2 — not required to consume the npm package.

../docker/                    # example parent directory
├── NENE2/                    # PHP framework (OpenAPI source: docs/openapi/openapi.yaml)
├── nene2-js/                 # this repository
├── nene-mcp/                 # PHP MCP stdio library (separate concern)
└── NENE2-FT/                 # field-trial reference apps (historical name; see nene2-js-FT)
cd /path/to/parent-of-NENE2
git clone [email protected]:hideyukiMORI/nene2-js.git
cd nene2-js
npm install
npm run check

OpenAPI types: npm run codegen (see Phase 3).

Point live tests at a running NENE2 API when needed:

cp .env.example .env
# NENE2_JS_API_BASE_URL=http://localhost:8080

Usage (typed client)

import { createNene2Client, Nene2ClientError } from '@hideyukimori/nene2-client';

const client = createNene2Client({
  baseUrl: 'http://localhost:8080',
  // apiKey: process.env.NENE2_MACHINE_API_KEY,
  // bearer: process.env.NENE2_BEARER_TOKEN,
});

const { health, ping } = await client.smoke();
const root = await client.frameworkSmoke();
const notes = await client.listNotes({ limit: 20 });

// Load balancers may return 503 with status "degraded" — opt in:
const degraded = await client.health({ allowDegraded: true });

try {
  await client.getNote(1);
} catch (err) {
  if (err instanceof Nene2ClientError && err.problem) {
    console.error(err.problem.title, err.problem.detail);
  }
}

Works in Node 22+ and browsers that provide fetch.

Verify the API before live smoke

Port 8080 is not always NENE2. Confirm the canonical health shape:

curl -sS http://localhost:8080/health | jq .
# expect: { "status": "ok", "service": "NENE2" }

Or in TypeScript: await client.health({ strictService: true }) rejects wrong service values.

If you see a different JSON wrapper, point NENE2_JS_API_BASE_URL at a running NENE2 PHP instance (sibling ../NENE2).

Multi-backend live smoke (same client, OpenAPI contract — see ADR 0003):

export NENE2_JS_API_BASE_URL=http://localhost:18080     # NENE2 evac (see ft-evac-ports.md)
export NENE2_JS_PYTHON_BASE_URL=http://localhost:18000  # optional: nene2-python
# export NENE2_JS_NODE_BASE_URL=http://localhost:13000  # optional: nene2-node

npm run verify:backends   # curl /health, /examples/ping, /examples/notes
npm test -- tests/client/live-smoke-matrix.test.ts

Unset URLs are skipped; CI runs fixture tests only. Field-trial friction: ADR 0004.

Transport headers

By default, every authenticated request carries the bearer token on two headers: the standard Authorization and a non-standard X-Authorization mirror. Both the typed client (createNene2Client) and the fleet transport (createNene2Transport) apply the mirror on every path — JSON verbs, blob downloads, multipart uploads, raw byte POSTs. Auth headers are applied after static and per-request headers, so no per-request caller can drop or overwrite the mirror while it is enabled (src/transport/headers.ts, src/client/request.ts).

Why. Some shared-hosting front proxies and reverse proxies strip the standard Authorization header before it reaches the application. NENE2 backends fall back to the X-Authorization mirror when the standard header is missing, so the mirror keeps auth working behind such proxies.

Operational note — please read. Because the bearer is duplicated onto a non-standard header, add X-Authorization to the credential-masking rules of anything that records or inspects requests: application logs, access logs, WAF rules, and proxy log pipelines. An environment that masks only Authorization will otherwise record the bearer token in clear text.

Opting out (since 1.3.0). If you control the edge and know Authorization reaches the backend intact, disable the mirror at construction time with mirrorAuthorizationHeader: false — the client then sends Authorization only. This is a construction-time switch; there is no per-request override.

// Authorization only — no X-Authorization mirror
const client = createNene2Client({
  baseUrl: process.env.NENE2_JS_API_BASE_URL!,
  bearer,
  mirrorAuthorizationHeader: false,
});

// Same switch on the fleet transport
const transport = createNene2Transport({ tokenStore, mirrorAuthorizationHeader: false });

The default remains true (mirror on) to keep working behind Authorization-stripping proxies. Making the mirror off by default is planned for a future major release; until then, deployments that keep the default should continue to mask X-Authorization.

Transport contract for consumers (/testing)

The package's own unit tests prove that the package works. They cannot tell you whether your product's wiring — token store, onUnauthorized, recoverAuth, per-request headers — matches what the fleet assumes, and they are not distributed (they live in tests/, outside files).

The ./testing subpath ships a contract you run in your own repository:

// frontend/src/shared/api/transport.contract.test.ts
import { describe, it } from 'vitest';
import { createSessionTokenStore } from '@hideyukimori/nene2-client';
import { runTransportContract } from '@hideyukimori/nene2-client/testing';

runTransportContract({
  product: 'nene-payout',
  surface: 'adapter', // or 'transport' — required; see the how-to
  runner: { describe, it },
  createWiring: ({ storage }) => {
    const tokenStore = createSessionTokenStore({ key: 'nene_payout_token', storage });
    return {
      config: buildTransportConfig(tokenStore), // your own config
      seedToken: (token) => tokenStore.setToken(token),
    };
  },
});

surface declares how your features reach the transport: pass createTransport from createWiring when they go through your own apiClient. Four required cases can only see a failure through that seam — measured, not assumed.

It registers 12 required cases in five groups — the X-Authorization mirror on every path, sessionStorage-only token handling, 401/403 policy, and single-flight recovery — plus an empty-run guard so a suite that shrinks to nothing cannot report success. Differences are declared as exemptions with a reason and a ref, never skipped silently. Individual expect* helpers are exported too, for products that need finer control.

Setup, exemptions, the jsdom requirement, and how to ask for the check to become required are in docs/howto/transport-contract.md.

Documentation site (local)

npm install
npm run docs:dev    # http://localhost:5175
npm run docs:build  # static output → .vitepress/dist

Published on push to main via .github/workflows/docs.yml.

Contributing

Work is GitHub Issue driven. Read docs/CONTRIBUTING.md and docs/workflow.md before opening a PR.

AI agents: start at AGENTS.md.

Consumer DX evidence: field trials (FT30–529 marathon; see methodology, friction registry). Local app sandbox: sibling ../nene2-js-FT/. Quick start: howto/consume-client.md.

Release: releases.md · publish.md · GitHub Releases · Phase history: phase-2.md.

Related projects

| Project | Role | | ----------------------------------------------------------------------- | -------------------------------------------------------- | | NENE2 | PHP API framework, OpenAPI contract, MCP catalog in-repo | | nene2-node | Node.js framework port (@hideyukimori/nene2-framework) | | nene-mcp | Standalone PHP stdio MCP server | | hideyukimori/nene2 | Composer package for PHP consumers |

License

MIT — see LICENSE.