Compare commits
9
Commits
09011d838f
...
0.8.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45df45df4b | ||
|
|
21b628f91d | ||
|
|
3c802ad7df | ||
|
|
5025fa3870 | ||
|
|
eb1acbd9d8 | ||
|
|
df09d3ae61 | ||
|
|
ac1fd60043 | ||
|
|
f5871c37c8 | ||
|
|
7a1eaa0d7f |
No files matched your search
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"packages": ["npm:@spences10/pi-lsp@0.0.46"]
|
"packages": ["npm:@spences10/pi-lsp@0.0.47"]
|
||||||
}
|
}
|
||||||
+16
-7
@@ -7,13 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
- restore the README's Synopsis and Examples sections: a quick-start recipe plus
|
## [0.8.3] - 2026-09-28
|
||||||
real-world examples (primitive-union dispatch, a fallback, a property union
|
|
||||||
narrowed by the tagged-union matcher, and a widening variant)
|
- upgrade dependencies: oxfmt 0.71 (the only range widened), oxlint 1.86,
|
||||||
- document the public API in the README: the four factories, when to use each,
|
oxlint-tsgolint 7.0.2003, cspell 10.3.5 and the rest within their existing
|
||||||
what the `W` (widening) suffix means, and examples that bind the handler-map
|
ranges; no rule or format fallout
|
||||||
function once
|
- prune the completed items from the backlog; their rationale already lives in
|
||||||
|
the README, `development/` and the released changelog entries
|
||||||
|
|
||||||
|
## [0.8.2] - 2026-09-25
|
||||||
|
|
||||||
|
- write the README's Synopsis and Examples sections
|
||||||
|
- document the public API in the README
|
||||||
- add TSDoc to the four public matcher factories
|
- add TSDoc to the four public matcher factories
|
||||||
|
- document alternatives
|
||||||
|
|
||||||
## [0.8.1] - 2026-09-23
|
## [0.8.1] - 2026-09-23
|
||||||
|
|
||||||
@@ -109,7 +116,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
- basic setup
|
- basic setup
|
||||||
|
|
||||||
[Unreleased]: https://gitea.e1nsnull.de/tmu/tiny-pattern-ts/compare/0.8.1...main
|
[Unreleased]: https://gitea.e1nsnull.de/tmu/tiny-pattern-ts/compare/0.8.3...main
|
||||||
|
[0.8.3]: https://gitea.e1nsnull.de/tmu/tiny-pattern-ts/compare/0.8.2...0.8.3
|
||||||
|
[0.8.2]: https://gitea.e1nsnull.de/tmu/tiny-pattern-ts/compare/0.8.1...0.8.2
|
||||||
[0.8.1]: https://gitea.e1nsnull.de/tmu/tiny-pattern-ts/compare/0.8.0...0.8.1
|
[0.8.1]: https://gitea.e1nsnull.de/tmu/tiny-pattern-ts/compare/0.8.0...0.8.1
|
||||||
[0.8.0]: https://gitea.e1nsnull.de/tmu/tiny-pattern-ts/compare/0.7.1...0.8.0
|
[0.8.0]: https://gitea.e1nsnull.de/tmu/tiny-pattern-ts/compare/0.7.1...0.8.0
|
||||||
[0.7.1]: https://gitea.e1nsnull.de/tmu/tiny-pattern-ts/compare/0.7.0...0.7.1
|
[0.7.1]: https://gitea.e1nsnull.de/tmu/tiny-pattern-ts/compare/0.7.0...0.7.1
|
||||||
|
|||||||
@@ -38,7 +38,9 @@ assert.equal(phoneOutput, "PHONE: +1 555 0100");
|
|||||||
The main goal of `tiny-pattern-ts` is to make pattern matching type-safe with a
|
The main goal of `tiny-pattern-ts` is to make pattern matching type-safe with a
|
||||||
lean syntax. This is accomplished by being exhaustive and passing typed
|
lean syntax. This is accomplished by being exhaustive and passing typed
|
||||||
parameters per branch to the handlers — supported by an outstanding
|
parameters per branch to the handlers — supported by an outstanding
|
||||||
autocomplete and a tiny footprint.
|
autocomplete and a tiny footprint. The matchers are data last and pipe-friendly:
|
||||||
|
build the handler map once, then apply the resulting matcher to values
|
||||||
|
(`match(value)`, or `pipe(value, match)`).
|
||||||
|
|
||||||
See [development/library.md](./development/library.md) for the design decisions
|
See [development/library.md](./development/library.md) for the design decisions
|
||||||
and [Caveats](#caveats) for the limits.
|
and [Caveats](#caveats) for the limits.
|
||||||
@@ -284,6 +286,43 @@ provable exhaustiveness — to automate what a `switch` and a default arm alread
|
|||||||
cover. The type-level cost of supporting open universes is recorded in
|
cover. The type-level cost of supporting open universes is recorded in
|
||||||
[development/library.md](./development/library.md#supported-universes).
|
[development/library.md](./development/library.md#supported-universes).
|
||||||
|
|
||||||
|
## Alternatives
|
||||||
|
|
||||||
|
### [`ts-pattern`](https://github.com/gvergnaud/ts-pattern)
|
||||||
|
|
||||||
|
- is the full structural matcher — nested and partial patterns, guards, unions,
|
||||||
|
captures — exhausting at `.exhaustive()`
|
||||||
|
- has a fluent `.with(…)` chain that is heavy on syntax; tiny-pattern-ts is one
|
||||||
|
handler map
|
||||||
|
- is about 2 kB minified and gzipped; tiny-pattern-ts is 0.2 kB
|
||||||
|
- reach for it when you need a feature tiny-pattern-ts does not cover
|
||||||
|
|
||||||
|
### [Effect's `Match`](https://effect.website/docs/code-style/pattern-matching/)
|
||||||
|
|
||||||
|
- is the same piped matcher (`Match.type` / `Match.when` / `Match.exhaustive`),
|
||||||
|
but only as part of the `effect` ecosystem
|
||||||
|
- tiny-pattern-ts is standalone: no runtime dependency to buy into
|
||||||
|
|
||||||
|
### [`match-iz`](https://github.com/shuckster/match-iz)
|
||||||
|
|
||||||
|
- expresses patterns in the TC39 proposal's style, deciding each case at runtime
|
||||||
|
- is written in JavaScript with hand-maintained declarations, so its types do
|
||||||
|
not prove the cases exhaustive
|
||||||
|
- tiny-pattern-ts does: exhaustiveness is a compile-time guarantee, not an
|
||||||
|
`otherwise` fallback
|
||||||
|
|
||||||
|
### plain `switch` (baseline)
|
||||||
|
|
||||||
|
- is the zero-dependency baseline — pair it with
|
||||||
|
[`eslint-plugin-strict-pattern-matching`](https://www.npmjs.com/package/eslint-plugin-strict-pattern-matching)
|
||||||
|
for exhaustiveness
|
||||||
|
- is a statement, not an expression, so it cannot produce a value directly
|
||||||
|
- leaves the `never` guard to you; tiny-pattern-ts is an expression and does not
|
||||||
|
need one
|
||||||
|
|
||||||
|
The [TC39 pattern-matching proposal](https://github.com/tc39/proposal-pattern-matching)
|
||||||
|
is still stage 1, so userland libraries remain the only option today.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT © 2026 tmu. See [LICENSE](./LICENSE).
|
MIT © 2026 tmu. See [LICENSE](./LICENSE).
|
||||||
|
|||||||
@@ -7,32 +7,8 @@ Backlog and tracking for tiny-pattern-ts. Managed in vscode-todotasks format.
|
|||||||
Setup:
|
Setup:
|
||||||
☐ Split off template into separate package => pi --session 01a07dde-7050-7054-bb36-1606d7eb2bc3 @low
|
☐ Split off template into separate package => pi --session 01a07dde-7050-7054-bb36-1606d7eb2bc3 @low
|
||||||
|
|
||||||
v1.0:
|
|
||||||
✔ API surface is stable and fully typed @done
|
|
||||||
✔ Finalize public exports in `src/index.ts` @done
|
|
||||||
✔ Document all exported types and functions @done
|
|
||||||
✔ Add JSDoc for public APIs @done
|
|
||||||
✔ Test coverage meets threshold @done
|
|
||||||
✔ Achieve 100% branch coverage on `src/primitive-union.ts` @done
|
|
||||||
✔ Achieve 100% branch coverage on `src/index.ts` @done
|
|
||||||
|
|
||||||
Matcher:
|
|
||||||
✔ when using a union type as a property, the current behavior of tagged union matcher is @done
|
|
||||||
to pass never to handler parameters
|
|
||||||
→ new matcher function needed or can be fixed in tagged union matcher
|
|
||||||
✔ optional discriminant (`{ type?: "x" }`) is the same hole: the boolean/nullish change now admits the `undefined` tag, so the factory accepts the key, but `Extract<T, Record<K, V>>` still passes `never` to both the `x` and `undefined` handlers @done
|
|
||||||
|
|
||||||
Documentation:
|
Documentation:
|
||||||
✔ Bring README.md back to its previous form — synopsis and examples restored, in the correct place @done
|
|
||||||
→ previous section order: title, tagline, Synopsis, Description, Requirements, Examples, API, License, Contributing
|
|
||||||
→ previous Examples order: literal/exhaustive, typeof, structural/discriminated unions, when, any
|
|
||||||
☐ Create `examples/` directory with runnable snippets
|
☐ Create `examples/` directory with runnable snippets
|
||||||
☐ Add comparison section vs. other TS pattern-matching libs in Readme.md
|
|
||||||
☐ Why do we do this? => exhaustiveness encoded type safe
|
|
||||||
☐ Why this form? little syntax, data last, very small, autocomplete, strict typing in the handler; for more features use ts-pattern
|
|
||||||
✔ Write migration guide for users coming from discriminated unions @done (9/24/2026, 10:21:17 PM)
|
|
||||||
✔ Create backlog tasks for implementation @done (9/24/2026, 10:21:16 PM)
|
|
||||||
✔ Validate code fences in Markdown (start with README.md) — compile the TypeScript examples against `src/` so the docs cannot drift from the API @done
|
|
||||||
|
|
||||||
Maintenance:
|
Maintenance:
|
||||||
☐ Serve CI coverage over a tiny self-hosted webserver (replace the zip artifact) @low
|
☐ Serve CI coverage over a tiny self-hosted webserver (replace the zip artifact) @low
|
||||||
|
|||||||
+2
-1
@@ -45,7 +45,8 @@
|
|||||||
"todotasks",
|
"todotasks",
|
||||||
"connor",
|
"connor",
|
||||||
"injective",
|
"injective",
|
||||||
"injectivity"
|
"injectivity",
|
||||||
|
"userland"
|
||||||
],
|
],
|
||||||
"ignorePaths": ["dist", "node_modules", "coverage", "*.svg", ".gitignore"]
|
"ignorePaths": ["dist", "node_modules", "coverage", "*.svg", ".gitignore"]
|
||||||
}
|
}
|
||||||
+13
-12
@@ -196,27 +196,28 @@ joining the oxfmt-superseded rules already off.
|
|||||||
are part of the public API.
|
are part of the public API.
|
||||||
- The narrower scope keeps the signal high without config-file boilerplate.
|
- The narrower scope keeps the signal high without config-file boilerplate.
|
||||||
|
|
||||||
### `knip` lists `src/index.ts` as an entry
|
### `knip` does not list the library entry
|
||||||
|
|
||||||
#### Decision (2026-09)
|
#### Decision (2026-09)
|
||||||
|
|
||||||
`knip.json` declares `"entry": ["src/index.ts", "scripts/*.ts"]`.
|
`knip.json` declares `"entry": ["scripts/*.ts"]`; the library entry
|
||||||
|
`src/index.ts` is not listed.
|
||||||
|
|
||||||
#### Why
|
#### Why
|
||||||
|
|
||||||
- Supplying `entry` **replaces** knip's default entry detection, which otherwise
|
- knip derives the public entry from `package.json` `exports` and resolves it to
|
||||||
derives the public entry from `package.json` `exports`. Adding `scripts/*.ts`
|
`src/index.ts` itself, so naming the file is a redundant pattern and
|
||||||
there therefore dropped the library entry, so knip resolved the package through
|
`maintain:knip` reports it as a configuration hint.
|
||||||
its `dist/index.js` output and reported the unreferenced source entry file
|
- Listing `scripts/*.ts` does not switch that derivation off: the scope stays
|
||||||
`src/index.ts` as an unused file.
|
clean with or without `dist/`, and with the barrel's own test removed.
|
||||||
- Naming the source entry restores the link between the public API and the
|
|
||||||
source graph without pointing knip at build output.
|
|
||||||
|
|
||||||
#### Rejected
|
#### Rejected
|
||||||
|
|
||||||
|
- `"src/index.ts"` in `entry`: it silenced an `unused files` report for the
|
||||||
|
barrel, which the derivation above no longer produces; keeping it only adds a
|
||||||
|
hint.
|
||||||
- `paths` mapping `dist/index.*` back to `src/index.ts`: more config to model a
|
- `paths` mapping `dist/index.*` back to `src/index.ts`: more config to model a
|
||||||
relation the explicit entry states directly, and it would break whenever the
|
relation knip already resolves.
|
||||||
build layout changes.
|
|
||||||
|
|
||||||
### `maintain:outdated` ignores `@types/node`
|
### `maintain:outdated` ignores `@types/node`
|
||||||
|
|
||||||
@@ -327,7 +328,7 @@ of a hand-rolled JSON-RPC client.
|
|||||||
|
|
||||||
#### Decision (2026-09)
|
#### Decision (2026-09)
|
||||||
|
|
||||||
`@spences10/pi-lsp` is pinned to `0.0.46` and used read-only.
|
`@spences10/pi-lsp` is pinned to `0.0.47` and used read-only.
|
||||||
|
|
||||||
#### Why
|
#### Why
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"$schema": "./node_modules/knip/schema.json",
|
"$schema": "./node_modules/knip/schema.json",
|
||||||
"entry": ["src/index.ts", "scripts/*.ts"],
|
"entry": ["scripts/*.ts"],
|
||||||
"ignoreDependencies": ["@runwisp/pubv"]
|
"ignoreDependencies": ["@runwisp/pubv"]
|
||||||
}
|
}
|
||||||
Generated
+376
-354
File diff suppressed because it is too large.
Load diff
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "tiny-pattern-ts",
|
"name": "tiny-pattern-ts",
|
||||||
"version": "0.8.1",
|
"version": "0.8.3",
|
||||||
"description": "Exhaustive, type-safe pattern matching for TypeScript",
|
"description": "Exhaustive, type-safe pattern matching for TypeScript",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"adt",
|
"adt",
|
||||||
@@ -88,7 +88,7 @@
|
|||||||
"knip": "^6.34.0",
|
"knip": "^6.34.0",
|
||||||
"lefthook": "^2.1.12",
|
"lefthook": "^2.1.12",
|
||||||
"mdast-util-from-markdown": "^2.0.3",
|
"mdast-util-from-markdown": "^2.0.3",
|
||||||
"oxfmt": "^0.70.0",
|
"oxfmt": "^0.71.0",
|
||||||
"oxlint": "^1.83.0",
|
"oxlint": "^1.83.0",
|
||||||
"oxlint-tsgolint": "^7.0.2001",
|
"oxlint-tsgolint": "^7.0.2001",
|
||||||
"publint": "^0.3.24",
|
"publint": "^0.3.24",
|
||||||
|
|||||||
Reference in new issue
Block a user