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

@navio-maritime/platform

v0.12.0

Published

Shared platform primitives for every Navio Maritime product: JWT verification, vessel context, invite helpers, Pattern 3+4 cache invalidation, PIN signoff trust window, identity-plane grace-period verifier. Consumed by NavioWorks, NavioFit, NavioBuild, MA

Readme

@navio/platform

Shared platform primitives for every Navio Maritime product: Supabase JWT verification, vessel context resolution, and vessel invite issuance / acceptance. One consistent integration layer across NavioWorks, NavioFit, NavioBuild, MANTIS, and BEACON.

What it is

Three primitive surfaces, landed one per PR under the design spec memory/project_navio_platform_package_design.md:

  • Auth — verify a Supabase JWT, classify failures with a typed error code, cache verified tokens to avoid repeat round-trips.
  • Vessel — resolve a full VesselContext (user + vessel + role + department) from an auth sub claim, or pick the user's active vessel when no explicit vesselId is passed.
  • Invites — issue a Supabase magic-link invite tied to a vessel grant, and accept the resulting token after the user completes password setup.

Every primitive accepts an optional supabase client for testing and lazy-constructs a shared admin client from env vars when called live. No framework coupling — use it from Express, Hono, tRPC, an edge function, a CLI.

What it's NOT

  • Not a schema owner. The package reads/writes users, vessel_users, and vessels rows; the canonical schema lives in each product's database migrations.
  • Not business logic. No crew, equipment, tasks, IHM, SEEMP, or any other product-specific domain. Those stay in their respective routers.
  • Not UI. Components + design tokens live in @navio-maritime/ui (packages/ui-navio/, M4 — published 0.1.0).
  • Not a Supabase client wrapper. Primitives delegate to @supabase/supabase-js; callers who already hold a SupabaseClient can inject it to avoid double-caching.

Public API (v0.4.0)

| Export | Kind | Description | | ----------------------------------------------- | ----- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | verifySupabaseToken(token) | fn | HS256-first JWT verification with Supabase API fallback + 60s cache. Throws PlatformAuthError with typed code. | | getVesselContext(userId, vesselId?, options?) | fn | Resolve the full VesselContext for a Supabase auth sub. Throws PlatformVesselError on no access / missing vessel / no assignments. | | resolveActiveVessel(userId, options?) | fn | Non-throwing variant — returns the primary (or first available) vessel_id for a user, or null. | | createVesselInvite(params, options?) | fn | Issue a vessel invite. New email → creates Supabase auth user + sends magic-link email + creates vessel_users row. Existing user → vessel_users row only. Throws PlatformInviteError on duplicates / missing vessel. | | acceptVesselInvite(token, options?) | fn | Post-login lookup primitive. Validates token state (invalid / expired / already-accepted) and returns the VesselContext the invitee should land in. | | PlatformAuthError | class | extends Error with typed code: PlatformAuthErrorCode. | | PlatformVesselError | class | Same shape; code: PlatformVesselErrorCode. | | PlatformInviteError | class | Same shape; code: PlatformInviteErrorCode. |

Type exports: PlatformUser, PlatformUserRole, PlatformVessel, VesselContext, VesselRole, VesselDepartment, VesselInvite, CreateVesselInviteParams, CreateVesselInviteOptions, AcceptVesselInviteOptions, plus the *ErrorCode string unions.

Installation

From GitHub Packages (external repos — MANTIS, BEACON, etc.)

  1. Add a registry entry for the @navio scope in the consumer repo's .npmrc:

    @navio:registry=https://npm.pkg.github.com
    //npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
  2. Provide a GITHUB_TOKEN with read:packages scope in the consumer environment. For local dev, use a PAT (GITHUB_TOKEN=ghp_... in a shell .env). For CI, the built-in GITHUB_TOKEN from Actions is sufficient if the consumer repo is in the same org.

  3. Install:

    pnpm add @navio/platform

From this monorepo (NavioWorks apps)

Already wired via pnpm workspace resolution — add to package.json:

"dependencies": {
  "@navio/platform": "workspace:*"
}

Quick start

Express middleware that verifies a Supabase session and loads the vessel context onto the request:

import { Request, Response, NextFunction } from 'express';
import {
  verifySupabaseToken,
  getVesselContext,
  PlatformAuthError,
  PlatformVesselError,
  type VesselContext,
} from '@navio/platform';

declare module 'express-serve-static-core' {
  interface Request {
    ctx?: VesselContext;
  }
}

export async function requireVessel(
  req: Request,
  res: Response,
  next: NextFunction
): Promise<void> {
  const token = req.headers.authorization?.replace(/^Bearer\s+/i, '');
  if (!token) return void res.status(401).json({ code: 'no_token' });

  try {
    const user = await verifySupabaseToken(token);
    const vesselIdHeader = req.header('x-vessel-id') ?? undefined;
    req.ctx = await getVesselContext(user.userId, vesselIdHeader);
    next();
  } catch (err) {
    if (err instanceof PlatformAuthError) {
      res.status(401).json({ code: err.code, message: err.message });
      return;
    }
    if (err instanceof PlatformVesselError) {
      res.status(403).json({ code: err.code, message: err.message });
      return;
    }
    next(err);
  }
}

The same pattern works for Hono, tRPC createContext, or a Supabase Edge Function — swap the framework glue; keep the primitive calls.

Environment

Read from process.env lazily at call time (testable via vi.stubEnv):

| Var | Used by | Required? | | --------------------------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | | SUPABASE_URL | all primitives | Yes (unless a client is injected via options.supabase) | | SUPABASE_SERVICE_ROLE_KEY | all primitives | Yes (same) | | JWT_SECRET | verifySupabaseToken | Optional — enables the HS256 fast path. Without it, every verification falls back to the Supabase API. | | APP_URL | createVesselInvite | Optional — default http://localhost:3001. Used as the base for the Supabase invite redirectTo when the caller doesn't pass params.redirectTo. |

Missing Supabase env vars do not throw at import time — they throw (or return null, for resolveActiveVessel) when a primitive actually tries to call a client. This keeps the package importable from tests and CI without a live Supabase instance.

Versioning

Manual semver per PR. Every public-API change bumps the version in package.json and adds a CHANGELOG.md entry in the same commit that ships the change. Breaking changes (rename, removal, signature change) are major bumps; additive surface is minor; internal-only fixes are patch.

Changesets adoption is planned for Great Alignment Week 8+ (per design memo decision #3) — not yet.

Contributing

See the repo's CONTRIBUTING.md. Public API is governed by the design spec at memory/project_navio_platform_package_design.md — any new export must be justified there before it lands.

Publishing

First publish is a manual GitHub Actions dispatch by a maintainer. See .github/workflows/publish-platform.yml:

Actions → Publish @navio/platform → Run workflow → dry_run=false

The workflow rebuilds, re-tests, verifies the version doesn't already exist in the registry, then publishes to https://npm.pkg.github.com. Auto-trigger on push/tag is deliberately not wired — a non-publish-ready commit landing on main should not publish automatically.

License

UNLICENSED. This is a private package distributed inside Navio Maritime OÜ's GitHub organisation. External redistribution is not permitted.