@jpcw/configs
v2.0.0
Published
Shared TypeScript / ESLint / Prettier configs and CLI helpers for JPCW projects (SuiteScript, React, and React Native presets).
Readme
@jpcw/configs
Shared TypeScript / ESLint / Prettier configs and a small CLI for JPCW projects.
In honor and memory of Forrest Jones. C# > TS.
Three 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 NS runtime) and requires the@NApiVersion/@NScriptTypegovernance JSDoc on files underSuiteScripts/. Ships a separatetsconfig.spa.jsonfor 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)
Modern flat-config ESLint (no airbnb / no FlatCompat), projectService: true for fast type-aware lint, Prettier owns formatting.
Install in a new project
init scaffolds everything: .gitignore, .editorconfig, tsconfig.json, eslint.config.mjs, prettier.config.mjs, .vscode/settings.json, and a starter package.json with deps already wired up. It's idempotent — re-running on an existing project only adds what's missing.
SuiteScript
mkdir my-suitescript-project && cd my-suitescript-project
git init
npx -p @jpcw/configs jpcw-configs init suitescript --pm yarn # or --pm npm | --pm bun
yarn installReplace the PROJECT_NAME and REPLACE_WITH_SDF_AUTH_ID_* placeholders in package.json, then yarn install.
The scaffolded tsconfig.json extends @jpcw/configs/suitescript/tsconfig.json. Want full strict mode? Switch the extends to @jpcw/configs/suitescript/tsconfig.strict.json.
React (web)
mkdir my-react-project && cd my-react-project
git init
npx -p @jpcw/configs jpcw-configs init react --pm bun # or yarn | npm
bun install # match your --pmReact Native (Expo)
mkdir my-rn-project && cd my-rn-project
git init
npx -p @jpcw/configs jpcw-configs init react-native --pm yarn
yarn installThe RN preset assumes Expo + Expo Router. If you're 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) |
| .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) |
| .yarnrc.yml | Yarn-only, with nodeLinker: node-modules (required for SDF tooling on suitescript) |
Migrate an existing project
If you currently extend @interiorworx/netsuite-customization-configs (or have raw inlined configs):
Install the package alongside what's there. It won't conflict.
yarn add -D @jpcw/configsRun
init. It only adds missing scripts/devDependencies and skips files that already exist (--forceoverrides.gitignore).npx @jpcw/configs init suitescriptinitadds deps at the template's pinned versions. If you're migrating an old repo and want the toolchain at current versions (instead of bumpingeslint/typescript/etc. by hand, as you may have been doing), follow withupgrade— or scaffold withinit suitescript --latestto do both at once:npx @jpcw/configs upgrade suitescript # toolchain → current npx @jpcw/configs upgrade suitescript --dry-run # preview firstIf you had
tsconfig.json/eslint.config.mjs/prettier.config.mjs,initskipped them. Either delete yours and re-run, or swap theextends/ re-export by hand:- "extends": "./node_modules/@interiorworx/netsuite-customization-configs/configs/tsconfig.json", + "extends": "@jpcw/configs/suitescript/tsconfig.json",Replace any old
.eslintrc.jsonwith the scaffoldedeslint.config.mjs(ESLint 9 flat config) and delete the old file.Replace any old
.prettierrcwith the scaffoldedprettier.config.mjsand delete the old file.Replace
writeProjectJSON.jscalls inpackage.jsonscripts with the CLI:- "MWC-SB": "node writeProjectJSON.js SB", - "MWC-PROD": "node writeProjectJSON.js PROD", + "MWC-SB": "jpcw-configs write-project-json --auth 7027364_SB1-Adm-Sand", + "MWC-PROD": "jpcw-configs write-project-json --auth 7027364-Adm-Prod",Then delete
writeProjectJSON.jsfrom the repo.Drop the old dep:
yarn remove @interiorworx/netsuite-customization-configsVerify:
yarn typecheck yarn lint yarn format yarn run MWC-SB # or your env script
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 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 when you init into an old client 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-runThe 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. - Framework / native (react, react-dom, expo, expo-router, react-native, …) — version-sensitive, so skipped unless
--include-frameworks. For thereact-nativepreset these never go to npm-latest (that breaks the Expo SDK); they're realigned vianpx 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). Replaces the per-project writeProjectJSON.js pattern.
jpcw-configs write-project-json --auth 7027364_SB1-Adm-Sand| 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 |
Maintaining this package
Branching / git hygiene
Work on main for small changes, branch for anything that touches preset behavior (rule additions/removals are user-visible). Tag every published version (npm version does this for you).
git checkout -b feat/some-change
# ...edits...
git add -A
git commit -m "feat(react): add some-change"
git push -u origin feat/some-change
gh pr create
# after merge:
git checkout main && git pullBumping the version
Use npm version so the git tag and package.json stay in lockstep. Pick:
patch— bug fix, internal refactor, doc changes (no rule changes)minor— new preset, new rule additions, new CLI flagmajor— rule removals, rule severity bumps (warn→error), config option renames, dropping a preset, anything that could break a downstream lint or build
# from a clean main
npm version patch # or minor / major
git push --follow-tagsnpm version will:
- bump
versioninpackage.json - create a commit (
v0.2.1) - create a matching git tag
Publishing to npm
The package is published as @jpcw/configs with public access. You need to be logged in (npm whoami to check; npm login if not).
The convenience scripts in package.json chain bump → publish → push:
yarn release:patch # bump patch, publish, push tags
yarn release:minor
yarn release:majorIf you've already bumped manually:
yarn publish:current # = npm publish --access publicAfter publishing, smoke-test on a real client repo:
cd ~/git/clients/<some-project>
yarn add -D @jpcw/configs@latest
yarn install
yarn lint && yarn typecheckPre-publish checklist
- [ ] Updated
README.mdif behavior or flags changed - [ ] Bumped template
@jpcw/configsversion pins (suitescript/react/react-nativetemplates/package.json) if the version is a major bump - [ ] Ran
yarn installlocally —.pnp.cjs/yarn.lockare clean - [ ] No stray
console.log/ debug code insrc/cli/ - [ ] Tag and tarball look right:
npm pack --dry-run
What goes in the tarball
Controlled by files in package.json. As of 0.2.x:
bin/ # jpcw-configs CLI entry
src/ # CLI source
suitescript/ # preset configs + templates
react/ # preset configs + templates
react-native/ # preset configs + templates
README.md
LICENSE.idea/, yarn.lock, .pnp.cjs and the like are excluded.
Versioning
Semver. Breaking changes to any preset are major bumps; new rules / new lints are minor.
