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

@ikatec/frame

v0.2.0

Published

Reusable backend framework — Hono, Pino, OpenTelemetry, Drizzle/Sequelize, built-in DI. Runs on Node and Cloudflare Workers.

Readme

@ikatec/frame

Reusable backend framework for Node and Cloudflare Workers, built from a single source tree. Hono routing, Pino logging, OpenTelemetry observability, Drizzle (and Sequelize on Node) persistence, a provider-agnostic mail/jobs/events layer, and a built-in, zero-dependency dependency-injection container. Pick the subpaths you need — most run on both runtimes; the few that pull a Node-only dependency are called out below.

Install

# base — always required
npm install @ikatec/frame hono pino @opentelemetry/api

Everything else is an optional peer, installed only for the features you use:

npm install @hono/zod-validator zod          # @ikatec/frame/validation
npm install drizzle-orm                       # database/drizzle + repositories/drizzle (Node + Workers)
npm install sequelize sequelize-typescript    # database/sequelize + repositories/sequelize (Node only)
npm install @hono/node-server                 # apps/node + apps/jobs (Node HTTP server)
npm install nodemailer                         # mail/smtp (Node only)
npm install @opentelemetry/sdk-node            # observability/node-sdk (Node)
npm install @opentelemetry/sdk-trace-base @opentelemetry/exporter-trace-otlp-http  # observability/workers-sdk

The AWS SES mail provider needs no extra install — @aws-sdk/client-sesv2 ships as a direct dependency.

Requirements: Node >=22 <23. The DI decorators are TC39 legacy decorators — enable them in your tsconfig.json (see TypeScript setup).

Packages

Each sub-package is its own import subpath (@ikatec/frame/<name>) with its own README:

  • apps — composition-root base classes (ApiApp; apps/node NodeApiApp, apps/workers WorkersApiApp, Node JobsApp/ScriptsApp)
  • cache — async Cache interface + in-memory and Cloudflare KV implementations
  • cls — continuation-local storage over AsyncLocalStorage
  • configBaseConfig contract + DI token
  • crypto — AES-256-CBC JSON ↔ URL-safe base64
  • databaseDatabaseService contract + Drizzle / Sequelize impls
  • di — DI container (Container, @Service, @Inject, Token)
  • errorsHttpError classes + serialize-error helpers
  • events — domain EventBus dispatching onto the job queue
  • httpClient — axios-based HTTP client with retries
  • jobs — background-job registry + HTTP / sync dispatchers
  • logsLogger interface + Pino implementation
  • mail — provider-agnostic email (MailService, SES, SMTP)
  • middleware — Hono error / logging / observability middleware
  • modules — type-only ModuleManifest composition contract
  • observability — OpenTelemetry seam (withSpan, runtime drivers)
  • repositoriesRepository<T> interface + filter DSL
  • scripts — named CLI script registry
  • transformers — type-only Transformer<T, U> contract
  • useCasesUseCase base class
  • validationvalidate (zod-validator wrapper)

Internal helpers (not export subpaths): tests (setupTestDB), utils.

Runtime targets

Most subpaths are runtime-neutral — the same import works on Node and Cloudflare Workers. The exceptions each pull a runtime-specific dependency:

| Subpath | Runs on | Why | | --- | --- | --- | | @ikatec/frame/cache (InMemoryCache) | Node only | setInterval().unref() (KvCache, same subpath, is Workers-oriented) | | @ikatec/frame/httpClient | Node only | axios + node http/https agents | | @ikatec/frame/apps/node (NodeApiApp) | Node only | @hono/node-server (long-lived server) | | @ikatec/frame/apps/jobs (JobsApp) | Node only | @hono/node-server | | @ikatec/frame/apps/scripts (ScriptsApp) | Node only | yargs | | @ikatec/frame/database/sequelize | Node only | sequelize | | @ikatec/frame/repositories/sequelize | Node only | sequelize | | @ikatec/frame/mail/smtp (SmtpEmailProvider) | Node only | nodemailer | | @ikatec/frame/observability/node-sdk (NodeObservability) | Node only | @opentelemetry/sdk-node | | @ikatec/frame/observability/workers-sdk (WorkersObservability) | Workers only | @opentelemetry/sdk-trace-base + OTLP/fetch |

The neutral counterparts (@ikatec/frame/apps's ApiApp, database/drizzle, repositories/drizzle, mail's AwsSesEmailProvider, logs, observability's interface, jobs/sync, validation, …) run on both.

Node-only subpaths are not gated behind an export condition, so importing one in a Workers bundle drags its Node-only dependency in. Import the neutral subpath (or the Workers driver) on Workers.

Dependency injection

A small, opinionated DI toolkit ships under @ikatec/frame/di: a singleton Container, @Service / @Inject decorators, and Token for non-class identifiers (config values, interfaces, primitives). Zero dependencies, no reflect-metadata.

import { Container, Service, Inject } from '@ikatec/frame/di'

@Service()
class Logger {
  log(msg: string) { console.log(msg) }
}

@Service()
class UserService {
  @Inject(() => Logger) private logger!: Logger
  greet() { this.logger.log('hello') }
}

Container.get(UserService).greet()
  • Container.get(id) / Container.set(id, value) — resolve / register
  • Container.has(id) / Container.remove(id) / Container.reset()
  • @Service(options?) — mark a class injectable ({ transient: true } for per-resolve instances)
  • @Inject(() => Class) — lazy property injection (supports forward refs); pass a Token directly
  • Token<T>(name) — opaque identifier for non-class deps

See the DI README for scopes, circular-dependency handling, and inheritance.

Observability per runtime

OpenTelemetry works on both runtimes via the neutral @ikatec/frame/observability interface (ObservabilityToken, withSpan). Register the driver that matches your runtime:

| Runtime | Driver | Backed by | | --- | --- | --- | | Node | @ikatec/frame/observability/node-sdk (NodeObservability) | @opentelemetry/sdk-node (auto-instrumentation) | | Workers | @ikatec/frame/observability/workers-sdk (WorkersObservability) | @opentelemetry/sdk-trace-base + OTLP/HTTP-over-fetch |

// Cloudflare Worker
import { ObservabilityToken } from '@ikatec/frame/observability'
import { WorkersObservability } from '@ikatec/frame/observability/workers-sdk'
import { Container } from '@ikatec/frame/di'

const obs = new WorkersObservability({ endpoint: env.OTLP_ENDPOINT, headers: { /* ... */ } })
obs.start()
Container.set(ObservabilityToken, obs)
// flush before the isolate suspends — exports run on `fetch`, which the Worker cancels at response:
ctx.waitUntil(obs.forceFlush())

WorkersObservability uses a SimpleSpanProcessor (not BatchSpanProcessor, whose background timers don't fire between Worker invocations) and takes config explicitly (there's no process.env on Workers). Cloudflare's own automatic tracing can also export OTLP with no code if you don't need custom spans.

TypeScript setup

The @Service / @Inject decorators are TC39 legacy decorators, and property injection relies on declared-but-uninitialized fields staying absent until the container wires them. Configure your tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2022",
    "experimentalDecorators": true,
    "useDefineForClassFields": false,
    "emitDecoratorMetadata": false // not needed — no reflect-metadata
  }
}

Getting started

Subclass BaseConfig, pick a database implementation, register both in the Container, and start an ApiApp. Working setups live in examples/:

| Example | Runtime | Shows | | --- | --- | --- | | minimal-node | Node | smallest NodeApiApp + listen() server | | minimal-cloudflare | Workers | smallest Workers fetch handler | | modular-node | Node | ModuleManifest composition over Drizzle/SQLite | | production-fullstack | Workers | end-to-end Hono RPC + D1 + React, a production-shaped monorepo |

Releasing

CI lives in .gitlab-ci.yml: every branch/MR pipeline runs lint, type-check, and tests, then builds dist/. The testcontainers-based Postgres integration suites (*.integration.test.ts) are skipped in CI via SKIP_INTEGRATION_TESTS=1 because the runner can't run docker-in-docker yet — run them locally with a plain npm test.

Releases are automated with semantic-release (config in .releaserc.json): every push to main analyzes the conventional-commit history, and when it warrants a release, bumps the version, publishes to npm, pushes a chore(release) commit + tag, and creates the GitLab release. No manual tagging or version bumps — fix: → patch, feat: → minor, BREAKING CHANGE: → major. Requires the NPM_TOKEN and GITLAB_TOKEN (api scope) CI/CD variables.

Status

0.1.0 — initial extraction from ikatec-backoffice.