@@ -54,14 +54,35 @@ function writeCache(cache: RegistryCache): void {
5454 }
5555}
5656
57+ /**
58+ * 解析 first-party index.json。
59+ * 契约与 tools/fetch-module.mjs 一致:权威映射在 `modules` 字段下
60+ * (`{ version, modules: { <folder>: { repo, tag } } }`),忽略 `_` 前缀元数据键。
61+ */
62+ function parseRegistryIndex ( json : unknown ) : RegistryIndex {
63+ if ( typeof json !== "object" || json === null || Array . isArray ( json ) ) {
64+ throw new Error ( "registry index must be a JSON object with a 'modules' field" ) ;
65+ }
66+ const root = json as Record < string , unknown > ;
67+ const modulesRaw = root . modules ;
68+ if ( typeof modulesRaw !== "object" || modulesRaw === null || Array . isArray ( modulesRaw ) ) {
69+ throw new Error ( "registry index must have a 'modules' object mapping id → { repo, tag }" ) ;
70+ }
71+ const filtered : RegistryIndex = { } ;
72+ for ( const [ k , v ] of Object . entries ( modulesRaw as Record < string , unknown > ) ) {
73+ if ( k . startsWith ( "_" ) ) continue ;
74+ if ( typeof v !== "object" || v === null || Array . isArray ( v ) ) continue ;
75+ const entry = v as Record < string , unknown > ;
76+ if ( typeof entry . repo !== "string" || typeof entry . tag !== "string" ) continue ;
77+ filtered [ k ] = { repo : entry . repo , tag : entry . tag } ;
78+ }
79+ return filtered ;
80+ }
81+
5782async function fetchFresh ( ) : Promise < RegistryIndex > {
5883 const res = await fetch ( INDEX_URL , { headers : { "User-Agent" : "sfmc-cli" } } ) ;
5984 if ( ! res . ok ) throw new Error ( `HTTP ${ res . status } for ${ INDEX_URL } ` ) ;
60- const json = ( await res . json ( ) ) as unknown ;
61- if ( typeof json !== "object" || json === null || Array . isArray ( json ) ) {
62- throw new Error ( "registry index must be a JSON object mapping id → { repo, tag }" ) ;
63- }
64- return json as RegistryIndex ;
85+ return parseRegistryIndex ( await res . json ( ) ) ;
6586}
6687
6788export interface RegistryResult {
0 commit comments