Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CONTEXT-MAP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Context Map

## Contexts

- [HAL Domain & Serialization](./src/Chatter.Rest.Hal/CONTEXT.md) — in-memory HAL document model, fluent builder API, and JSON serialization/deserialization
- [HAL Shared Kernel](./src/Chatter.Rest.Hal.Core/CONTEXT.md) — shared types with no standalone package, referenced by consumer and test projects; the source generator discovers HalResponseAttribute by metadata name, not via a direct Core reference
- [HAL Code Generation](./src/Chatter.Rest.Hal.CodeGenerators/CONTEXT.md) — Roslyn source generator that emits HAL-aware partial classes from annotated user types

## Relationships

- **Shared Kernel -> HAL Domain & Serialization**: Core defines **HalResponseAttribute**; the domain library declares the **Link Collection** and **Embedded Resource Collection** types that generated code references
- **Shared Kernel -> HAL Code Generation**: Code Generation reads **HalResponseAttribute** at compile time to discover annotated classes and emit partial-class source
- **HAL Domain & Serialization <-> HAL Code Generation**: No direct project reference; generated code depends on domain types (**Link Collection**, **Embedded Resource Collection**) at the consuming project's compile time, not at generator compile time
40 changes: 40 additions & 0 deletions src/Chatter.Rest.Hal.CodeGenerators/CONTEXT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# HAL Code Generation

A Roslyn incremental source generator that discovers classes annotated with **HalResponseAttribute** and emits partial-class source containing HAL navigation properties (`Links`, `Embedded`).

## Language

**HalResponseGenerator**:
The Roslyn incremental source generator entry point that discovers **HalResponseAttribute**-annotated classes and feeds them to the **Emitter**.
_Avoid_: source generator, code generator (too generic), analyzer

**Emitter**:
The component that produces the generated C# source text for each discovered class, adding `Links` and `Embedded` properties with the correct `[JsonPropertyName]` attributes.
_Avoid_: code writer, template, renderer

**HalClassInfo**:
A value type capturing the name and namespace of a single annotated class, used as the pipeline's intermediate representation between discovery and emission.
_Avoid_: class metadata, class descriptor, target info

**Generated Partial Class**:
The source file emitted per annotated class, adding `Links` (typed as **Link Collection**) and `Embedded` (typed as **Embedded Resource Collection**) properties so the user's DTO can participate in HAL serialization without inheriting from **Resource**.
_Avoid_: generated file, code-gen output, scaffolded class

## Relationships

- **HalResponseGenerator** discovers classes annotated with **HalResponseAttribute** (defined in HAL Shared Kernel)
- **HalResponseGenerator** collects each discovered class as a **HalClassInfo** and passes the set to the **Emitter**
- The **Emitter** produces one **Generated Partial Class** per **HalClassInfo**
- Each **Generated Partial Class** references **Link Collection** and **Embedded Resource Collection** (defined in HAL Domain & Serialization) via `using Chatter.Rest.Hal`

## Example dialogue

> **Dev:** "My `[HalResponse]` class compiles but the generated `Links` property doesn't appear."
> **Domain expert:** "The class must be declared `partial`. **HalResponseGenerator** emits a **Generated Partial Class** that adds the property -- if the class isn't partial, the compiler can't merge them."

> **Dev:** "Can I customize what the **Emitter** generates for my class?"
> **Domain expert:** "No. The **Emitter** produces a fixed shape: a `Links` property of type **Link Collection** and an `Embedded` property of type **Embedded Resource Collection**. Customization happens at the domain level, not at generation time."

## Flagged ambiguities

- "generator" is used both for the Roslyn concept (IIncrementalGenerator) and for the project-specific **HalResponseGenerator** class -- resolved: use **HalResponseGenerator** when referring to this project's generator; use "Roslyn source generator" when referring to the platform concept.
22 changes: 22 additions & 0 deletions src/Chatter.Rest.Hal.Core/CONTEXT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# HAL Shared Kernel

Shared marker types referenced by consumer projects and test projects. The source generator discovers HalResponseAttribute by metadata name at compile time and does not require a direct project reference to Core. Generated code references the domain package (Chatter.Rest.Hal) at the consuming project's compile time.

## Language

**HalResponseAttribute**:
A class-level attribute that marks a user-defined type for HAL source generation; the generator scans for this attribute at compile time to discover target classes.
_Avoid_: HalAttribute, HAL marker, response marker

## Relationships

- **HalResponseAttribute** is declared here and consumed by consumer projects and test projects; HAL Code Generation discovers it by metadata name at compile time to find annotated classes; generated code references HAL Domain & Serialization types (**Link Collection**, **Embedded Resource Collection**) at the consuming project's compile time

## Example dialogue

> **Dev:** "I decorated my DTO with `[HalResponse]` but nothing happened."
> **Domain expert:** "**HalResponseAttribute** only marks the class for the source generator. You also need the `Chatter.Rest.Hal.CodeGenerators` analyzer package referenced so the generator can find it and emit the partial class."

## Flagged ambiguities

- None at this time.
137 changes: 137 additions & 0 deletions src/Chatter.Rest.Hal/CONTEXT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# HAL Domain & Serialization

The in-memory object model for HAL (Hypertext Application Language) documents, a fluent builder API for constructing them, and System.Text.Json converters for round-trip serialization.

## Language

### Document model

**Resource**:
A HAL document or an individual embedded item; the root aggregate that holds **State**, a **Link Collection**, and an **Embedded Resource Collection**.
_Avoid_: document, response, payload, HAL object

**State**:
The application-specific properties of a **Resource**, excluding reserved HAL properties (`_links`, `_embedded`).
_Avoid_: body, data, properties, content

**Link**:
A named entry in a **Link Collection**, identified by a **Relation** and containing zero or more **Link Objects**.
_Avoid_: hyperlink, URL entry, link relation entry

**Relation**:
A string that identifies the semantics of a **Link** (e.g., `"self"`, `"next"`, `"acme:widgets"`).
_Avoid_: rel type, link name, link key

**Link Object**:
A single hyperlink target within a **Link**, carrying an **Href** and optional properties (templated, type, deprecation, name, profile, title, hreflang).
_Avoid_: link entry, link item, href object

**Href**:
The URI or URI Template value on a **Link Object**; the only required property.
_Avoid_: URL, address, endpoint

**Embedded Resource**:
A named entry in an **Embedded Resource Collection**, identified by a name string and containing a **Resource Collection**.
_Avoid_: nested resource, sub-resource, child resource, embed

**Link Collection**:
The ordered set of **Links** on a **Resource**, serialized as the `_links` JSON property.
_Avoid_: links map, link set

**Link Object Collection**:
The ordered set of **Link Objects** within a single **Link**.
_Avoid_: link array, href list

**Embedded Resource Collection**:
The ordered set of **Embedded Resources** on a **Resource**, serialized as the `_embedded` JSON property.
_Avoid_: embeds, embedded map

**Resource Collection**:
The ordered set of **Resources** within a single **Embedded Resource**.
_Avoid_: resource array, resource list

### Reserved relations

**Self Link**:
A **Link** with **Relation** `"self"` that identifies the **Resource's** own URI.
_Avoid_: self-ref, canonical link, identity link

**CURIE**:
A compact URI prefix defined under the reserved `"curies"` **Relation**, enabling short-form **Relations** (e.g., `"acme:widgets"`) that expand to full URIs via a URI Template.
_Avoid_: compact URI, namespace, prefix

**CURIE Expansion**:
The process of replacing a prefixed **Relation** (e.g., `"acme:widgets"`) with its full URI by substituting the suffix into the CURIE's **Href** template at the `{rel}` token.
_Avoid_: prefix resolution, namespace expansion

### Serialization

**Force Array**:
A per-**Link** flag (`IsArray`) or a global option (`AlwaysUseArrayForLinks`) that forces a **Link** to serialize as a JSON array even when it contains a single **Link Object**.
_Avoid_: always-array, array mode

**Force Write As Collection**:
A per-**Embedded Resource** flag (`ForceWriteAsCollection`) that forces its **Resource Collection** to serialize as a JSON array even when it contains a single **Resource**.
_Avoid_: always-array (embedded), collection mode

**HAL JSON Options**:
Configuration object (`HalJsonOptions`) controlling HAL-specific serialization behavior, notably the global **Force Array** setting for links.
_Avoid_: serialization settings, converter config

### Builder

**Fluent Builder**:
The staged builder API (`ResourceBuilder`) for constructing a **Resource** graph through chained method calls, using stage interfaces to guide valid construction sequences.
_Avoid_: resource factory, DSL, construction API

**Stage Interface**:
An interface (e.g., `IResourceCreationStage`, `ILinkCreationStage`) that constrains which builder methods are available at each step of **Fluent Builder** construction.
_Avoid_: step interface, phase interface, builder contract

### Marker type

**IHalPart**:
Marker interface implemented by every HAL domain type (**Resource**, **Link**, **Link Object**, and all collection types); used as the generic constraint for the builder hierarchy.
_Avoid_: IHalType, IHalEntity

### External dependency

**URI Template**:
An RFC 6570 template string used by **Link Object** for template expansion via the external `Chatter.Rest.UriTemplates` package. **CURIEs** also use a template-shaped **Href** (containing a `{rel}` token), but CURIE expansion performs plain `{rel}` string substitution — it does not use the external `Chatter.Rest.UriTemplates` package.
_Avoid_: URL template, route template

## Relationships

- A **Resource** contains exactly one **Link Collection** and one **Embedded Resource Collection**
- A **Resource** contains zero or one **State** objects
- A **Link Collection** contains zero or more **Links**
- A **Link** is identified by exactly one **Relation** and contains one **Link Object Collection**
- A **Link Object Collection** contains zero or more **Link Objects**
- A **Link Object** carries exactly one **Href** and optional metadata properties
- An **Embedded Resource Collection** contains zero or more **Embedded Resources**
- An **Embedded Resource** is identified by a name and contains one **Resource Collection**
- A **Resource Collection** contains zero or more **Resources** (recursive: each may have its own **Links** and **Embedded Resources**)
- A **CURIE** is a **Link** under the reserved `"curies"` **Relation** whose **Link Objects** define prefix-to-template mappings
- **CURIE Expansion** uses a **CURIE's** **Href** (a template-shaped string with a `{rel}` token) to resolve prefixed **Relations** to full URIs via plain string substitution — the external `Chatter.Rest.UriTemplates` package is not involved
- A **Self Link** is a **Link** with **Relation** `"self"`
- **Force Array** applies to **Links**; **Force Write As Collection** applies to **Embedded Resources** — both override the default singular/plural JSON shape
- The **Fluent Builder** produces a **Resource** graph; **Stage Interfaces** control the construction sequence
- Every HAL domain type implements **IHalPart**
- **HalResponseAttribute** (defined in HAL Shared Kernel) is not consumed directly in this context; it is consumed by HAL Code Generation, whose generated code references types from this context

## Example dialogue

> **Dev:** "When I add a **Link** with **Relation** `"next"`, does it automatically get a **Link Object**?"
> **Domain expert:** "No -- a **Link** starts with an empty **Link Object Collection**. You add **Link Objects** to it, each with its own **Href**."

> **Dev:** "If my **Link** only has one **Link Object**, will it serialize as a JSON object or a JSON array?"
> **Domain expert:** "By default it serializes as a single object. If you need a stable array shape, set **Force Array** on the **Link** -- or enable it globally via **HAL JSON Options**."

> **Dev:** "How does **CURIE Expansion** work for `acme:widgets`?"
> **Domain expert:** "It finds the **CURIE** **Link Object** with name `acme` under the `curies` **Relation**, takes its **Href** template, and substitutes `widgets` for the `{rel}` token."

## Flagged ambiguities

- "link" was used to mean both the relation-level entry (**Link**) and the individual hyperlink target (**Link Object**) -- resolved: **Link** is the relation-keyed container; **Link Object** is the target with an **Href**.
- "embedded" was used to mean both the named entry (**Embedded Resource**) and the collection property on a **Resource** (**Embedded Resource Collection**) -- resolved: these are distinct types at different levels of the hierarchy.
- "force array" applies to two distinct mechanisms: **Force Array** (on **Links**, controlling `_links` shape) and **Force Write As Collection** (on **Embedded Resources**, controlling `_embedded` shape) -- resolved: use the specific term for each.
Loading