@@ -73,3 +73,116 @@ describe("Auth", () => {
7373 } ) ,
7474 )
7575} )
76+
77+ describe ( "Auth Profiles" , ( ) => {
78+ it . instance ( "set and get with profile" , ( ) =>
79+ Effect . gen ( function * ( ) {
80+ const auth = yield * Auth . Service
81+ yield * auth . set ( "openrouter" , { type : "api" , key : "sk-default" } )
82+ yield * auth . set ( "openrouter" , { type : "api" , key : "sk-work" } , "work" )
83+ yield * auth . set ( "openrouter" , { type : "api" , key : "sk-personal" } , "personal" )
84+
85+ const def = yield * auth . get ( "openrouter" )
86+ expect ( def ?. type ) . toBe ( "api" )
87+ if ( def ?. type === "api" ) expect ( def . key ) . toBe ( "sk-default" )
88+
89+ const work = yield * auth . get ( "openrouter" , "work" )
90+ expect ( work ?. type ) . toBe ( "api" )
91+ if ( work ?. type === "api" ) expect ( work . key ) . toBe ( "sk-work" )
92+
93+ const personal = yield * auth . get ( "openrouter" , "personal" )
94+ expect ( personal ?. type ) . toBe ( "api" )
95+ if ( personal ?. type === "api" ) expect ( personal . key ) . toBe ( "sk-personal" )
96+ } ) ,
97+ )
98+
99+ it . instance ( "profiles lists all profiles for a provider" , ( ) =>
100+ Effect . gen ( function * ( ) {
101+ const auth = yield * Auth . Service
102+ yield * auth . set ( "openrouter" , { type : "api" , key : "sk-default" } )
103+ yield * auth . set ( "openrouter" , { type : "api" , key : "sk-work" } , "work" )
104+
105+ const profiles = yield * auth . profiles ( "openrouter" )
106+ expect ( profiles . length ) . toBe ( 2 )
107+ const names = profiles . map ( ( p ) => p . profile ) . sort ( )
108+ expect ( names ) . toEqual ( [ undefined , "work" ] )
109+ } ) ,
110+ )
111+
112+ it . instance ( "hasDefault returns true when default exists" , ( ) =>
113+ Effect . gen ( function * ( ) {
114+ const auth = yield * Auth . Service
115+ yield * auth . set ( "openrouter" , { type : "api" , key : "sk-default" } )
116+
117+ expect ( yield * auth . hasDefault ( "openrouter" ) ) . toBe ( true )
118+ expect ( yield * auth . hasDefault ( "anthropic" ) ) . toBe ( false )
119+ } ) ,
120+ )
121+
122+ it . instance ( "setDefault swaps named profile to default" , ( ) =>
123+ Effect . gen ( function * ( ) {
124+ const auth = yield * Auth . Service
125+ yield * auth . set ( "openrouter" , { type : "api" , key : "sk-old-default" } )
126+ yield * auth . set ( "openrouter" , { type : "api" , key : "sk-work" } , "work" )
127+
128+ yield * auth . setDefault ( "openrouter" , "work" )
129+
130+ const def = yield * auth . get ( "openrouter" )
131+ expect ( def ?. type ) . toBe ( "api" )
132+ if ( def ?. type === "api" ) expect ( def . key ) . toBe ( "sk-work" )
133+
134+ const old = yield * auth . get ( "openrouter" , "work" )
135+ expect ( old ?. type ) . toBe ( "api" )
136+ if ( old ?. type === "api" ) expect ( old . key ) . toBe ( "sk-old-default" )
137+ } ) ,
138+ )
139+
140+ it . instance ( "remove with profile only removes that profile" , ( ) =>
141+ Effect . gen ( function * ( ) {
142+ const auth = yield * Auth . Service
143+ yield * auth . set ( "openrouter" , { type : "api" , key : "sk-default" } )
144+ yield * auth . set ( "openrouter" , { type : "api" , key : "sk-work" } , "work" )
145+
146+ yield * auth . remove ( "openrouter" , "work" )
147+
148+ const def = yield * auth . get ( "openrouter" )
149+ expect ( def ?. type ) . toBe ( "api" )
150+
151+ const work = yield * auth . get ( "openrouter" , "work" )
152+ expect ( work ) . toBeUndefined ( )
153+ } ) ,
154+ )
155+ } )
156+
157+ describe ( "Auth parseKey / buildKey" , ( ) => {
158+ it ( "parseKey returns providerID only for simple keys" , ( ) => {
159+ expect ( Auth . parseKey ( "openrouter" ) ) . toEqual ( { providerID : "openrouter" } )
160+ expect ( Auth . parseKey ( "anthropic" ) ) . toEqual ( { providerID : "anthropic" } )
161+ } )
162+
163+ it ( "parseKey splits providerID and profile" , ( ) => {
164+ expect ( Auth . parseKey ( "openrouter:work" ) ) . toEqual ( { providerID : "openrouter" , profile : "work" } )
165+ expect ( Auth . parseKey ( "anthropic:personal" ) ) . toEqual ( { providerID : "anthropic" , profile : "personal" } )
166+ } )
167+
168+ it ( "buildKey creates simple key when no profile" , ( ) => {
169+ expect ( Auth . buildKey ( "openrouter" ) ) . toBe ( "openrouter" )
170+ expect ( Auth . buildKey ( "openrouter" , undefined ) ) . toBe ( "openrouter" )
171+ } )
172+
173+ it ( "buildKey creates composite key with profile" , ( ) => {
174+ expect ( Auth . buildKey ( "openrouter" , "work" ) ) . toBe ( "openrouter:work" )
175+ } )
176+
177+ it ( "validateProfileName accepts valid names" , ( ) => {
178+ expect ( Auth . validateProfileName ( "work" ) ) . toBe ( true )
179+ expect ( Auth . validateProfileName ( "my-profile" ) ) . toBe ( true )
180+ expect ( Auth . validateProfileName ( "profile_1" ) ) . toBe ( true )
181+ } )
182+
183+ it ( "validateProfileName rejects invalid names" , ( ) => {
184+ expect ( Auth . validateProfileName ( "" ) ) . toBe ( false )
185+ expect ( Auth . validateProfileName ( "my profile" ) ) . toBe ( false )
186+ expect ( Auth . validateProfileName ( "my@profile" ) ) . toBe ( false )
187+ } )
188+ } )
0 commit comments