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

@jpcw/configs

v2.5.0

Published

Shared TypeScript / ESLint / Prettier configs and CLI helpers for JPCW projects (SuiteScript, React, and React Native presets).

Readme

@jpcw/configs

Opinionated TypeScript / ESLint / Prettier presets and a small CLI: scaffold a fully configured project in one command, keep the toolchain current without hand-editing pins, and run a quieter tsc --watch.

In honor and memory of Forrest Jones. C# > TS.

Why

Every TypeScript repo carries the same half-dozen config files, and they drift the moment they're copy-pasted. This package centralizes them: your repo takes one dev dependency and a handful of one-line files that extend / re-export a preset. Update the package, and every repo follows.

  • Modern by default — ESLint 9+ flat config (no airbnb, no FlatCompat), fast type-aware linting via projectService: true, Prettier owns all formatting.
  • NetSuite as a first-class target — generic presets get SuiteScript wrong; the suitescript preset targets the actual runtime (AMD/ES2021 output, CRLF) and lints for its constraints.
  • A CLI for the boring partsinit scaffolds everything, upgrade re-resolves the toolchain to current versions, watch is an incremental tsc --watch that reports only what changed.

Presets

  • suitescript — NetSuite SuiteScript 2.x. TS targeting AMD/ES2021, CRLF, modern typescript-eslint. Lints Node.js built-in imports as errors (they don't exist in the NetSuite runtime), requires the @NApiVersion / @NScriptType governance JSDoc on files under SuiteScripts/ (miscased tags like @NAPIVersion break NetSuite's loader and are auto-corrected by eslint --fix), and enforces the entry-point contract: .ue.ts/.mr.ts/etc. files must declare the @NScriptType matching their suffix and export that script type's entry-point function(s) — deploy-time failures caught at lint time. Ships a separate tsconfig.spa.json for React SPAs bundled into a Suitelet.
  • react — React for the web (Vite + ES2022 + JSX, LF, jsx-a11y).
  • react-native — React Native / Expo (no DOM lib, __DEV__ global, jsx: react-native).

Quick start

mkdir my-project && cd my-project
git init
npx -p @jpcw/configs jpcw-configs init suitescript --pm yarn   # or react | react-native; --pm npm | bun
yarn install                                                   # match your --pm

init scaffolds everything: .gitignore, .gitattributes, .editorconfig, tsconfig.json, eslint.config.mjs, prettier.config.mjs, .vscode/settings.json, a CI workflow, a pre-commit hook (lint-staged on staged files), CLAUDE.md + .claude/settings.json for Claude Code, and a starter package.json with deps already wired up. It's idempotent — re-running on an existing project only adds what's missing (doctor --fix does the same for repos scaffolded by older versions).

Preset notes:

  • suitescript — replace the PROJECT_NAME and REPLACE_WITH_SDF_AUTH_ID_* placeholders in package.json, then install. Want full strict mode? Switch the tsconfig extends to @jpcw/configs/suitescript/tsconfig.strict.json.
  • react-native — assumes Expo + Expo Router. On bare RN, drop expo-router from package.json and adjust main.

What gets written

| File | Purpose | |---|---| | .gitignore | Per-preset ignores (Node, build artifacts, IDE, secrets, plus SDF for suitescript / native + Expo for react-native) | | .gitattributes | Line endings pinned at the git layer (CRLF working tree for suitescript, LF otherwise) — checkouts stop depending on each machine's autocrlf | | .prettierignore | Per-preset Prettier ignores (build output, lockfiles; native dirs for react-native) | | tsconfig.spa.json | suitescript only — bundler/react-jsx tsconfig for a React SPA served by a Suitelet (source under src/spa/) | | .editorconfig | Tabs/EOL source of truth (CRLF for suitescript, LF for react/react-native) | | .vscode/settings.json | Format-on-save, ESLint flat-config mode, Prettier as default formatter | | tsconfig.json | Extends the preset; project-specific paths/include filled in | | eslint.config.mjs | One-line re-export of the preset | | prettier.config.mjs | One-line re-export of the preset | | package.json | Pinned deps, lint/lint:fix/format/format:write/typecheck scripts, SDF auth scripts (suitescript), lint-staged config + a postinstall that wires the pre-commit hook | | .githooks/pre-commit | Runs lint-staged (Prettier + eslint --fix on staged files only); wired via git config core.hooksPath .githooks in postinstall | | .github/workflows/ci.yml | Thin caller of this repo's centrally maintained reusable-ci.yml — lint + typecheck + format check on push/PR, package-manager auto-detected | | CLAUDE.md | Per-preset starter notes for Claude Code (commands, conventions — e.g. the "script records are created in the NetSuite UI" rule for suitescript) | | .claude/settings.json | Claude Code permission allowlist for the standard scripts (fewer prompts in fresh repos) | | .yarnrc.yml | Yarn-only: nodeLinker: node-modules (required for SDF tooling on suitescript) + npmPreapprovedPackages for @jpcw/* (Yarn 4's age gate otherwise blocks fresh releases) |


Migrate an existing project

init is safe to run on a non-empty repo — it only adds what's missing and skips files that already exist (--force overrides .gitignore).

  1. Add the package and run init:

    yarn add -D @jpcw/configs
    npx jpcw-configs init suitescript        # or react | react-native

    init adds deps at the template's pinned versions. Migrating an older repo? Follow with upgrade to bring the toolchain to current versions — or scaffold with init suitescript --latest to do both at once.

  2. If you already had tsconfig.json / eslint.config.mjs / prettier.config.mjs, init skipped them. Either delete yours and re-run, or point them at the preset by hand:

    - "extends": "./configs/tsconfig.base.json",
    + "extends": "@jpcw/configs/suitescript/tsconfig.json",
  3. Replace any legacy .eslintrc* with the scaffolded eslint.config.mjs (ESLint 9 flat config), and any .prettierrc* with prettier.config.mjs. Delete the old files — ESLint and Prettier will pick up the old ones first otherwise.

  4. Verify:

    npx jpcw-configs doctor
    yarn typecheck && yarn lint && yarn format

    doctor re-run any time later catches drift (new scaffold files added by newer @jpcw/configs versions, lost files, package.json gaps) — --fix applies the additive repairs.


CLI reference

jpcw-configs init <preset>

Scaffolds a project with the preset's config files. Idempotent — re-running only adds what's missing.

jpcw-configs init suitescript --pm yarn
jpcw-configs init react       --pm bun
jpcw-configs init react-native --pm yarn

| Flag | Default | Behavior | |---|---|---| | --pm <yarn\|npm\|bun> | yarn | Pins packageManager in package.json and drops in PM-specific files (e.g. .yarnrc.yml). | | --force | off | Overwrites an existing .gitignore. Other config files are skipped if they already exist (delete first to re-scaffold). | | --latest | off | After scaffolding, runs upgrade <preset> so the toolchain installs at current versions instead of the template pins. |

jpcw-configs doctor [preset]

The drift check init isn't: audits an existing repo against its preset and reports findings — missing scaffold files, package.json gaps (scripts, deps, packageManager, private, lint-staged), legacy .eslintrc*/.prettierrc* files shadowing the flat config, a TS 7 install that breaks the toolchain, or an @jpcw/configs pin a major behind. The preset is auto-detected from the repo's configs; pass it only if detection fails.

jpcw-configs doctor            # report
jpcw-configs doctor --fix      # apply the additive fixes
jpcw-configs doctor --json     # machine-readable, for scripting across repos

--fix is additive only — it copies missing files and fills package.json gaps, and never overwrites or deletes anything (legacy configs are reported for manual cleanup). Exits non-zero while warnings/errors remain, so it works as a CI or fleet-script gate. Typical fleet sweep: run doctor --fix in each repo after bumping @jpcw/configs.

| Flag | Default | Behavior | |---|---|---| | --fix | off | Apply fixable findings (copy missing files, merge package.json gaps) | | --json | off | JSON findings instead of human output | | --pm <yarn\|npm\|bun> | auto | Package manager used when filling packageManager |

jpcw-configs upgrade <preset>

The template package.json ships reproducible pinned versions — good for a deterministic scaffold, but they go stale. upgrade resolves the managed dependency set to whatever is current at the moment you run it, by delegating to your package manager. Run it the day you scaffold, or a year later on an old repo — it picks up whatever is newest then, with no template re-pinning required.

jpcw-configs upgrade suitescript                     # bump the toolchain to latest
jpcw-configs upgrade react --include-frameworks      # also bump react/vite
jpcw-configs upgrade react-native --include-frameworks --dry-run

The managed set is read straight from the preset template, so it tracks the preset automatically. Deps are split:

  • Toolchain (eslint, prettier, typescript, @jpcw/configs, @types/*, vite, …) — always taken at @latest. The preset is built around current tooling. Exception: typescript is capped at 6.x — TS 7 (the native compiler) drops the JS compiler API (watch, type-aware linting) and AMD emit (the suitescript output format), so moving to it is a deliberate migration, not an upgrade.
  • Framework / native (react, react-dom, expo, expo-router, react-native, …) — version-sensitive, so skipped unless --include-frameworks. For the react-native preset these never go to npm-latest (that breaks the Expo SDK); they're realigned via npx expo install expo@latest && npx expo install --fix, which keeps them SDK-correct.

| Flag | Default | Behavior | |---|---|---| | --pm <yarn\|npm\|bun> | auto | Detected from packageManager / lockfile if omitted. | | --include-frameworks | off | Also upgrade framework/native deps (Expo via expo install). | | --dry-run | off | Print the package-manager commands without running them. |

jpcw-configs write-project-json --auth <id>

Writes a SuiteCloud SDK project.json (pretty-printed), so switching the target NetSuite account is a one-line package.json script instead of a hand-maintained helper file.

jpcw-configs write-project-json --auth MY_SDF_AUTH_ID

| Flag | Default | Meaning | |---|---|---| | --auth | required | SDF auth ID for the target NetSuite account | | --asv | ERROR | accountSpecificValues strategy (ERROR or WARNING) | | --out | project.json | output path, relative to cwd |

jpcw-configs ns-upload [files...]

Uploads one or more File Cabinet files to the active NetSuite account (the project.json found at or above cwd) via suitecloud file:upload — so a multi-file selection uploads in one keystroke, where the IDE plugins only handle a single file. Selecting either half of a .ts/.js pair uploads both. Files must live under src/FileCabinet.

jpcw-configs ns-upload src/FileCabinet/SuiteScripts/jpcw/lib/a.lib.ts
jpcw-configs ns-upload --from-clipboard    # VS Code multi-select hook

Uploads go to whatever account project.json targets. The banner (and the --notify toast) names the account, flagged PRODUCTION when the auth ID doesn't look like a dev/sandbox one (sb / sand / tstdrv / dev).

VS Code multi-select in one keystroke: add a user-level task (Tasks: Open User Tasks) and keybinding, and it works in every SDF repo with no per-repo files:

// User Tasks — reveal: silent keeps focus in the editor (terminal only pops
// on failure); --notify toasts when the upload finishes instead
{ "label": "NS: Upload selected", "type": "shell",
  "command": "npx jpcw-configs ns-upload --from-clipboard --notify",
  "presentation": { "reveal": "silent", "focus": false, "panel": "shared", "clear": true } }
// keybindings.json — copies ALL selected explorer paths, then runs the task
{ "key": "shift+alt+y", "command": "runCommands",
  "args": { "commands": ["copyFilePath",
    { "command": "workbench.action.tasks.runTask", "args": "NS: Upload selected" }] },
  "when": "filesExplorerFocus" }

| Flag | Default | Behavior | |---|---|---| | --from-clipboard | off | Read newline-separated paths from the clipboard (accepts WSL, relative, or \\wsl.localhost\... UNC paths) | | --dry-run | off | Print the suitecloud command without running it | | --notify | off | Desktop notification (Windows toast from WSL, else notify-send) when the upload finishes or fails |

jpcw-configs watch

Incremental TypeScript watch mode (type-check + emit, same as tsc --watch) with delta-aware reporting. tsc --watch already re-checks only changed files internally, but it re-prints every error in the project on every pass; watch drives the same incremental compiler via the API and reports the diff instead:

── 9:02:16 AM ── recompiling… ──────────────────────────

a.ts — fixed (was 1) ✔
  src/a.ts

b.ts — 1 error
  src/b.ts

  src/b.ts:3:7 TS2322: Type 'number' is not assignable to type 'string'.

Watching… ✖ 1 error in 1 file  (▼1)
  • Every pass ends with the current state on the last line: Watching… ✖ 13 errors in 5 files (▼1) ( in red when the count went up). Passes are separated by a timestamped divider.
  • Full diagnostics only for files whose error set changed — whether saved directly or broken/fixed as a ripple effect of a change elsewhere (tagged [affected by your change]). Each error prints as path:line:col, which IDE terminals hyperlink straight to the error.
  • Files that go clean get a one-time fixed ✔ line; files whose errors didn't change aren't listed at all (the summary line carries the totals).
  • On startup, per-file error counts only — details print as files change.

Uses the project's own typescript install, so it always agrees with the version the repo type-checks against.

| flag | default | | | --- | --- | --- | | -p, --project | nearest tsconfig.json | tsconfig to use | | --no-color | | disable ANSI colors (also honors NO_COLOR) |

jpcw-configs setup-watch

Sets up incremental TypeScript watch-mode compilation for the project — a long-running jpcw-configs watch (see above) that only recompiles what changed, instead of a per-save IDE File Watcher spawning a full non-incremental compile every time. Run from the project root. Idempotent:

  • Adds "watch": "jpcw-configs watch" to package.json scripts. A watch script that still holds the old default (tsc --watch) is upgraded in place; anything else is left alone with a warning.
  • Writes .vscode/tasks.json — a watch task (type: npm, $tsc-watch problem matcher) with "runOptions": { "runOn": "folderOpen" }, so the watcher starts when the project opens. Committed to git, so it's available to everyone who opens the project. If the file already exists, it's left alone and the task JSON is printed for you to add manually.
npx @jpcw/configs setup-watch

One manual step (per repo, per machine): VS Code won't auto-run workspace tasks until you allow it — run Tasks: Manage Automatic Tasks → Allow Automatic Tasks, or just accept the prompt the first time the folder opens.


Versioning

Semver. Breaking changes to any preset (rule removals, severity bumps) are major; new rules / new lints / new CLI flags are minor. Per-version notes live in CHANGELOG.md; maintainer notes in MAINTAINING.md.