Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add client internal query params #349

Merged
merged 7 commits into from
Sep 17, 2024
Merged
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
19 changes: 19 additions & 0 deletions src/buildQueryURL.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
import { castArray } from "./lib/castArray"
import { devMsg } from "./lib/devMsg"

import { version } from "../package.json"

/**
* The query parameter used to indicate if the client is in development mode to
* the API.
*/
const PRISMIC_DEV_PARAM = "x-d"

/**
* The query parameter used to indicate the version of the client to the API.
*/
const PRISMIC_CLIENT_VERSION_PARAM = "x-c"

/**
* Create a union of the given object's values, and optionally specify which
* keys to get the values from.
Expand Down Expand Up @@ -374,5 +387,11 @@ export const buildQueryURL = (
}
}

url.searchParams.set(PRISMIC_CLIENT_VERSION_PARAM, `js-${version}`)

if (process.env.NODE_ENV === "development") {
url.searchParams.set(PRISMIC_DEV_PARAM, "1")
}

return url.toString()
}
55 changes: 39 additions & 16 deletions test/buildQueryURL.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { expect, it, vi } from "vitest"

import { version } from "../package.json"

import * as prismic from "../src"

const endpoint = prismic.getRepositoryEndpoint("qwerty")
const xClientVersionParam = `&x-c=js-${version}`

it("includes ref", () => {
expect(prismic.buildQueryURL(endpoint, { ref: "ref" })).toBe(
"https://qwerty.cdn.prismic.io/api/v2/documents/search?ref=ref",
`https://qwerty.cdn.prismic.io/api/v2/documents/search?ref=ref${xClientVersionParam}`,
)
})

Expand All @@ -19,7 +22,7 @@ it("supports single filter", () => {
}),
),
).toBe(
"https://qwerty.cdn.prismic.io/api/v2/documents/search?q=[[has(my.document.title)]]&ref=ref",
`https://qwerty.cdn.prismic.io/api/v2/documents/search?q=[[has(my.document.title)]]&ref=ref${xClientVersionParam}`,
)

// TODO: Remove when we remove support for deprecated `predicates` argument.
Expand All @@ -31,7 +34,7 @@ it("supports single filter", () => {
}),
),
).toBe(
"https://qwerty.cdn.prismic.io/api/v2/documents/search?q=[[has(my.document.title)]]&ref=ref",
`https://qwerty.cdn.prismic.io/api/v2/documents/search?q=[[has(my.document.title)]]&ref=ref${xClientVersionParam}`,
)
})

Expand All @@ -47,7 +50,7 @@ it("supports multiple filters", () => {
}),
),
).toBe(
"https://qwerty.cdn.prismic.io/api/v2/documents/search?q=[[has(my.document.title)]]&q=[[has(my.document.subtitle)]]&ref=ref",
`https://qwerty.cdn.prismic.io/api/v2/documents/search?q=[[has(my.document.title)]]&q=[[has(my.document.subtitle)]]&ref=ref${xClientVersionParam}`,
)

// TODO: Remove when we remove support for deprecated `predicates` argument.
Expand All @@ -62,7 +65,7 @@ it("supports multiple filters", () => {
}),
),
).toBe(
"https://qwerty.cdn.prismic.io/api/v2/documents/search?q=[[has(my.document.title)]]&q=[[has(my.document.subtitle)]]&ref=ref",
`https://qwerty.cdn.prismic.io/api/v2/documents/search?q=[[has(my.document.title)]]&q=[[has(my.document.subtitle)]]&ref=ref${xClientVersionParam}`,
)
})

Expand All @@ -85,7 +88,7 @@ it("supports params", () => {
}),
),
).toBe(
"https://qwerty.cdn.prismic.io/api/v2/documents/search?ref=ref&access_token=accessToken&pageSize=1&page=1&after=after&fetch=fetch&fetchLinks=fetchLinks&graphQuery=graphQuery&lang=lang&orderings=[orderings]&routes=routes&brokenRoute=brokenRoute",
`https://qwerty.cdn.prismic.io/api/v2/documents/search?ref=ref&access_token=accessToken&pageSize=1&page=1&after=after&fetch=fetch&fetchLinks=fetchLinks&graphQuery=graphQuery&lang=lang&orderings=[orderings]&routes=routes&brokenRoute=brokenRoute${xClientVersionParam}`,
)
})

Expand All @@ -105,7 +108,9 @@ it("ignores nullish params", () => {
orderings: undefined,
}),
),
).toBe("https://qwerty.cdn.prismic.io/api/v2/documents/search?ref=ref")
).toBe(
`https://qwerty.cdn.prismic.io/api/v2/documents/search?ref=ref${xClientVersionParam}`,
)
})

it("supports array fetch param", () => {
Expand All @@ -117,7 +122,7 @@ it("supports array fetch param", () => {
}),
),
).toBe(
"https://qwerty.cdn.prismic.io/api/v2/documents/search?ref=ref&fetch=title,subtitle",
`https://qwerty.cdn.prismic.io/api/v2/documents/search?ref=ref&fetch=title,subtitle${xClientVersionParam}`,
)
})

Expand All @@ -130,7 +135,7 @@ it("supports array fetchLinks param", () => {
}),
),
).toBe(
"https://qwerty.cdn.prismic.io/api/v2/documents/search?ref=ref&fetchLinks=page.link,page.second_link",
`https://qwerty.cdn.prismic.io/api/v2/documents/search?ref=ref&fetchLinks=page.link,page.second_link${xClientVersionParam}`,
)
})

Expand All @@ -144,7 +149,7 @@ it("supports empty orderings param", () => {
}),
),
).toBe(
"https://qwerty.cdn.prismic.io/api/v2/documents/search?ref=ref&orderings=[]",
`https://qwerty.cdn.prismic.io/api/v2/documents/search?ref=ref&orderings=[]${xClientVersionParam}`,
)

expect(
Expand All @@ -155,7 +160,7 @@ it("supports empty orderings param", () => {
}),
),
).toBe(
"https://qwerty.cdn.prismic.io/api/v2/documents/search?ref=ref&orderings=[]",
`https://qwerty.cdn.prismic.io/api/v2/documents/search?ref=ref&orderings=[]${xClientVersionParam}`,
)
})

Expand All @@ -169,7 +174,7 @@ it("supports array orderings param", () => {
}),
),
).toBe(
"https://qwerty.cdn.prismic.io/api/v2/documents/search?ref=ref&orderings=[page.title,page.subtitle]",
`https://qwerty.cdn.prismic.io/api/v2/documents/search?ref=ref&orderings=[page.title,page.subtitle]${xClientVersionParam}`,
)
})

Expand All @@ -183,7 +188,7 @@ it("supports setting direction of ordering param", () => {
}),
),
).toBe(
"https://qwerty.cdn.prismic.io/api/v2/documents/search?ref=ref&orderings=[page.title,page.subtitle]",
`https://qwerty.cdn.prismic.io/api/v2/documents/search?ref=ref&orderings=[page.title,page.subtitle]${xClientVersionParam}`,
)

expect(
Expand All @@ -198,7 +203,7 @@ it("supports setting direction of ordering param", () => {
}),
),
).toBe(
"https://qwerty.cdn.prismic.io/api/v2/documents/search?ref=ref&orderings=[page.title+desc,page.subtitle+desc]",
`https://qwerty.cdn.prismic.io/api/v2/documents/search?ref=ref&orderings=[page.title+desc,page.subtitle+desc]${xClientVersionParam}`,
)
})

Expand All @@ -219,7 +224,7 @@ it("supports single item routes param", () => {
).toBe(
`https://qwerty.cdn.prismic.io/api/v2/documents/search?ref=ref&routes=[${JSON.stringify(
route,
)}]`,
)}]${xClientVersionParam}`,
)
})

Expand Down Expand Up @@ -247,10 +252,28 @@ it("supports array routes param", () => {
).toBe(
`https://qwerty.cdn.prismic.io/api/v2/documents/search?ref=ref&routes=${JSON.stringify(
routes,
)}`,
)}${xClientVersionParam}`,
)
})

it("forwards `x-c` param in production", () => {
expect(prismic.buildQueryURL(endpoint, { ref: "ref" })).toBe(
`https://qwerty.cdn.prismic.io/api/v2/documents/search?ref=ref${xClientVersionParam}`,
)
})

it("forwards `x-c` and `x-d` param in development", () => {
const originalEnv = { ...process.env }

process.env.NODE_ENV = "development"

expect(prismic.buildQueryURL(endpoint, { ref: "ref" })).toBe(
`https://qwerty.cdn.prismic.io/api/v2/documents/search?ref=ref${xClientVersionParam}&x-d=1`,
)

process.env = originalEnv
})

it("warns if NODE_ENV is development and a string is provided to `orderings`", () => {
const originalEnv = { ...process.env }

Expand Down
23 changes: 23 additions & 0 deletions test/client-buildQueryURL.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ import { createTestClient } from "./__testutils__/createClient"
import { getMasterRef } from "./__testutils__/getMasterRef"
import { mockPrismicRestAPIV2 } from "./__testutils__/mockPrismicRestAPIV2"

import { version } from "../package.json"

import type * as prismic from "../src"

const xClientVersion = `js-${version}`

it("builds a query URL using the master ref", async (ctx) => {
const repositoryResponse = ctx.mock.api.repository()
const ref = getMasterRef(repositoryResponse)
Expand All @@ -21,6 +25,7 @@ it("builds a query URL using the master ref", async (ctx) => {

const expectedSearchParams = new URLSearchParams({
ref,
"x-c": xClientVersion,
})
url.searchParams.delete("integrationFieldsRef")
url.searchParams.sort()
Expand All @@ -31,6 +36,21 @@ it("builds a query URL using the master ref", async (ctx) => {
expect(url.searchParams.toString()).toBe(expectedSearchParams.toString())
})

it("includes the `x-d` param in development", async (ctx) => {
const originalEnv = { ...process.env }
process.env.NODE_ENV = "development"

mockPrismicRestAPIV2({ ctx })

const client = createTestClient()
const res = await client.buildQueryURL()
const url = new URL(res)

expect(url.searchParams.get("x-d")).toBe("1")

process.env = originalEnv
})

it("includes params if provided", async (ctx) => {
const params: prismic.BuildQueryURLArgs = {
accessToken: "custom-accessToken",
Expand All @@ -49,6 +69,7 @@ it("includes params if provided", async (ctx) => {
lang: params.lang?.toString() ?? "",
// TODO: Remove when Authorization header support works in browsers with CORS.
access_token: params.accessToken ?? "",
"x-c": xClientVersion,
})

url.searchParams.delete("integrationFieldsRef")
Expand Down Expand Up @@ -78,6 +99,7 @@ it("includes default params if provided", async (ctx) => {
lang: clientConfig.defaultParams?.lang?.toString() ?? "",
// TODO: Remove when Authorization header support works in browsers with CORS.
access_token: clientConfig.accessToken ?? "",
"x-c": xClientVersion,
})

url.searchParams.delete("integrationFieldsRef")
Expand Down Expand Up @@ -111,6 +133,7 @@ it("merges params and default params if provided", async (ctx) => {
page: clientConfig.defaultParams?.page?.toString() ?? "",
// TODO: Remove when Authorization header support works in browsers with CORS.
access_token: clientConfig.accessToken ?? "",
"x-c": xClientVersion,
})

url.searchParams.delete("integrationFieldsRef")
Expand Down
Loading