chore: scaffold @acamarata/tsconfig 0.1.0

Four JSON tsconfig presets for acamarata packages: base (strict/ES2022/bundler),
library (declaration output), node (CommonJS), react (jsx:react-jsx/DOM). JSON-only
package — no build step. Includes validation script and CI workflow.
This commit is contained in:
Aric Camarata 2026-05-28 12:30:48 -04:00
commit 47b729f6c7
12 changed files with 339 additions and 0 deletions

64
.github/workflows/ci.yml vendored Normal file
View file

@ -0,0 +1,64 @@
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
name: Validate JSON (Node ${{ matrix.node-version }})
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20, 22, 24]
steps:
- uses: actions/checkout@v4
- name: Setup Node ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- name: Enable corepack
run: corepack enable
- name: Install dependencies
run: pnpm install
- name: Validate JSON configs
run: pnpm test
pack-check:
name: Pack check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node 24
uses: actions/setup-node@v4
with:
node-version: 24
cache: 'pnpm'
- name: Enable corepack
run: corepack enable
- name: Install dependencies
run: pnpm install
- name: Pack
run: npm pack
- name: Verify pack contents
run: |
tar -tf *.tgz | sort
tar -tf *.tgz | grep -q "package/tsconfig.base.json" || (echo "MISSING: tsconfig.base.json" && exit 1)
tar -tf *.tgz | grep -q "package/tsconfig.library.json" || (echo "MISSING: tsconfig.library.json" && exit 1)
tar -tf *.tgz | grep -q "package/tsconfig.node.json" || (echo "MISSING: tsconfig.node.json" && exit 1)
tar -tf *.tgz | grep -q "package/tsconfig.react.json" || (echo "MISSING: tsconfig.react.json" && exit 1)
tar -tf *.tgz | grep -q "package/README.md" || (echo "MISSING: README.md" && exit 1)
tar -tf *.tgz | grep -q "package/LICENSE" || (echo "MISSING: LICENSE" && exit 1)
echo "Pack check passed"

14
.gitignore vendored Normal file
View file

@ -0,0 +1,14 @@
node_modules/
.DS_Store
*.tgz
.claude/
.vscode/*
.idea/
.codex/
.cursor/
.aider/
.aider.chat.history.md
.continue/
.windsurf/
.gemini/
.codeium/

0
.npmrc Normal file
View file

19
CHANGELOG.md Normal file
View file

@ -0,0 +1,19 @@
# Changelog
All notable changes to this project will be documented in this file.
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [0.1.0] - 2026-05-28
### Added
- `tsconfig.base.json`: strict base config with ES2022 target, bundler module resolution, `noUncheckedIndexedAccess`, `exactOptionalPropertyTypes`
- `tsconfig.library.json`: extends base, adds declaration output for publishable libraries (ESNext module, `declarationMap`, `sourceMap`)
- `tsconfig.node.json`: extends base, targets CommonJS for Node.js tools and scripts
- `tsconfig.react.json`: extends base, adds `jsx: react-jsx` and DOM lib for React applications
- JSON validation script (`scripts/validate-json.mjs`) to verify all variants parse and contain expected keys
- CI workflow validating JSON on Node 20, 22, and 24

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 Aric Camarata
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

66
README.md Normal file
View file

@ -0,0 +1,66 @@
# @acamarata/tsconfig
Shared TypeScript configs for acamarata packages. Four variants covering the common cases: a strict base, a publishable library, a Node.js tool, and a React app.
## Install
```sh
pnpm add -D @acamarata/tsconfig
```
## Variants
| Config | Extends | Use case |
|--------|---------|----------|
| `tsconfig.base.json` | — | Strict base. All other variants extend this. Use it directly only if none of the others fit. |
| `tsconfig.library.json` | base | Publishable npm libraries. ESNext modules, `declaration: true`, `declarationMap: true`, `sourceMap: true`. |
| `tsconfig.node.json` | base | Node.js tools and scripts. CommonJS output, `@types/node` included. |
| `tsconfig.react.json` | base | React apps. Adds `jsx: react-jsx` and the DOM lib. |
## Usage
In your `tsconfig.json`, set `extends` to the variant that matches your project:
```json
{
"extends": "@acamarata/tsconfig/tsconfig.library.json",
"compilerOptions": {
"rootDir": "src"
},
"include": ["src"]
}
```
For a Node.js CLI tool:
```json
{
"extends": "@acamarata/tsconfig/tsconfig.node.json",
"compilerOptions": {
"rootDir": "src"
},
"include": ["src"]
}
```
For a React app:
```json
{
"extends": "@acamarata/tsconfig/tsconfig.react.json",
"include": ["src"]
}
```
## What the base config enables
- `strict: true` — the full strict family of checks
- `skipLibCheck: true` — skips checking declaration files in `node_modules`
- `noUncheckedIndexedAccess: true` — array index access includes `undefined` in the type
- `exactOptionalPropertyTypes: true` — distinguishes `{ x?: string }` from `{ x: string | undefined }`
- `target: ES2022` — modern output; no polyfill overhead for `async/await`, `class fields`, `at()`
- `moduleResolution: bundler` — resolves `.ts` extensions naturally in bundler pipelines (tsup, Vite, esbuild)
## License
MIT

48
package.json Normal file
View file

@ -0,0 +1,48 @@
{
"name": "@acamarata/tsconfig",
"version": "0.1.0",
"description": "Shared TypeScript configs for acamarata packages. Four variants: base, library, node, and react.",
"author": "Aric Camarata",
"license": "MIT",
"exports": {
"./tsconfig.base.json": "./tsconfig.base.json",
"./tsconfig.library.json": "./tsconfig.library.json",
"./tsconfig.node.json": "./tsconfig.node.json",
"./tsconfig.react.json": "./tsconfig.react.json",
"./package.json": "./package.json"
},
"files": [
"tsconfig.base.json",
"tsconfig.library.json",
"tsconfig.node.json",
"tsconfig.react.json",
"README.md",
"CHANGELOG.md",
"LICENSE"
],
"scripts": {
"test": "node scripts/validate-json.mjs"
},
"engines": {
"node": ">=20"
},
"repository": {
"type": "git",
"url": "git+https://github.com/acamarata/tsconfig.git"
},
"homepage": "https://github.com/acamarata/tsconfig#readme",
"bugs": {
"url": "https://github.com/acamarata/tsconfig/issues"
},
"keywords": [
"typescript",
"tsconfig",
"config",
"acamarata"
],
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org/"
},
"packageManager": "pnpm@10.11.1"
}

56
scripts/validate-json.mjs Normal file
View file

@ -0,0 +1,56 @@
/**
* Purpose: Validate that all tsconfig JSON files parse without error and contain expected keys.
* Inputs: none reads tsconfig.*.json from package root
* Outputs: pass/fail per file to stdout; exits 1 on any failure
* Constraints: runs with Node built-in fs no deps
*/
import { readFileSync } from 'fs';
const variants = [
{ file: 'tsconfig.base.json', requiredKeys: ['compilerOptions'] },
{ file: 'tsconfig.library.json', requiredKeys: ['extends', 'compilerOptions'] },
{ file: 'tsconfig.node.json', requiredKeys: ['extends', 'compilerOptions'] },
{ file: 'tsconfig.react.json', requiredKeys: ['extends', 'compilerOptions'] },
];
const compilerOptionChecks = {
'tsconfig.base.json': ['strict', 'skipLibCheck', 'noUncheckedIndexedAccess', 'exactOptionalPropertyTypes'],
'tsconfig.library.json': ['declaration', 'declarationMap', 'sourceMap', 'outDir', 'module'],
'tsconfig.node.json': ['declaration', 'declarationMap', 'sourceMap', 'outDir', 'module'],
'tsconfig.react.json': ['declaration', 'declarationMap', 'sourceMap', 'outDir', 'jsx'],
};
let failed = false;
for (const { file, requiredKeys } of variants) {
try {
const content = readFileSync(new URL(`../${file}`, import.meta.url), 'utf8');
const parsed = JSON.parse(content);
for (const key of requiredKeys) {
if (!(key in parsed)) {
console.error(`FAIL ${file}: missing top-level key "${key}"`);
failed = true;
}
}
const expectedCompilerOptions = compilerOptionChecks[file] ?? [];
for (const opt of expectedCompilerOptions) {
if (!(opt in (parsed.compilerOptions ?? {}))) {
console.error(`FAIL ${file}: missing compilerOptions.${opt}`);
failed = true;
}
}
if (!failed) {
console.log(`PASS ${file}`);
}
} catch (err) {
console.error(`FAIL ${file}: ${err.message}`);
failed = true;
}
}
if (failed) {
process.exit(1);
}

14
tsconfig.base.json Normal file
View file

@ -0,0 +1,14 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"target": "ES2022",
"moduleResolution": "bundler",
"strict": true,
"skipLibCheck": true,
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"allowImportingTsExtensions": false
}
}

11
tsconfig.library.json Normal file
View file

@ -0,0 +1,11 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "./tsconfig.base.json",
"compilerOptions": {
"module": "ESNext",
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"outDir": "dist"
}
}

13
tsconfig.node.json Normal file
View file

@ -0,0 +1,13 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "./tsconfig.base.json",
"compilerOptions": {
"module": "CommonJS",
"target": "ES2022",
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"outDir": "dist",
"types": ["node"]
}
}

13
tsconfig.react.json Normal file
View file

@ -0,0 +1,13 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "./tsconfig.base.json",
"compilerOptions": {
"module": "ESNext",
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"outDir": "dist",
"jsx": "react-jsx",
"lib": ["ES2022", "DOM", "DOM.Iterable"]
}
}