Skip to content
JainParichayPublic

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

JainParichay Shared Packages

Shared @jainparichay/* packages for all JainParichay apps, published to GitHub Packages.

Package What it is
@jainparichay/db PostgreSQL connection handler (bring your own Prisma schema)
@jainparichay/ui Shared React components (CVA + Tailwind)
@jainparichay/i18n Localization helpers
@jainparichay/storage Storage helpers
@jainparichay/ai OpenAI-compatible client wrapper
@jainparichay/config-typescript Reusable tsconfig presets

These packages contain mechanism only — no database schemas, no domain types, no visual design. Anything specific to one app's data model or brand belongs in that app. @jainparichay/types was removed for this reason: its contents were one app's domain.

Installing in an app

GitHub Packages requires a token even for public packages. The app's committed .npmrc should carry the registry mapping only:

@jainparichay:registry=https://npm.pkg.github.com

Do not put the token in that file. It's committed to the repo, and pnpm deliberately refuses to expand environment variables in credentials that come from a project-level .npmrc — putting //npm.pkg.github.com/:_authToken=${NODE_AUTH_TOKEN} there will fail with a 401, not read the variable. Supply the token from a trusted source instead:

  • Local development, once per machine: pnpm config set "//npm.pkg.github.com/:_authToken" "<your PAT>" (a classic PAT with read:packages). This writes to pnpm's user-level config store, which pnpm does trust to expand.
  • GitHub Actions: use actions/setup-node@v7 with registry-url: https://npm.pkg.github.com, and set NODE_AUTH_TOKEN from a secret on the install step — this is the mechanism this repo's own release.yml already uses successfully.
  • Docker or a deploy server: write the user-level file at build/deploy time from a secret, e.g. echo "//npm.pkg.github.com/:_authToken=$NODE_AUTH_TOKEN" > ~/.npmrc, never committed and never baked into an image layer.

If the app sets minimumReleaseAge, also add minimumReleaseAgeExclude: ['@jainparichay/*'] — otherwise new releases are unresolvable until the buffer elapses.

Then: pnpm add @jainparichay/db @jainparichay/ui

@jainparichay/db and @jainparichay/ui ship both ESM and CommonJS (each has a require condition alongside import); the rest are ESM-only. From a CommonJS app depending on an ESM-only package, load it with await import('@jainparichay/…').

Using @jainparichay/db

This package only handles the database connection — it owns no schema. Each consuming app defines its own prisma/schema.prisma, runs its own prisma generate, and passes its own generated PrismaClient in:

import { createDatabaseClient } from '@jainparichay/db';
import { PrismaClient } from '@prisma/client'; // the app's own generated client

export const db = createDatabaseClient(
  (adapter) => new PrismaClient({ adapter }),
);

createDatabaseClient validates DATABASE_URL (or an explicit connectionString option), builds a PrismaPg adapter, and — outside production — caches the resulting client on globalThis so hot reloads don't open a new connection pool each time. Pass cache: false to opt out, or a globalKey to namespace multiple databases in one process (e.g. when Astro and NestJS share a process but talk to different databases). Call resetDatabaseClient with the same connectionString or globalKey to clear a cached entry, which is useful between test files.

Caching is not unconditional. The cache defaults to cache: process.env.NODE_ENV !== 'production' — it's on in development (to survive hot reloads) and off in production. The globalThis cache itself is shared correctly across the package's CJS and ESM entry points (both require() and import resolve to the same module-level state, so there's no dual-package hazard from the dual build). But with caching off, a process that loads both entries — for example a graph where one dependency require()s @jainparichay/db and another imports it — will construct two separate PrismaClient instances and two separate connection pools under NODE_ENV=production, since nothing is deduplicating uncached calls. This isn't reachable in today's single-importer app graphs, but it becomes possible now that a require condition exists, so don't assume the singleton holds under NODE_ENV=production without checking whether every entry point in your dependency graph actually uses the same module condition.

@prisma/adapter-pg is a peer dependency of this package — install it in the app alongside @prisma/client and prisma, matching major versions. The package re-exports its PrismaPg type so callbacks can be typed from the app's own installed copy:

import { createDatabaseClient, type PrismaPg } from '@jainparichay/db';

App-local packages

These packages hold generic, cross-app code only. An app may still keep its own packages/ui, packages/types, etc. under its own scope (e.g. @myapp/ui) that wrap, extend, or re-export the shared ones. Promote code here only once a second app needs it.

Releasing

  1. pnpm changeset — describe the change, pick bump levels.
  2. Merge the PR; the release workflow opens a "Version Packages" PR.
  3. Merge the version PR; packages publish automatically.

How releasing actually works here. changesets/action publishes whenever there are no pending changesets — it treats the versions currently in package.json as ready to ship. Always land your changeset in the same push as your code, and let the generated Version Packages PR perform the version bump.

Because of that, the version field in every package.json is owned by the changesets bot. Never edit a version by hand on main: the next push to main would publish it immediately, with no review step and no way to take it back. A published version can only be superseded, never corrected.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages