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

@jarwizz/jarshop-invoicing

v0.1.0

Published

JarShop invoicing Feature Package adopting the pinned Pinelab invoice engine.

Readme

JarShop Invoicing

@jarwizz/jarshop-invoicing is the invoicing Feature Package described by ADR-0012. It adopts @pinelab/[email protected] and explicitly supplies [email protected] and [email protected], which the plugin imports without declaring dependencies.

Entries

  • @jarwizz/jarshop-invoicing exports SellerProfile, InvoiceOrder, SlovakNonVatInvoiceInput, createSlovakNonVatInvoiceData, slovakNonVatInvoiceTemplate, and renderSlovakNonVatInvoice without Vendure.
  • @jarwizz/jarshop-invoicing/server exports JarShopInvoicingPlugin and the JarShopInvoicingConfig type. The JarShop plugin composes the adopted engine and exposes its Dashboard extension through a directly discoverable package entry. It also exports seedSlovakNonVatInvoiceTemplate. It also exports configureSlovakInvoicing, SlovakInvoicingOptions, configureInvoiceNumbering, JarShopInvoicingInit1789336800000, and jarShopInvoicingMigrations.

The server entry targets Vendure 3.7.1 and the exact peers in package.json. Consumers import this package, not Pinelab, and do not choose the engine version. Production publication and staging verification remain separate release work.

Installation policy

The Client Project must explicitly deny [email protected] in its pnpm allowBuilds policy. Its install script must not download Chrome. The worker image supplies Chrome through PUPPETEER_EXECUTABLE_PATH; image and font setup belong to the later adoption and staging slices.

Verification

pnpm verify:packages builds and packs this package, validates its exports and tarball inventory, runs publint and Are the Types Wrong, and imports the root from a clean consumer without Vendure.

pnpm --filter @jarwizz/jarshop-invoicing test additionally packs and installs the server in a separate consumer, compiles a typed Vendure configuration, and boots Vendure 3.7.1 against disposable PostgreSQL to query the Invoice GraphQL schema. The fixture follows the repository's skipLibCheck: true policy; it checks the consumer configuration, not all upstream declaration files. Docker is required. TestServer explicitly creates the disposable schema; this is not migration evidence. No PDF rendering or Chrome launch is tested.

Slovak non-VAT template

The template is reviewed package source, uses local DejaVu Sans/Arial fonts, and has no external assets or custom Handlebars helpers. The Seller Profile has name, street, city, postalCode, ico, dic, vatStatus: "non-payer", iban, and registerEntry. Other VAT statuses are rejected at runtime. It renders “Nie sme platiteľmi DPH” with no VAT columns or totals.

renderSlovakNonVatInvoice({ seller, order, invoiceNumber, issuedAt }) returns HTML without starting Chrome. invoiceNumber is supplied by the caller, never allocated by the template. issuedAt is an explicit date rendered in the Europe/Bratislava timezone. Order prices are Vendure minor units; discounted line/unit prices including allocated order discounts (prorated*WithTax), shipping, and the authoritative order total are formatted in the order currency. Billing address takes precedence, falling back to shipping when its street is absent, and the order customer supplies a missing buyer name. Only synthetic identities are used in tests.

The engine compiles stored templates against the loadDataFn return value. configureSlovakInvoicing supplies the compatible loader. It increments the latest Channel number (or Last Issued Number), maps the Seller Profile and order, and uses the stored original total for credits. A credit says “Dobropis”, names the original invoice, and reverses it in full without reusing lines from the now-cancelled or modified order.

After migrations, the Client Project's explicit seed script calls:

import { ModuleRef } from "@nestjs/core";
import { Injector, RequestContextService } from "@vendure/core";
import { seedSlovakNonVatInvoiceTemplate } from "@jarwizz/jarshop-invoicing/server";

const ctx = await app.get(RequestContextService).create({
  apiType: "admin",
  channelOrToken: channelToken,
});
await seedSlovakNonVatInvoiceTemplate(ctx, new Injector(app.get(ModuleRef)));

The seed uses the adopted plugin's configuration service to enable generation and credit invoices for the selected Channel and replace its stored template. Repeat runs reuse that Channel's configuration row. Dashboard template edits are temporary and are replaced by the next explicit seed. Do not call this operation from application startup. Verify worker rendering before live adoption.

Follow-up scope

Runtime adoption is provided by the starter; delivery is #152; staging and publication are #153. Invoice entities, rendering, credit invoices, Dashboard screens, and events remain upstream-owned.

Last Issued Number and migrations

For an existing legal series, spread configureInvoiceNumbering(lastIssuedNumber) into JarShopInvoicingPlugin.init(...). The value is reviewed Client Project configuration. For example, 20260143 produces 20260144 as the first new invoice with the adopted loader. Do not subtract one: Pinelab's misleadingly named startInvoiceNumber is passed to the loader as the previous number. Once invoices exist, the latest number in the current Channel takes precedence over this initial configuration. A custom loadDataFn must preserve the same increment-by-one contract, including on retries.

The helper accepts positive integers up to 2147483646, leaving room for the next PostgreSQL integer. Zero is rejected because Pinelab replaces a falsy start value with its default 10000. This API continues an existing series; it does not define a new series or its format. The yearly series transition is explicitly deferred pending the operator's answer tracked on #150.

Register package-owned migrations explicitly:

import { jarShopInvoicingMigrations } from "@jarwizz/jarshop-invoicing/server";

// In the Client Project's PostgreSQL dbConnectionOptions:
// migrations: [...clientMigrations, ...jarShopInvoicingMigrations],
// synchronize: false,
// migrationsRun: false,

Run migrations through the Client Project's explicit migration command before seeding or issuing. The hand-written migration targets PostgreSQL and Vendure's default integer entity IDs and naming strategy. It creates invoice and invoice_config, preserving the pinned upstream schema, including string Channel/order IDs, the credit-invoice self-reference and the unique (channelId, invoiceNumber) constraint. Do not apply it over tables previously created by synchronization; reconcile such a database explicitly before adoption. Rollback locks both tables and refuses while any invoice or configuration row exists. Run migrations transactionally (TypeORM's default). Disabling the feature is not a rollback operation.

test/migration.test.ts runs up/down/up against disposable PostgreSQL, checks that TypeORM has no schema differences, verifies Channel-scoped uniqueness and refusal to drop issued records. test/issuance.test.ts issues two real Vendure orders against this migration and forces both initial candidates to collide; it asserts the engine's retry warning and the resulting 20260144/20260145. Only Chrome rendering and PDF storage are replaced at the system boundaries. This proves local numbering and migration behavior, not PDF or staging readiness.

Runtime adoption

JarShopInvoicingPlugin.init(
  configureSlovakInvoicing({
    seller: reviewedSellerProfile,
    lastIssuedNumber: 20260143,
    vendureHost: "https://shop.example.com",
    localStorageDirectory: "/data/invoices",
    chromeExecutablePath: "/usr/bin/chromium",
  }),
);

The adopted subscriber handles OrderPlacedEvent; no second subscriber or inline PDF generation is added. It enqueues a generate-invoice job with ten retries. The worker renders and stores the PDF. Render errors are observable in worker logs and the Vendure job queue; checkout is already complete. After exhausted retries, repair Chrome/storage configuration before attempting explicit operator recovery; automatic retries do not continue indefinitely. Never log or distribute its email-bearing download URLs to customers.

The Dashboard bridge uses Pinelab's invoice queries and correction mutation, while presenting JarShop-owned operator controls. Downloads use an authenticated invoice-ID endpoint without customer data in the URL. The order detail distinguishes downloading an existing PDF, intentionally redelivering that document through the Client Project outbox, and correcting business data through Pinelab's credit-note-and-replacement flow. JarShop ships the bridge as raw TSX so the Client Project's Vite build transforms it.

test/event-path.test.ts uses the real Shop API COD mutation, EventBus, PostgreSQL package migrations, SQL job queue, and local file strategy. It asserts both placement and invoice-created events and one invoice. A synthetic PDF failure is retried by the same job without changing successful placement. Only Chrome rendering is replaced in this test. This proves one normal placement and a pre-insert render retry; it does not claim general exactly-once processing after arbitrary storage failures or replayed external events.

Generated-consumer verification installs retained, verified package tarballs, checks a frozen reinstall, runs a browser COD checkout and waits for one real worker-generated PDF. Registry installation of the unreleased 0.0.0 pin is not available until the release slice updates and publishes the package matrix. The worker needs Chrome and local fonts; server and worker need the same storage directory and backups. This local proof does not replace real-image staging.