From 3e7b772e3e76b7d4747620de2ee8f0f6675ffabb Mon Sep 17 00:00:00 2001 From: Malte Sussdorff Date: Mon, 20 Apr 2026 10:21:20 +0200 Subject: [PATCH] fix(profile): avoid duplicate meta key when meta is a factory param MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a profile exposes `meta` as a required factory param (e.g. KBV FOR/ERP profiles where `meta.profile` is pinned via min=1), the TypeScript profile writer emitted two `meta:` keys in the same `createResource` object literal — the first from the generic param loop and the second from the unconditional `meta: { profile: [...] }` emission. This produced TypeScript TS1117 errors and silently dropped any caller-supplied `meta.tag` / `meta.source` / extra profile URLs, because the second key overwrote the first. Fix: when `meta` is already in `allFields`, suppress the generic emission and merge the caller-supplied meta with the profile's canonical URL: meta: { ...args.meta, profile: [...(args.meta?.profile ?? []), canonicalUrl] } Profiles without `meta` in params are unchanged: meta: { profile: [canonicalUrl] } Applies to both the Input-helper branch (with extension slices) and the standard branch. Typecheck on consuming project (mira-adapters, 10+ KBV profiles) goes from 9 TS1117 errors to 0 after regeneration. --- .../writer-generator/typescript/profile.ts | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/api/writer-generator/typescript/profile.ts b/src/api/writer-generator/typescript/profile.ts index dc730143..613bef65 100644 --- a/src/api/writer-generator/typescript/profile.ts +++ b/src/api/writer-generator/typescript/profile.ts @@ -488,14 +488,22 @@ const generateFactoryMethods = ( } w.line(); const extensionVar = extSliceField ? "extensionWithDefaults" : "resolvedExtensions"; + const hasMetaParam = allFields.some((f) => f.name === "meta"); w.curlyBlock([`const resource: ${tsBaseResourceName} =`], () => { for (const f of allFields) { if (f.name === "extension") continue; + if (f.name === "meta" && hasMeta) continue; w.line(`${f.name}: ${f.value},`); } w.line(`extension: ${extensionVar},`); if (hasMeta) { - w.line(`meta: { profile: [${profileClassName}.canonicalUrl] },`); + if (hasMetaParam) { + w.line( + `meta: { ...args.meta, profile: [...(args.meta?.profile ?? []), ${profileClassName}.canonicalUrl] },`, + ); + } else { + w.line(`meta: { profile: [${profileClassName}.canonicalUrl] },`); + } } }); @@ -530,12 +538,20 @@ const generateFactoryMethods = ( if (isPrimitiveIdentifier(flatProfile.base)) { w.lineSM(`const resource = undefined as unknown as ${tsBaseResourceName}`); } else { + const hasMetaParam = allFields.some((f) => f.name === "meta"); w.curlyBlock([`const resource: ${tsBaseResourceName} =`], () => { for (const f of allFields) { + if (f.name === "meta" && hasMeta) continue; w.line(`${f.name}: ${f.value},`); } if (hasMeta) { - w.line(`meta: { profile: [${profileClassName}.canonicalUrl] },`); + if (hasMetaParam) { + w.line( + `meta: { ...args.meta, profile: [...(args.meta?.profile ?? []), ${profileClassName}.canonicalUrl] },`, + ); + } else { + w.line(`meta: { profile: [${profileClassName}.canonicalUrl] },`); + } } }); }