You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: API_REFERENCE.md
+11-14Lines changed: 11 additions & 14 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,7 @@ This file catalogs every public export from `@git-stunts/trailer-codec` so you c
8
8
- Deprecated convenience wrapper around `new TrailerCodec().decode(message)`.
9
9
- Input: a raw commit payload (title, optional body, trailers) as a string.
10
10
- Output: `{ title: string, body: string, trailers: Record<string, string> }` where `body` is trimmed via `formatBodySegment` (see below) and trailer keys are normalized to lowercase.
- Extends `TrailerCodecError` and introduces the following codes:
85
+
### Validation error subclasses
87
86
88
-
|Code| Thrown by | Meaning |
87
+
|Error| Thrown by | Meaning |
89
88
| --- | --- | --- |
90
-
|`TRAILER_TOO_LARGE`|`MessageNormalizer.guardMessageSize` (called by `TrailerCodecService.decode` and the exported `decodeMessage`) | Message exceeds the 5 MB guard in `MessageNormalizer`. |
91
-
|`TRAILER_NO_SEPARATOR`|`TrailerParser.split` / `TrailerCodecService.decode` when the blank-line guard fails | A trailer block was found without a blank line separating it from the body (see `TrailerParser`). |
92
-
|`TRAILER_VALUE_INVALID`|`GitTrailer` via `GitTrailerSchema.parse` when constructing trailers | A trailer value violated the `GitTrailerSchema` (e.g., contained `\n`). |
93
-
|`TRAILER_INVALID`|`GitTrailer` via `GitTrailerSchema.parse` when constructing trailers | Trailer key or value failed validation (`GitTrailerSchema`). |
94
-
|`COMMIT_MESSAGE_INVALID`|`GitCommitMessage` via `GitCommitMessageSchema.parse` (triggered by `TrailerCodecService.decode` or `encode`) | The `GitCommitMessageSchema` rejected the title/body/trailers combination. |
95
-
96
-
The thrown `ValidationError` exposes `code` and `meta` for programmatic recovery; refer to `docs/SERVICE.md` or `README.md#validation-error-codes` for how to react in your integration.
89
+
|`TrailerTooLargeError`|`MessageNormalizer.guardMessageSize` (called by `TrailerCodecService.decode` and the exported `decodeMessage`) | Message exceeds the 5 MB guard in `MessageNormalizer`. |
90
+
|`TrailerNoSeparatorError`|`TrailerParser.split` / `TrailerCodecService.decode` when the blank-line guard fails | A trailer block was found without a blank line separating it from the body (see `TrailerParser`). |
91
+
|`TrailerValueInvalidError`|`GitTrailer` via `GitTrailerSchema.parse` when constructing trailers | A trailer value violated the `GitTrailerSchema` (e.g., contained `\n`). |
92
+
|`TrailerInvalidError`|`GitTrailer` via `GitTrailerSchema.parse` when constructing trailers | Trailer key or value failed validation (`GitTrailerSchema`). |
93
+
|`CommitMessageInvalidError`|`GitCommitMessage` via `GitCommitMessageSchema.parse` (triggered by `TrailerCodecService.decode` or `encode`) | The `GitCommitMessageSchema` rejected the title/body/trailers combination. |
-**Errors**: Domain-specific error hierarchy (`TrailerCodecError` plus concrete subclasses such as `TrailerNoSeparatorError` and `TrailerValueInvalidError`).
14
14
-**Schemas**: Zod schemas for validation of domain objects.
15
15
16
16
### Ports Layer (`src/ports/`)
@@ -22,7 +22,7 @@ The core business logic, isolated from external frameworks or I/O.
│ ├── errors/ # TrailerCodecError and validation subclasses
26
26
│ ├── schemas/ # Zod schemas
27
27
│ ├── services/ # TrailerCodecService
28
28
│ └── value-objects/ # GitTrailer
@@ -35,6 +35,6 @@ src/
35
35
36
36
## 🛠️ Design Decisions
37
37
38
-
1.**Zod for Validation**: We use Zod for runtime schema validation but wrap it in domain-specific `ValidationError`s to avoid leaking implementation details.
38
+
1.**Zod for Validation**: We use Zod for runtime schema validation but wrap it in domain-specific `TrailerCodecError` subclasses to avoid leaking implementation details.
39
39
2.**Case Normalization**: Git trailer keys are case-insensitive. We normalize them to lowercase in the `GitTrailer` Value Object to ensure consistency.
40
40
3.**Facade Pattern**: `index.js` acts as a facade, providing a simple, backward-compatible API while exposing the rich domain model for advanced users.
- Auditing README.md and related docs for accuracy, topic coverage, and developer onboarding completeness.
5
+
- Ensuring the `docs/` tree (ADVANCED, SERVICE, INTEGRATION, etc.) reflects the actual exports/behaviors in `src/` and covers validation errors, helper exports, and the service pipeline described in the audit prompts.
6
+
- Stabilizing service helpers (MessageNormalizer, TitleExtractor, BodyComposer, TrailerParser) and domain objects (ValidationError refactor to specific subclasses, GitTrailer, GitCommitMessage) before wiring them back into TrailerCodecService.
7
+
- Planning the long list of fix/cleanup tasks (JSDoc coverage, README reorganizations, new docs, tests) that the prompts outlined but have not yet been committed.
8
+
9
+
## Progress so far
10
+
- Several source files have been touched (`CodecBuilder`, `FacadeAdapter`, domain helpers/services, tests) though the work is mid-flight.
11
+
- New custom error classes plus the docs mention these files, but the repo is currently a mix of trailer-codec logic and early-stage `jsdoctor` experimentation (scripts/, utils/ folder, etc.).
12
+
- There is a big ongoing audit and documentation cleanup, making the codebase look unstable—this is why we need to pause here before introducing a major refactor.
13
+
14
+
## Why the pause
15
+
- We want to **purify trailer-codec** by removing/reorganizing the `jsdoctor`-related experiments and then hand off a clean repo that can continue evolving on its own.
16
+
- The user explicitly requested we shift context to the new `jsdoctor` repo, ensuring that the latest doc/LLM tooling lives there instead of being scattered here.
17
+
- We need to trace whether the `jsdoctor` code already exists elsewhere (the new repo) before deleting it from this repo, to avoid losing work.
18
+
19
+
## Next steps when returning
20
+
1. Sweep `src/`/`docs/` to finish the remaining audit points (Accuracy, docs updates, error classes, tests, etc.).
21
+
2. Complete the requested README/docs/CHANGELOG updates, plus missing files (`TESTING.md`, `API_REFERENCE.md`, etc.).
22
+
3. Ensure the newly created error classes/tests are in their final shape and fix test coverage regressions.
23
+
4. After finishing this cleanup, determine if any `jsdoctor` code still needs migration back into trailer-codec before the final handoff.
24
+
5. Re-assess `CONTINUE.md` and update it with whichever parts are unfinished at that point.
25
+
26
+
>> Note: We are now switching to the `jsdoctor` repo to continue the new 'Bobs' tooling work—treat this note as the single source of truth for where we left off here.
-`createMessageHelpers({ service, bodyFormatOptions })` returns `{ decodeMessage, encodeMessage }` bound to the provided `TrailerCodecService`; pass `bodyFormatOptions` to control whether decoded bodies keep their trailing newline.
150
150
-`TrailerCodec` wraps `createMessageHelpers()` so you can instantiate a codec class with custom `service` or `bodyFormatOptions` and still leverage the helper contract via `encode()`/`decode()`.
151
151
-`createConfiguredCodec({ keyPattern, keyMaxLength, parserOptions, formatters, bodyFormatOptions })` wires together `createGitTrailerSchemaBundle`, `TrailerParser`, `TrailerCodecService`, and the helper pair, letting you configure key validation, parser heuristics, formatting hooks, and body formatting in a single call.
152
-
-`TrailerCodecService` exposes the schema bundle, parser, trailer factory, formatter hooks, and helper classes (`MessageNormalizer`, `TitleExtractor`, `BodyComposer`); see `docs/SERVICE.md` for a deeper explanation of how to customize each stage without touching the core service.
152
+
-`TrailerCodecService` exposes the schema bundle, parser, trailer factory, formatter hooks, and helper utilities (`MessageNormalizer`, `extractTitle`, `composeBody`); see `docs/SERVICE.md` for a deeper explanation of how to customize each stage without touching the core service.
153
153
154
154
## ✅ Validation Rules
155
155
156
-
Trailer codec enforces strict validation:
156
+
Trailer codec enforces strict validation via the concrete subclasses of `TrailerCodecError`:
157
157
158
-
| Rule | Constraint | Error Type |
159
-
|------|-----------|------------|
160
-
|**Message Size**| ≤ 5MB |`ValidationError`|
161
-
|**Title**| Must be non-empty string |`ValidationError`|
162
-
|**Trailer Key**| Alphanumeric, hyphens, underscores only (`/^[A-Za-z0-9_-]+$/`) |`ValidationError`|
|**Trailer Value**| Must be non-empty string |`ValidationError`|
158
+
| Rule | Constraint | Thrown Error |
159
+
|------|------------|--------------|
160
+
|**Message Size**| ≤ 5MB |`TrailerTooLargeError`|
161
+
|**Title**| Must be a non-empty string |`CommitMessageInvalidError` (during entity construction) |
162
+
|**Trailer Key**| Alphanumeric, hyphens, underscores only (`/^[A-Za-z0-9_-]+$/`) and ≤ 100 characters (prevents ReDoS) |`TrailerInvalidError`|
163
+
|**Trailer Value**| Cannot contain carriage returns or line feeds and must not be empty |`TrailerValueInvalidError`|
165
164
166
165
**Key Normalization:** All trailer keys are automatically normalized to lowercase (e.g., `Signed-Off-By` → `signed-off-by`).
167
166
168
-
**Blank-Line Guard:** Trailers must be separated from the body by a blank line; committing without that empty line results in a `ValidationError`.
167
+
**Blank-Line Guard:** Trailers must be separated from the body by a blank line; omitting the separator throws `TrailerNoSeparatorError`.
169
168
170
-
**Trailer Line Limits:** Trailer values cannot contain carriage returns or line feeds.
169
+
### Validation Errors
171
170
172
-
### Validation Error Codes
171
+
When `TrailerCodecService` or the exported helpers throw, they surface one of the following classes so you can recover with `instanceof` checks:
173
172
174
-
|Code| Trigger | Suggested Fix |
173
+
|Error| Trigger | Suggested Fix |
175
174
| --- | --- | --- |
176
-
|`TRAILER_TOO_LARGE`| Message exceeds 5MB | Split the commit or remove content until the payload fits |
177
-
|`TRAILER_NO_SEPARATOR`| Missing blank line before trailers | Insert an empty line between the body and the trailer metadata |
178
-
|`TRAILER_VALUE_INVALID`| Trailer value contains newline characters | Remove newlines from the value before encoding |
179
-
|`TRAILER_INVALID`| Trailer key or value fails schema validation | Adjust the key/value or pass a custom schema bundle via `TrailerCodecService`|
175
+
|`TrailerTooLargeError`| Message exceeds 5MB while `MessageNormalizer.guardMessageSize()` runs | Split the commit or remove content until the payload fits. |
176
+
|`TrailerNoSeparatorError`| Missing blank line before trailers when `TrailerParser.split()` runs | Insert the required empty line between body and trailers. |
177
+
|`TrailerValueInvalidError`| Trailer value includes newline characters or fails the schema value rules | Remove or escape newline characters before encoding. |
178
+
|`TrailerInvalidError`| Trailer key/value pair fails the schema validation (`GitTrailerSchema`) | Adjust the key/value or supply a custom schema bundle via `TrailerCodecService`. |
179
+
|`CommitMessageInvalidError`|`GitCommitMessageSchema` rejects the full payload (title/body/trailers) | Fix the invalid field or pass a conforming payload; use formatters if needed. |
180
180
181
-
Each code appears on the thrown `ValidationError` (`src/domain/errors/ValidationError.js`), so you can read `error.code` and `error.meta`to respond. See `API_REFERENCE.md#validation-errors` for the class signature and recommended recovery guidance for each code.
181
+
All of the above inherit from `TrailerCodecError` (`src/domain/errors/TrailerCodecError.js`) and expose `meta`for diagnostics; prefer checking the specific class instead of inspecting `code`.
182
182
183
183
## 🛡️ Security
184
184
@@ -192,15 +192,13 @@ See [SECURITY.md](SECURITY.md) for details.
-[`docs/SERVICE.md`](docs/SERVICE.md) — How `TrailerCodecService` wires schema, parser, and formatter helpers for customization.
199
+
-[`API_REFERENCE.md`](API_REFERENCE.md) — Complete catalog of the public exports, their inputs/outputs, and notable knobs.
200
+
-[`TESTING.md`](TESTING.md) — How to run/extend the Vitest, lint, and format scripts plus contributor tips.
201
+
-**Git hooks**: Run `npm run setuphooks` once per clone to point `core.hooksPath` at `scripts/`. The hook now runs just `npm run lint` and `npm run format` before each commit.
Copy file name to clipboardExpand all lines: docs/INTEGRATION.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
# Integration Guide
2
2
3
-
`decodeMessage()` returns `{ title: string, body: string, trailers: Record<string,string> }` (see `API_REFERENCE.md#encoding--decoding-helpers`). `.title` is the first commit line, `.body` trims leading/trailing blanks to provide the content between title and trailers, and `.trailers` is an object of normalized lowercase keys (empty when no trailers exist). `formatBodySegment(segment)` expects a string and returns the trimmed segment, optionally keeping a trailing newline when `keepTrailingNewline: true`. `decodeMessage()` throws `ValidationError` on malformed input instead of returning an error object, so callers should wrap calls in try/catch if they want to handle validation failures gracefully.
3
+
`decodeMessage()` returns `{ title: string, body: string, trailers: Record<string,string> }` (see `API_REFERENCE.md#encoding--decoding-helpers`). `.title` is the first commit line, `.body` trims leading/trailing blanks to provide the content between title and trailers, and `.trailers` is an object of normalized lowercase keys (empty when no trailers exist). `formatBodySegment(segment)` expects a string and returns the trimmed segment, optionally keeping a trailing newline when `keepTrailingNewline: true`. `decodeMessage()` throws validation subclasses such as `TrailerNoSeparatorError`, `TrailerValueInvalidError`, or `CommitMessageInvalidError` instead of returning an error object, so callers should wrap calls in try/catch if they want to handle failures gracefully.
4
4
5
5
Blend `@git-stunts/trailer-codec` with Git history and tooling to treat commit trailers as structured metadata.
Copy file name to clipboardExpand all lines: docs/PARSER.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,7 +7,7 @@ The parser in `TrailerCodecService.decode()` walks **backwards** from the bottom
7
7
1.**Normalize line endings** to `\n` and split the message.
8
8
2.**Consume the title** (the first line) and drop the optional blank line that separates it from the body.
9
9
3.**Walk backward** with `_findTrailerStartIndex` until either a non-matching line or an empty line appears; contiguous `Key: Value` patterns form the trailer block.
10
-
4.**Validate the separator**: `_validateTrailerSeparation` ensures there is a blank line before the trailers. Messages that omit the blank line now throw `ValidationError`.
10
+
4.**Validate the separator**: `_validateTrailerSeparation` ensures there is a blank line before the trailers. Messages that omit the blank line now throw `TrailerNoSeparatorError`.
11
11
5.**Trim the body** without double allocations: `_trimBody` trims leading/trailing blank lines via index arithmetic and one `join`.
12
12
6.**Parse trailers** using the schema bundle’s `keyPattern`, instantiating trailers via the injected `trailerFactory`.
0 commit comments