@@ -40,7 +40,11 @@ const OptionsSchema = v.strictObject({
4040type Options = v . InferOutput < typeof OptionsSchema > ;
4141
4242type AddonArgsIn = { id : string ; options ?: string [ ] } ;
43- type AddonArgsOut = AddonArgsIn & { options : string [ ] ; kind : 'official' | 'file' | 'scoped' } ;
43+ type AddonArgsOut = AddonArgsIn & {
44+ options : string [ ] ;
45+ kind : 'official' | 'file' | 'scoped' ;
46+ resolvedId : string ;
47+ } ;
4448
4549// infers the workspace cwd if a `package.json` resides in a parent directory
4650const defaultPkgPath = pkg . up ( ) ;
@@ -229,7 +233,7 @@ export async function resolveAddons(
229233 // Resolve community addons (file: and scoped packages)
230234 if ( communityAddonArgs . length > 0 ) {
231235 const communitySpecifiers = communityAddonArgs . map ( ( addon ) => addon . id ) ;
232- const communityAddons = await resolveNonOfficialAddons ( cwd , communitySpecifiers , downloadCheck ) ;
236+ const communityAddons = await resolveNonOfficialAddons ( cwd , communityAddonArgs , downloadCheck ) ;
233237
234238 // Map community addons by position (they're resolved in the same order)
235239 communitySpecifiers . forEach ( ( specifier , index ) => {
@@ -731,18 +735,30 @@ export function sanitizeAddons(addonArgs: AddonArgsIn[]): AddonArgsOut[] {
731735 toRet . set ( official . id , {
732736 id : official . id ,
733737 options : addon . options ?? [ ] ,
734- kind : 'official'
738+ kind : 'official' ,
739+ resolvedId : official . id
735740 } ) ;
736741 } else if ( addon . id . startsWith ( 'file:' ) ) {
737- const location = addon . id . replace ( 'file:' , '' ) . trim ( ) ;
738- if ( ! location ) {
742+ const resolvedId = addon . id . replace ( 'file:' , '' ) . trim ( ) ;
743+ if ( ! resolvedId ) {
739744 invalidAddons . push ( 'file:' ) ;
740745 continue ;
741746 }
742- toRet . set ( addon . id , { id : addon . id , options : addon . options ?? [ ] , kind : 'file' } ) ;
747+ toRet . set ( addon . id , {
748+ id : addon . id ,
749+ options : addon . options ?? [ ] ,
750+ kind : 'file' ,
751+ resolvedId
752+ } ) ;
743753 } else if ( addon . id . startsWith ( '@' ) ) {
744754 // Scoped package (e.g., @org/name)
745- toRet . set ( addon . id , { id : addon . id , options : addon . options ?? [ ] , kind : 'scoped' } ) ;
755+ const resolvedId = addon . id . includes ( '/' ) ? addon . id : addon . id + '/sv' ;
756+ toRet . set ( addon . id , {
757+ id : addon . id ,
758+ options : addon . options ?? [ ] ,
759+ kind : 'scoped' ,
760+ resolvedId
761+ } ) ;
746762 } else {
747763 invalidAddons . push ( addon . id ) ;
748764 }
@@ -849,18 +865,40 @@ function getOptionChoices(details: ResolvedAddon) {
849865
850866export async function resolveNonOfficialAddons (
851867 cwd : string ,
852- addons : string [ ] ,
868+ addons : AddonArgsOut [ ] ,
853869 downloadCheck : boolean
854870) {
855871 const selectedAddons : ResolvedAddon [ ] = [ ] ;
856872 const highlighter = getHighlighter ( ) ;
857873 const { start, stop } = p . spinner ( ) ;
858874
859875 try {
860- start ( `Resolving ${ addons . map ( ( id ) => highlighter . addon ( id ) ) . join ( ', ' ) } packages` ) ;
876+ start ( `Resolving ${ addons . map ( ( a ) => highlighter . addon ( a . id ) ) . join ( ', ' ) } packages` ) ;
877+
878+ // Do this only for npm addons
879+ // const npmAddons = addons.filter((a) => a.kind !== 'file' && a.kind !== 'official');
880+ // if (npmAddons.length > 0) {
881+ // let blocklist: { npm_names: string[] } = { npm_names: [] } as any;
882+ // try {
883+ // const res = await fetch(
884+ // 'https://raw.githubusercontent.com/sveltejs/cli/refs/heads/feat/community-add-on-draft-0/packages/sv/blocklist.json'
885+ // );
886+ // blocklist = await res.json();
887+ // } catch {
888+ // throw new Error('Failed to fetch blocklist');
889+ // }
890+ // const blockedNpmAddons = npmAddons.filter((a) => blocklist.npm_names.includes(a.resolvedId));
891+ // if (blockedNpmAddons.length > 0) {
892+ // const h = getHighlighter();
893+ // common.errorAndExit(
894+ // `${blockedNpmAddons.map((a) => h.env(a.id)).join(', ')} blocked from being installed.`
895+ // );
896+ // }
897+ // }
898+
861899 const pkgs = await Promise . all (
862- addons . map ( async ( id ) => {
863- return await getPackageJSON ( { cwd, packageName : id } ) ;
900+ addons . map ( async ( a ) => {
901+ return await getPackageJSON ( { cwd, packageName : a . id } ) ;
864902 } )
865903 ) ;
866904 stop ( 'Resolved community add-on packages' ) ;
@@ -897,7 +935,7 @@ export async function resolveNonOfficialAddons(
897935 } catch ( err ) {
898936 const msg = err instanceof Error ? err . message : 'Unknown error' ;
899937 common . errorAndExit (
900- `Failed to resolve ${ addons . map ( ( id ) => highlighter . addon ( id ) ) . join ( ', ' ) } \n${ highlighter . optional ( msg ) } `
938+ `Failed to resolve ${ addons . map ( ( a ) => highlighter . addon ( a . id ) ) . join ( ', ' ) } \n${ highlighter . optional ( msg ) } `
901939 ) ;
902940 }
903941 return selectedAddons ;
0 commit comments