Skip to content

Commit 1d9236b

Browse files
committed
Sanitize slice names in static match field identifiers
Slice names from FHIR may contain special characters like hyphens or [x] brackets that are invalid in TypeScript identifiers. Strip [x] and replace other special chars with underscores for static field names.
1 parent de14ae4 commit 1d9236b

1 file changed

Lines changed: 6 additions & 4 deletions

File tree

src/api/writer-generator/typescript/profile.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ import {
3838
import { resolveFieldTsType, resolvePrimitiveType, tsEnumType, tsGet, tsTypeFromIdentifier } from "./utils";
3939
import type { TypeScript } from "./writer";
4040

41+
const tsSliceStaticName = (name: string): string => name.replace(/\[x\]/g, "").replace(/[^a-zA-Z0-9_$]/g, "_");
42+
4143
type ProfileFactoryInfo = {
4244
autoFields: { name: string; value: string }[];
4345
/** Array fields with required slices — optional param with auto-merge of required stubs */
@@ -663,7 +665,7 @@ export const generateProfileClass = (
663665
w.line();
664666
}
665667
for (const sliceDef of sliceDefs) {
666-
const staticName = `${sliceDef.sliceName}SliceMatch`;
668+
const staticName = `${tsSliceStaticName(sliceDef.sliceName)}SliceMatch`;
667669
w.line(
668670
`private static readonly ${staticName}: Record<string, unknown> = ${JSON.stringify(sliceDef.match)}`,
669671
);
@@ -685,7 +687,7 @@ export const generateProfileClass = (
685687
w.curlyBlock(["static", "createResource", `(${paramSignature})`, `: ${tsBaseResourceName}`], () => {
686688
// Generate merge logic for slice auto-fields
687689
for (const f of factoryInfo.sliceAutoFields) {
688-
const matchRefs = f.sliceNames.map((s) => `${profileClassName}.${s}SliceMatch`);
690+
const matchRefs = f.sliceNames.map((s) => `${profileClassName}.${tsSliceStaticName(s)}SliceMatch`);
689691
w.line(`const ${f.name}WithDefaults = ensureSliceDefaults(`);
690692
w.indentBlock(() => {
691693
w.line(`[...(args.${f.name} ?? [])],`);
@@ -790,7 +792,7 @@ export const generateProfileClass = (
790792
const methodName =
791793
sliceMethodNames.get(sliceDef) ?? tsQualifiedSliceMethodName(sliceDef.fieldName, sliceDef.sliceName);
792794
const typeName = tsSliceInputTypeName(tsProfileName, sliceDef.fieldName, sliceDef.sliceName);
793-
const matchRef = `${profileClassName}.${sliceDef.sliceName}SliceMatch`;
795+
const matchRef = `${profileClassName}.${tsSliceStaticName(sliceDef.sliceName)}SliceMatch`;
794796
const tsField = tsFieldName(sliceDef.fieldName);
795797
const fieldAccess = tsGet("this.resource", tsField);
796798
// Make input optional when there are no required fields (input can be empty object)
@@ -916,7 +918,7 @@ export const generateProfileClass = (
916918
if (generatedGetMethods.has(getMethodName)) continue;
917919
generatedGetMethods.add(getMethodName);
918920
const typeName = tsSliceInputTypeName(tsProfileName, sliceDef.fieldName, sliceDef.sliceName);
919-
const matchRef = `${profileClassName}.${sliceDef.sliceName}SliceMatch`;
921+
const matchRef = `${profileClassName}.${tsSliceStaticName(sliceDef.sliceName)}SliceMatch`;
920922
const matchKeys = JSON.stringify(Object.keys(sliceDef.match));
921923
const tsField = tsFieldName(sliceDef.fieldName);
922924
const fieldAccess = tsGet("this.resource", tsField);

0 commit comments

Comments
 (0)