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

@jwilleke/accounting-addon

v0.3.0

Published

Accounting addon for ngdpbase

Readme

Accounting

The base accounting add-on for ngdpbase: funds, a single-entry ledger with voids and transfers, the treasurer's screens, the [{Ledger}] plugin, a monthly summary and a CSV export.

  • Slug: accounting. It is the registry key and the config key, and equals the name exported from index.ts.
  • Type: additive.
  • Requires: ngdpbase 5.31.0 or later (ngdpbase.minVersion in package.json); the forms add-on for the screens (optionalDependencies: ['forms']).

Turning it on for a site: docs/guides/accounting-guide.md. The ledger's API for other add-ons: docs/managers/LedgerManager.md. Why it is built this way: docs/plans/ledger-design.md and docs/plans/decisions.md.

Contents

| Path | What it is | | --- | --- | | index.ts | register(engine, config, host): opens the declared database, builds the audit door, registers LedgerManager, mounts the API, the plugin and the forms | | managers/LedgerManager.ts | The ledger: one door per action, each asked of ngdpbase's decision point and audited | | managers/ReceiptManager.ts | Money coming in: picks the receipt provider (manual now, Stripe later) and hands the receipt or refund to the ledger | | managers/migrations.ts | The accounting tables, and the triggers that refuse deletes and silent changes to money | | routes/api.ts | JSON API under /api/accounting, including the CSV download at /export | | forms.ts | The treasurer's forms (receipt, refund, money out, transfer, void, fund create/rename/close) for the forms add-on | | plugins/LedgerPlugin.ts | [{Ledger view='balances' / 'entries' / 'summary'}], drawn for the viewer | | config/default-config.json | The database declaration, permissions with their audit rules (step-up is off for now, D-030), the treasurer role and its policy | | pages/ | The treasurer's pages and the Using Accounting help page, seeded on first enable | | __tests__/ | Ledger, report, form and plugin tests against a real SQLite database |

How it reaches ngdpbase

One path for each thing, never a local copy:

  • Core values (ApiContext, ApiError, sendApiError, recordAuditEvent, addonAuditEventName, actorOf, logger) come from the host passed to register() (ngdpbase #1813) and are handed down to the manager, routes and forms.
  • Shared capabilities belong to their manager: the CSV writer is ExportManager.toCsv, the money formatter PluginManager.formatters.formatMoney; the plugin gets the formatters as context.formatters.
  • Routes use engine.createRouter(), core's own Express; the add-on never imports express at runtime.
  • The database is opened with DatabaseManager.openAddonDatabase and declared as ngdpbase.addons.accounting.database.
  • Access: LedgerManager asks PolicyDecisionPoint.decide(subject, { action }) and turns a deny into ngdpbase's refusal with ctx.enforceDeny (D-025). No role names in code.
  • Caching: after each write the manager bumps the LedgerManager topic in CacheManager.

Types come from @jwilleke/ngdpbase-types (a dev dependency, published with each ngdpbase release); the tests use its /testing kit (the host builder, an in-memory add-on database checked against our declaration, the CSV writer, the plugin formatters). Nothing imports ngdpbase's files.

Develop

No ngdpbase checkout is needed to build or test:

cd addons/accounting
npm install
npm test                        # builds (tsc) first, then runs vitest

To run it, point an ngdpbase instance's add-ons path at this repository's addons/ folder, enable accounting (and forms), and restart. scripts/smoke.sh checks a running site end to end.