Skip to content
PluginStats

@gdp-ts/core weekly downloads statistics

By gdp-ts · npm · ESLint plugins

Ghosts of Departed Proofs for TypeScript: authorization (and other checks) whose results the type checker can see.

View on npm Fresh · Oct 18, 2026

@gdp-ts/core has 115,508 recorded weekly downloads on npm, a change of -8.4% over the past 7 days, ranking #457 of 2,322 tracked listings.

Weekly downloads
115,508
Official API · Oct 18, 2026
7-day growth
-8.4%
-10.6K weekly downloads
30-day growth
—
Insufficient history
90-day growth
—
Insufficient history
Rank
#457
Among tracked npm listings

About @gdp-ts/core

<img width="115" height="86" style="margin-bottom: -10px" alt="A pixel-art ghost carrying a TypeScript document with a green checkmark" src=".github/assets/logo.png" />

gdp-ts

A tiny library + linter and AI skill implementation of Ghosts of Departed Proofs for TypeScript, a verification system to make API contracts more secure at compile (type check) time.

gdp-ts makes an entire category of authorization ("can this user read this resource") or entitlement ("does this user pay for this resource") bugs very difficult for humans and coding agents to introduce, by catching them at compile time with negligible runtime overhead.

Features

  • Incrementally adoptable: works with any TS codebase and any runtime, and doesn't change how you do I/O or effects.
  • Ease-to-rigor slider: how much is exhaustively proven is up to the discretion / risk tolerance of each codebase, and the skill bundles advice.
  • ~Zero runtime overhead: no extra queries or dependencies. The only runtime cost is a tiny wrapper around the ids you check. The safety comes from type checker.
  • Cheap to typecheck: about 0.3 ms per authorized call site on a cold TypeScript 7 check. The cost grows with how often you use it, not with codebase size (benchmark).

Installation

$ npx skills add rauchg/gdp-ts
$ pnpm add @gdp-ts/core

Requires TypeScript 5.4 or newer.

The problem

A lot of codebases feature code like this:

async function handler(req, res) {
  await assertProjectAdmin(req.user.id, req.params.projectId); // throws 403
  await setPasswordProtection(req.params.projectId, req.body.password); // nothing connects this to the line above
  res.sendStatus(204);
}

Looks great, except: all it takes is

  • a developer to slip and miss the first await
  • the business rules on who gets to "change password protection" to change (say, Owners only), and one call site to keep running the old check

... for a security / business disaster to occur.

The solution

We change the signature above from something anyone can call from anywhere:

function setPasswordProtection(projectId: ProjectId, password: string): Promise<void>;

...to forcing the caller to present evidence (proof) that they can do (are admin) and can get (have the plan) the thing:

function setPasswordProtection<U, P>(
  project: Named<P, ProjectId>,
  password: string,
  _proofs: { admin: UserIsProjectAdmin<U, P>; plan: PlanIncludesPasswordProtection<P> },
): Promise<void>;

The skill takes care of guiding agents and humans towards this safer pattern, and away from the boolean blindness problem.

How it works

1️⃣ Name values. name(x, k) gives a runtime value a compile-time-only name N. Every call to name creates a different N, and N exists only inside the callback. For our example, wwo project ids named separately are now distinguishable to the compiler even though both are string:

// app.ts
import { name } from "@gdp-ts/core";
import { disablePasswordProtection } from "@/data/projects";
import { ProjectId } from "@/lib/ids";
import { userIsProjectAdmin } from "@/proofs/user-is-project-admin";
import { app, authenticated, HttpError } from "@/lib/server"; // your Express app, auth middleware, error type

app.delete(
  "/projects/:id/password-protection",
  authenticated((viewer, req, res) => // authenticated() resolves the logged-in user
    name(viewer.id, ProjectId(req.params.id), async (user, project) => {
      const admin = await userIsProjectAdmin(user, project);
      if (!admin) throw new HttpError(403, "Only Owners and Members can change this");
      await disablePasswordProtection(project, admin);
      res.sendStatus(204);
    }),
  ),
);

2️⃣ Prove facts about names. A small trusted module performs a check and returns a Proof<"UserIsProjectAdmin", [U, P]>, or null. Only that module can mint that proof. At runtime a proof is a frozen { kind } object.

// proofs/user-is-project-admin.ts  (trusted: the only place that can mint this proof)
import { defineProof, type Named, type Proof } from "@gdp-ts/core";
import { db } from "@/lib/db";
import type { ProjectId, UserId } from "@/lib/ids";

const UserIsProjectAdmin = defineProof("UserIsProjectAdmin"); // not exported
export interface UserIsProjectAdmin<U, P> extends Proof<"UserIsProjectAdmin", [U, P]> {}

export async function userIsProjectAdmin<U, P>(
  user: Named<U, UserId>,
  project: Named<P, ProjectId>,
): Promise<UserIsProjectAdmin<U, P> | null> {
  const role = await db.roleInProjectTeam(user.value, project.value);
  return role === "owner" || role === "member" ? UserIsProjectAdmin.prove(user, project) : null;
}

3️⃣ Demand proofs. Sensitive functions take a proof about their exact arguments. Calling them with the wrong proof, a proof about a different value, a raw id, or no proof is a compile error 🎉

// data/projects.ts  (sensitive: demands exact proofs)
import type { Named } from "@gdp-ts/core";
import { db } from "@/lib/db";
import type { ProjectId } from "@/lib/ids";
import type { UserIsProjectAdmin } from "@/proofs/user-is-project-admin";

export function disablePasswordProtection<U, P>(
  project: Named<P, ProjectId>,
  _proof: UserIsProjectAdmin<U, P>,
): Promise<void> {
  return db.writePasswordProtection(project.value, null);
}
```…

Description from the npm listing.

  • typescript
  • authorization
  • ghosts-of-departed-proofs
  • gdp
  • phantom-types
  • type-safety
  • eslint-plugin
  • oxlint

README badge

Show your rank in a README or on your website. The badge updates automatically.

Charts

Images: 30d · 1y · all time · 1600×900 dark

Adoption over time

@gdp-ts/core weekly downloads on npm, last 90 days: 115,508 weekly downloads as of Oct 18, 2026.@gdp-ts/coreWeekly downloads on npm · Last 90 days115,508downloads / week020K40K60K80K100K120K140KJul 20Aug 4Aug 19Sep 3Sep 18Oct 3Oct 18downloads / weekobservedarchived (Internet Archive)no observationsJul 22, 2026 – Oct 18, 2026 · 89 observations · Updated Oc…pluginstats.com
@gdp-ts/core weekly downloads on npm, last 90 days: 115,508 weekly downloads as of Oct 18, 2026.

7/30/90-day growth

@gdp-ts/core weekly downloads growth on npm: -8.4% over 7 days, 30-day growth unavailable, 90-day growth unavailable.@gdp-ts/coreWeekly downloads growth on npm115,508downloads / week now7-day growth-10,618 weekly downloads-8.4%30-day growth+115,508 weekly downloadsInsufficient history90-day growth+115,508 weekly downloadsInsufficient historyGrowth vs. nearest observation to each baseline date · Updated Oct 18, 2026pluginstats.com
@gdp-ts/core weekly downloads growth on npm: -8.4% over 7 days, 30-day growth unavailable, 90-day growth unavailable.

Ranking history

@gdp-ts/core npm ranking history: currently #457 (by weekly downloads).@gdp-ts/corenpm ranking · by weekly downloads · Last 90 days#457current rank#450#460#470#480#490#500Jul 22Aug 6Aug 21Sep 5Sep 20Oct 5Oct 20rankOct 18, 2026 – Oct 20, 2026 · 3 observations · Updated Oct 18, 2026pluginstats.com
@gdp-ts/core npm ranking history: currently #457 (by weekly downloads).

Listing placement

All npm2,320 listings · 116 pages · 1,161 shown · page 23, #17 (overall #457)
All npm: every listing in weekly downloads order

Listing placement

ESLint plugins256 listings · 13 pages · page 5, #20 (overall #100)
ESLint plugins: every listing in weekly downloads order

Filled points are observed values; hollow points come from Internet Archive snapshots of the listing page. Dashed segments span periods with no observations — values between points are not interpolated.

Each band is one page of 20. Weekly downloads on a linear scale. Placement is projected from weekly downloads, so it can differ from the marketplace's own sort order. Hover a dot to see the listing.

Recent observations

Full history (122)
Recent weekly downloads observations for @gdp-ts/core
Date (UTC)Weekly downloadsChange vs. previous
115,508+44.4K
71,065-20.2K
91,278+10.2K
81,064-32.9K
114,013-25.8K
139,7690
139,769+13.6K
126,126+14.6K
111,538+20.2K
91,325+30K
61,368+32.9K
28,419+25.8K
2,6630
2,663—

Similar npm ESLint plugins plugins

All 20 @gdp-ts/core alternatives

Data source

Weekly downloads (trailing 7 complete days) come from the official npm downloads API. Downloads include CI and mirrors and are not equivalent to installs or users. npm publishes no ratings.

Listing: https://www.npmjs.com/package/@gdp-ts/core. First seen Oct 16, 2026; last successful collection Oct 20, 2026. See the methodology.