Skip to content

Commit 5d109c6

Browse files
authored
Merge pull request #131 from atomic-ehr/chore/cleanup-dead-code-update-docs
TS: Remove dead stripMatchKeys, update CLAUDE.md with profile API docs
2 parents f9c36c8 + fa60420 commit 5d109c6

4 files changed

Lines changed: 41 additions & 39 deletions

File tree

CLAUDE.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,47 @@ assets/api/writer-generator/
252252
- Use assets for static runtime code shared across all generated profiles (helpers, validators, base models)
253253
- Use programmatic generation (`w.lineSM()`, `w.curlyBlock()`) for code that varies per schema/profile
254254

255+
## TypeScript Profile API
256+
257+
### Slice Types
258+
259+
Each non-type-discriminated slice generates two types:
260+
- **`SliceFlat`** — setter input, discriminator fields omitted (auto-applied by setter)
261+
- **`SliceFlatAll`** — getter return, extends `SliceFlat` with readonly discriminator literals
262+
263+
```typescript
264+
// Setter input — only user data
265+
export type VSCatSliceFlat = Omit<CodeableConcept, "coding">;
266+
// Getter return — includes discriminator values
267+
export type VSCatSliceFlatAll = VSCatSliceFlat & {
268+
readonly coding: [{ code: "vital-signs"; system: "http://...observation-category" }];
269+
}
270+
```
271+
272+
Type-discriminated slices (e.g. `BundleEntry<Patient>`) use the typed base type directly — no `SliceFlat`/`SliceFlatAll` generated.
273+
274+
### Unbounded Slices (max: *)
275+
276+
Slices with `max: *` use array-based API:
277+
- **Setter**: `setOrganizationEntry(entries[])` — replaces all matched elements
278+
- **Getter**: `getOrganizationEntry()` — returns `T[] | undefined`
279+
280+
Single-element slices (`max: 1`) keep the existing single-item API.
281+
282+
### Reference Types for Family Types
283+
284+
When a reference target is a family type (e.g. `Resource`, `DomainResource`), the generated type uses `Reference<string /* Resource */>` instead of `Reference<"Resource">`. This makes narrower profile references like `Reference<"Patient">` assignable to the base type field.
285+
286+
Detection uses `mkIsFamilyType(tsIndex)` which checks `schema.typeFamily.resources.length > 0`.
287+
288+
### Slice Field Validation
289+
290+
`validate()` checks required fields inside matched slice elements via `validateSliceFields`. For constrained choice slices (e.g. BP `component.value[x]` restricted to `valueQuantity`), the variant is validated as required:
291+
292+
```
293+
"observation-bp.component[SystolicBP].valueQuantity is required"
294+
```
295+
255296
## Common Development Patterns
256297
257298
### Adding a New Generator Feature

assets/api/writer-generator/typescript/profile-helpers.ts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -203,19 +203,6 @@ export const extractComplexExtension = <T = Record<string, unknown>>(
203203
// Slice helpers
204204
// ---------------------------------------------------------------------------
205205

206-
/**
207-
* Remove discriminator keys from a slice element, returning only the
208-
* user-supplied portion. Used by slice getters so callers see a clean object
209-
* without the fixed discriminator values baked in.
210-
*/
211-
export const stripMatchKeys = <T>(slice: object, matchKeys: string[]): T => {
212-
const result = { ...slice } as Record<string, unknown>;
213-
for (const key of matchKeys) {
214-
delete result[key];
215-
}
216-
return result as T;
217-
};
218-
219206
/**
220207
* Wrap a flat input object under a choice-type key before inserting into a
221208
* slice. For example, a Quantity value destined for `valueQuantity` is

examples/typescript-r4/fhir-types/profile-helpers.ts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -203,19 +203,6 @@ export const extractComplexExtension = <T = Record<string, unknown>>(
203203
// Slice helpers
204204
// ---------------------------------------------------------------------------
205205

206-
/**
207-
* Remove discriminator keys from a slice element, returning only the
208-
* user-supplied portion. Used by slice getters so callers see a clean object
209-
* without the fixed discriminator values baked in.
210-
*/
211-
export const stripMatchKeys = <T>(slice: object, matchKeys: string[]): T => {
212-
const result = { ...slice } as Record<string, unknown>;
213-
for (const key of matchKeys) {
214-
delete result[key];
215-
}
216-
return result as T;
217-
};
218-
219206
/**
220207
* Wrap a flat input object under a choice-type key before inserting into a
221208
* slice. For example, a Quantity value destined for `valueQuantity` is

examples/typescript-us-core/fhir-types/profile-helpers.ts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -203,19 +203,6 @@ export const extractComplexExtension = <T = Record<string, unknown>>(
203203
// Slice helpers
204204
// ---------------------------------------------------------------------------
205205

206-
/**
207-
* Remove discriminator keys from a slice element, returning only the
208-
* user-supplied portion. Used by slice getters so callers see a clean object
209-
* without the fixed discriminator values baked in.
210-
*/
211-
export const stripMatchKeys = <T>(slice: object, matchKeys: string[]): T => {
212-
const result = { ...slice } as Record<string, unknown>;
213-
for (const key of matchKeys) {
214-
delete result[key];
215-
}
216-
return result as T;
217-
};
218-
219206
/**
220207
* Wrap a flat input object under a choice-type key before inserting into a
221208
* slice. For example, a Quantity value destined for `valueQuantity` is

0 commit comments

Comments
 (0)