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

@doxajs/core

v0.1.0-alpha.33

Published

The application-facing programming model and contracts for the Doxa.js framework.

Readme

@doxajs/core

Controlled-adoption prerelease: Publicly downloadable under Apache-2.0; Midtown Home Improvements is the sole supported consumer. External use is permitted without compatibility, support, warranty, roadmap, or production-readiness commitments.

The primary application-facing programming model for Doxa. Application Features import roles, models, events, jobs, schedules, policies, configuration, ports, and public contracts from this package.

pnpm add @doxajs/core
import { Feature, Route, type HttpRequest } from '@doxajs/core'

export class HomeRoute extends Route {
  static override readonly id = 'home'
  static override readonly access = 'public'
  readonly method = 'GET'
  readonly path = '/'
  handle(_request: HttpRequest) {
    return { application: 'shop' }
  }
}

export class AppFeature extends Feature {
  id = 'app'
  routes = [HomeRoute]
}

Doxa contributes mandatory infrastructure, authentication routes, and GET /health from framework-owned generated declarations. Application Features do not re-declare them.

Features intentionally export cross-Feature ordinary services through provides without changing their transient or execution scope. Applications with existing group or user permission data map it to stable Doxa abilities through one PermissionSource; resource Policy classes may further narrow those grants. Runtime-invoked permission sources and policies may query declared models through an ambient read-only session without adding persistence machinery to their request objects.

Models

Persistent models expose typed cloned reads and writes while keeping their raw attribute bag protected:

const customer = await Customer.findOrFail(input.id)
const activeCustomer = await Customer.where({ active: true }).find(input.id)
const customerWithOrders = await Customer.with('orders').findOrFail(input.id)

customer.setAttribute('email', input.email)
customer.fill({ displayName: input.displayName, phone: input.phone })

if (customer.isDirty()) await customer.save()

Builder find and findOrFail preserve existing constraints and eager loads while appending the exact logical identity and forcing a one-row limit. The static Model.find() identity fast path is unchanged.

setAttribute and fill clone incoming values, mark ordinary dirty state, and never save implicitly. id cannot be changed after construction. Use intention-revealing model methods for changes that enforce invariants or raise domain events, journal facts, or outbox messages.

Mapped models declare their complete logical persistence projection on the model:

export class Customer extends Model<CustomerAttributes> {
  static override readonly table = 'legacy_customers'
  static override readonly managed = false
  static override readonly readOnly = true
  static override readonly columns = { displayName: 'full_name' } as const
}

managed defaults true and controls Doxa/Praxis migration management only. readOnly defaults false and independently rejects create, save, and delete before observers or persistence. Doxa never hydrates undeclared physical columns, unknown attribute access fails, and mapped updates write only declared dirty attributes plus required timestamp/version infrastructure.

See the Doxa repository for documentation and support.

Datetimes

Doxa application code uses immutable Graphite, Instant, LocalDate, and Duration values over Node.js 26's native Temporal runtime:

import { Duration, Graphite, Instant, LocalDate } from '@doxajs/core'

const startsAt = Graphite.parse('2026-08-05T09:00:00-05:00[America/Chicago]')
const storedInstant = startsAt.toInstant()
const shownForBranch = storedInstant.inTimeZone('America/Chicago')
const serviceDate = LocalDate.parse('2026-08-05')
const reminderLead = Duration.parse('PT30M')

// Explicit legacy interop rejects sub-millisecond loss on the way back to Date.
const legacy = Instant.fromLegacyDate(new Date('2026-08-05T14:00:00.000Z')).toLegacyDate()

Graphite couples an exact instant with an IANA time zone for calendar arithmetic and display. Object construction rejects invalid calendar and clock fields rather than normalizing them, and inTimeZone() accepts UTC or a named IANA zone, not a fixed offset. Database persistence always writes its UTC instant and hydrates Graphite in UTC; preserving a user or branch zone remains an explicit domain field. Instant is the UTC timeline value, LocalDate has no time or zone, and Duration has no anchor. JavaScript Date is unsupported in application models and framework contracts. Database adapters bridge legacy driver values privately. Application payloads use the recursive DoxaValue type when they may carry these values; framework storage and wire contracts remain plain JsonValue after boundary encoding.

Clock-relative calls such as Graphite.now() require an admitted Doxa execution. Every execution uses the configured application time zone and locale, defaulting to UTC and en-US. Strict input codecs compose with Zod through the dedicated subpath:

import { graphite, localDate } from '@doxajs/core/zod'
import { z } from 'zod'

const AppointmentInput = z.object({ startsAt: graphite(), serviceDate: localDate() })

Broadcasting

import { Event, PrivateChannel, type ShouldBroadcast } from '@doxajs/core'

export class OrderShipped extends Event<{ orderId: string }> implements ShouldBroadcast {
  static override readonly id = 'order-shipped'
  broadcastOn() {
    return new PrivateChannel(`orders.${this.payload.orderId}`)
  }
}

Queued broadcasts use the Unit of Work outbox automatically. Use ShouldBroadcastNow only when the publisher must synchronously observe transport success or failure.

Enable Doxa's first-party transport with doxa add keryx. Keryx is a framework-owned optional core module; application Features continue to depend only on the broadcasting contracts above.

Authenticated clients may send explicitly registered ephemeral commands without an HTTP Action:

import { RealtimeCommand } from '@doxajs/core'
import { z } from 'zod'

const TypingInput = z.object({ conversationId: z.string() })

export class SendTyping extends RealtimeCommand<z.infer<typeof TypingInput>> {
  static override readonly id = 'direct-messages.typing'
  static override readonly access = 'direct-messages.participate'
  static override readonly schema = TypingInput
  static override readonly throttle = { limit: 4, windowMs: 2_000 }

  async handle(input: z.infer<typeof TypingInput>): Promise<void> {
    // Emit transient local coordination or a ShouldBroadcastNow event.
  }
}

Register the role in Feature.realtimeCommands. Doxa throttles, validates, and resolves its declared ability against the socket's admitted actor through the normal PermissionSource and optional resource Policy composition. Realtime commands own no writable transaction, are non-retryable, and may not dispatch Actions or durable work; durable mutation remains an HTTP Action.

SMS

Queue provider-independent SMS inside an Action or Job so the delivery intent commits atomically with application state:

import { Action, Sms } from '@doxajs/core'

export class NotifyContact extends Action<{ contact: Contact }> {
  static override readonly id = 'notify-contact'
  private readonly sms = this.inject(Sms)

  async handle({ contact }: { contact: Contact }): Promise<void> {
    await this.sms.send({
      id: crypto.randomUUID(),
      from: contact.stickyTwilioNumber,
      to: contact.phoneNumber,
      text: 'Your appointment is confirmed.',
    })
  }
}

SmsMessage.from is optional and provider-independent. A selected transport owns sender validation and delivery semantics; for example, @doxajs/twilio-sms accepts an explicit E.164 sender or falls back to its configured Messaging Service.