Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion packages/core/src/lib/utils/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,19 @@ export default function parseProviders(params: {
const { options: userOptions, ...defaults } = provider

const id = (userOptions?.id ?? defaults.id) as string
// TODO: Support if properties have different types, e.g. authorization: string or object
// `authorization`/`token`/`userinfo` accept a string shorthand for just
// the endpoint URL. If a user only overrides part of that config (e.g.
// `authorization: { params: { scope } }`, without a new `url`), `merge`
// would otherwise see a string next to an object, discard the string
// default entirely, and lose the base URL. Promoting the string default
// to `{ url }` first lets `merge` combine them instead.
const defaultsAsRecord = defaults as Record<string, unknown>
for (const key of ["authorization", "token", "userinfo"] as const) {
const value = defaultsAsRecord[key]
if (typeof value === "string") {
defaultsAsRecord[key] = { url: value }
}
}
const merged = merge(defaults, userOptions, {
signinUrl: `${url}/signin/${id}`,
callbackUrl: `${url}/callback/${id}`,
Expand Down
40 changes: 40 additions & 0 deletions packages/core/test/providers.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { describe, expect, it } from "vitest"
import parseProviders from "../src/lib/utils/providers"
import Spotify from "../src/providers/spotify"
import { testConfig } from "./utils"

describe("parseProviders", () => {
it("merges a params-only authorization override into a string-shorthand default without losing the base URL", () => {
// Spotify's `authorization` default is a plain string
// ("https://accounts.spotify.com/authorize?scope=user-read-email").
// Overriding just the scope, as the docs recommend, must not discard
// that base URL.
const config = testConfig({
providers: [
Spotify({
clientId: "client-id",
clientSecret: "client-secret",
authorization: {
params: { scope: "user-read-email playlist-read-private" },
},
}),
],
})

const { providers } = parseProviders({
url: new URL("http://localhost:3000/auth"),
config,
})

const spotify = providers[0] as any

expect(spotify.authorization.url).toBeInstanceOf(URL)
expect(spotify.authorization.url.origin).toBe(
"https://accounts.spotify.com"
)
expect(spotify.authorization.url.pathname).toBe("/authorize")
expect(spotify.authorization.url.searchParams.get("scope")).toBe(
"user-read-email playlist-read-private"
)
})
})
Loading