Skip to content

Commit 113b9df

Browse files
authored
fix: update .npmignore comments and refine build script for npm publishing (#13)
* fix: update .npmignore comments and refine build script for npm publishing * feat: add CONTRIBUTING.md and CHANGELOG.md for project guidelines and release history * refactor: update release scripts and documentation for consistency * feat: enhance README and add package metadata usage examples; update ESLint config and consumer scripts
1 parent f91dc97 commit 113b9df

12 files changed

Lines changed: 209 additions & 56 deletions

File tree

.changeset/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ This repository uses Changesets for versioning and changelog automation.
66

77
```bash
88
npm run changeset
9-
npm run changeset:version
10-
npm run changeset:publish
9+
npm run release:version
10+
npm run release:changesets
1111
```
1212

1313
Create a changeset whenever a pull request changes the published package in a way

.github/workflows/release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ jobs:
3131
- name: Create release PR or publish package
3232
uses: changesets/action@v1
3333
with:
34-
version: npm run changeset:version
35-
publish: npm run release:publish
34+
version: npm run release:version
35+
publish: npm run release:changesets
3636
commit: 'chore: version package'
3737
title: 'chore: version package'
3838
env:

.npmignore

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
# This project uses `"files": ["dist"]` in package.json, so only files under
2-
# dist/ (plus standard top-level files like README/LICENSE) are published.
3-
# These patterns therefore only affect the contents of dist/, not the repo root.
4-
5-
# Build artifacts that should not be published
1+
# This project publishes via `"files": ["dist"]` in package.json, which is the
2+
# primary allowlist for package contents. `.npmignore` still applies across the
3+
# packed artifact and can affect top-level files as well, so the negations
4+
# below explicitly preserve the root README and LICENSE.
65
*.tsbuildinfo
76
*.map
7+
!README.md
8+
!LICENSE

CHANGELOG.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6+
and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
This repository uses [Changesets](https://github.com/changesets/changesets) to
9+
manage versioning and changelog generation. Release entries are created from
10+
merged changesets during the release process.
11+
12+
## Unreleased
13+
14+
- No unreleased entries yet.
15+
16+
## 1.0.0 - 2026-04-02
17+
18+
### Added
19+
20+
- Initial public release of `@coderrob/typescript-type-guards`.
21+
- A reusable TypeScript type guard library with primitive, numeric,
22+
collection, object-like, and utility guards.
23+
- Generic factory helpers for constructor-based and enum-based narrowing via
24+
`createTypeGuard` and `createEnumGuard`.
25+
- Behavioral runtime tests with strong coverage expectations for positive and
26+
negative guard usage.
27+
- Repository quality tooling for formatting, linting, typechecking, duplicate
28+
detection, and automated package verification.
29+
- npm packaging support files, including publish-oriented ignore rules and
30+
package metadata hardening.
31+
- Project documentation and branding, including the package README and logo.
32+
33+
### Changed
34+
35+
- Expanded the guard surface and test coverage as the library matured toward
36+
the `1.0.0` release.
37+
- Refined npm publishing behavior and package build output for release
38+
readiness.
39+
40+
### Security
41+
42+
- Updated transitive dependencies through Dependabot-driven maintenance,
43+
including `brace-expansion`, `flatted`, `picomatch`, and `handlebars`.

CONTRIBUTING.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Contributing
2+
3+
## Requirements
4+
5+
- Node.js `^20.19.0`, `^22.13.0`, or `>=24.0.0`
6+
- npm
7+
8+
## Setup
9+
10+
```bash
11+
npm ci
12+
```
13+
14+
## Development Workflow
15+
16+
1. Create a branch from `main`.
17+
2. Make the smallest coherent change that solves the problem.
18+
3. Add or update runtime tests, type tests, and documentation as needed.
19+
4. Run the verification commands before opening a pull request.
20+
5. Add a changeset if the published package behavior changes.
21+
22+
## Verification
23+
24+
Run the full local gate:
25+
26+
```bash
27+
npm run verify
28+
```
29+
30+
Run coverage separately when needed:
31+
32+
```bash
33+
npm run test:coverage
34+
```
35+
36+
Useful focused commands:
37+
38+
```bash
39+
npm run lint
40+
npm run typecheck
41+
npm test
42+
npm run build
43+
npm run test:package
44+
npm run bench
45+
npm run publish:package
46+
```
47+
48+
## Testing Expectations
49+
50+
- Add positive and negative behavioral coverage for runtime guards.
51+
- Keep type-level narrowing coverage current in `src/__tests__/narrowing.types.ts`.
52+
- Preserve the per-file coverage threshold enforced by the repository scripts.
53+
- Keep consumer smoke tests passing for both CommonJS and ESM package usage.
54+
55+
## Changesets
56+
57+
Create a changeset whenever a pull request changes the published package in a
58+
way that should produce a version bump or release note entry.
59+
60+
```bash
61+
npm run changeset
62+
```
63+
64+
Changesets are applied during release with:
65+
66+
```bash
67+
npm run release:version
68+
```
69+
70+
Changesets can be published with:
71+
72+
```bash
73+
npm run release:changesets
74+
```
75+
76+
## Packaging Notes
77+
78+
- The package publishes built files from `dist/`.
79+
- The root `README.md`, `LICENSE`, and `package.json` are included in the npm
80+
tarball automatically.
81+
- Source maps are intentionally not published.
82+
83+
## Pull Requests
84+
85+
- Keep pull requests focused.
86+
- Update documentation when behavior, packaging, or workflow changes.
87+
- Do not relax quality gates to make a change pass. Fix the code, tests, or
88+
tooling instead.

README.md

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,20 @@ import { isString } from '@coderrob/typescript-type-guards';
8989
const { isString } = require('@coderrob/typescript-type-guards');
9090
```
9191

92+
Package metadata can also be resolved explicitly when needed:
93+
94+
```js
95+
const packageMetadata = require('@coderrob/typescript-type-guards/package.json');
96+
```
97+
98+
```ts
99+
import packageMetadata from '@coderrob/typescript-type-guards/package.json' with { type: 'json' };
100+
```
101+
92102
Type declarations are emitted during build and included in the published package.
93103

104+
The published tarball also includes the root `README.md`, `LICENSE`, and `package.json`. Those top-level files are included automatically by npm and are not copied into `dist/`.
105+
94106
## Benchmarks
95107

96108
Run the local micro-benchmarks with:
@@ -112,14 +124,20 @@ These are indicative micro-benchmark results from a single local machine. They a
112124

113125
## Development
114126

127+
See also:
128+
129+
- `CONTRIBUTING.md` for local setup, verification, and contribution expectations
130+
- `CHANGELOG.md` for release history
131+
115132
```bash
116133
npm run verify
117134
npm run test:coverage
118135
npm run build
119136
npm run bench
120137
npm run changeset
121-
npm run changeset:version
122-
npm run changeset:publish
138+
npm run release:version
139+
npm run release:changesets
140+
npm run publish:package
123141
```
124142

125143
## Verification
@@ -138,6 +156,7 @@ npm run test:coverage
138156
## Releases
139157

140158
- `npm run changeset` creates a release note entry for a package change.
141-
- `npm run changeset:version` applies pending changesets and updates the changelog.
142-
- `npm run release:publish` runs the full verification stack, coverage, and publishes through Changesets.
159+
- `npm run release:version` applies pending changesets and updates the changelog.
160+
- `npm run release:changesets` runs the full verification stack, coverage, and then publishes through Changesets.
161+
- `npm run publish:package` performs a direct npm publish with a dry-run pack check first.
143162
- `.github/workflows/release.yml` is a manual `workflow_dispatch` workflow for optional release publishing.

eslint.config.mjs

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,29 +18,37 @@ import { defineConfig } from 'eslint/config';
1818
import zeroTolerance from '@coderrob/eslint-plugin-zero-tolerance';
1919
import tseslint from 'typescript-eslint';
2020

21+
const GENERAL_IGNORES = [
22+
'coverage/**',
23+
'dist/**',
24+
'eslint.config.mjs',
25+
'node_modules/**',
26+
'scripts/**',
27+
];
28+
const MAX_LINES_RULE = [
29+
'error',
30+
{ max: 25, skipComments: true, skipBlankLines: true },
31+
];
32+
const MAX_LINES_EXEMPT_FILES = [
33+
'**/*.spec.ts',
34+
'**/*.test.ts',
35+
'**/__tests__/**/*.ts',
36+
'**/guards/createEnumGuard.ts',
37+
'**/index.ts',
38+
'benchmarks/**/*.mjs',
39+
];
40+
2141
export default defineConfig(
2242
{
23-
ignores: [
24-
'dist/**',
25-
'node_modules/**',
26-
'coverage/**',
27-
'scripts/**',
28-
'eslint.config.mjs',
29-
],
43+
ignores: GENERAL_IGNORES,
3044
},
3145
...tseslint.configs.recommended,
3246
zeroTolerance.configs.strict,
3347
{
3448
rules: {
3549
complexity: ['error', { max: 3 }],
36-
'max-lines': [
37-
'error',
38-
{ max: 25, skipComments: true, skipBlankLines: true },
39-
],
40-
'max-lines-per-function': [
41-
'error',
42-
{ max: 25, skipComments: true, skipBlankLines: true },
43-
],
50+
'max-lines': MAX_LINES_RULE,
51+
'max-lines-per-function': MAX_LINES_RULE,
4452
},
4553
},
4654
{
@@ -50,26 +58,16 @@ export default defineConfig(
5058
},
5159
},
5260
{
53-
files: ['**/index.ts'],
61+
files: MAX_LINES_EXEMPT_FILES,
5462
rules: {
5563
'max-lines': 'off',
5664
},
5765
},
5866
{
59-
files: ['**/guards/createEnumGuard.ts'],
67+
files: ['fixtures/**/*.cjs'],
6068
rules: {
61-
'max-lines': 'off',
62-
},
63-
},
64-
{
65-
files: [
66-
'**/__tests__/**/*.ts',
67-
'**/*.test.ts',
68-
'**/*.spec.ts',
69-
'benchmarks/**/*.mjs',
70-
],
71-
rules: {
72-
'max-lines': 'off',
69+
'@typescript-eslint/no-require-imports': 'off',
70+
'zero-tolerance/no-dynamic-import': 'off',
7371
},
7472
},
7573
);

fixtures/cjs-consumer/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
"name": "cjs-consumer-fixture",
33
"private": true,
44
"scripts": {
5-
"smoke": "node smoke.mjs"
5+
"smoke": "node smoke.cjs"
66
}
77
}
Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
import assert from 'node:assert/strict';
2-
import { createRequire } from 'node:module';
1+
const assert = require('node:assert/strict');
32

43
const ANSWER = Number('42');
5-
const requirePackage = createRequire(import.meta.url);
6-
const { createEnumGuard, isPlainObject, isString } = requirePackage(
7-
'@coderrob/typescript-type-guards',
8-
);
4+
const {
5+
createEnumGuard,
6+
isPlainObject,
7+
isString,
8+
} = require('@coderrob/typescript-type-guards');
9+
const packageMetadata = require('@coderrob/typescript-type-guards/package.json');
910

1011
const isStatus = createEnumGuard(
1112
{
@@ -15,6 +16,7 @@ const isStatus = createEnumGuard(
1516
'Status',
1617
);
1718

19+
assert.equal(packageMetadata.name, '@coderrob/typescript-type-guards');
1820
assert.equal(isString('hello'), true);
1921
assert.equal(isPlainObject({ answer: ANSWER }), true);
2022
assert.equal(isStatus('ACTIVE'), true);

fixtures/esm-consumer/smoke.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
isPlainObject,
66
isString,
77
} from '@coderrob/typescript-type-guards';
8+
import packageMetadata from '@coderrob/typescript-type-guards/package.json' with { type: 'json' };
89

910
const isStatus = createEnumGuard(
1011
{
@@ -14,6 +15,7 @@ const isStatus = createEnumGuard(
1415
'Status',
1516
);
1617

18+
assert.equal(packageMetadata.name, '@coderrob/typescript-type-guards');
1719
assert.equal(isString('hello'), true);
1820
const ANSWER = Number('42');
1921

0 commit comments

Comments
 (0)