Skip to content
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
2 changes: 1 addition & 1 deletion next-env.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next/dev/types/routes.d.ts";
import "./.next/types/routes.d.ts";

// NOTE: This file should not be edited
// see https://nextjs.org/docs/pages/api-reference/config/typescript for more information.
23 changes: 17 additions & 6 deletions pages/api/vs-marketplace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,19 @@ export default createBadgenHandler({
title: 'Visual Studio Marketplace',
examples: {
'/vs-marketplace/v/vscodevim.vim': 'version',
'/vs-marketplace/v/ms-python.vscode-pylance/latest': 'version (including pre-release)',
'/vs-marketplace/i/vscodevim.vim': 'installs',
'/vs-marketplace/d/vscodevim.vim': 'downloads',
'/vs-marketplace/rating/vscodevim.vim': 'rating',
},
handlers: {
'/vs-marketplace/:topic<v|i|d|rating>/:pkg': handler
'/vs-marketplace/:topic<v|i|d|rating>/:pkg/:tag?': handler
}
})

async function handler ({ topic, pkg }: PathArgs) {
const { results } = await queryVSM(pkg)
async function handler ({ topic, pkg, tag }: PathArgs) {
const showLatest = tag === 'latest'
const { results } = await queryVSM(pkg, showLatest ? 979 : 467)
const extension = results[0].extensions[0]

if (!extension) {
Expand All @@ -30,7 +32,16 @@ async function handler ({ topic, pkg }: PathArgs) {

switch (topic) {
case 'v':
const version = extension.versions[0].version
let extensionVersion = extension.versions[0]
if (!showLatest) {
extensionVersion = extension.versions.find(ver => {
const isPreRelease = ver.properties?.some(prop =>
prop.key === 'Microsoft.VisualStudio.Code.PreRelease' && prop.value === 'true'
)
return !isPreRelease
}) || extension.versions[0]
}
const version = extensionVersion.version
return {
subject: 'VS Marketplace',
status: v(version),
Expand Down Expand Up @@ -65,13 +76,13 @@ async function handler ({ topic, pkg }: PathArgs) {
}
}

const queryVSM = async pkgName => {
const queryVSM = async (pkgName, flags = 467) => {
const endpoint = 'https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery'
return got.post(endpoint, {
searchParams: { 'api-version': '3.0-preview.1' },
json: {
filters: [{ criteria: [{ filterType: 7, value: pkgName }] }],
flags: 914
flags
}
}).json<any>()
}
Expand Down
36 changes: 32 additions & 4 deletions test/e2e.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@ test('/static: simple static badge', async (t) => {
})


test('/memo: update "depoyed" badge', async (t) => {
if (!process.env.MEMO_BADGE_TOKEN) {
throw new Error('MEMO_BADGE_TOKEN is required to run this test')
}
test('/memo: update "depoyed" badge', { skip: !process.env.MEMO_BADGE_TOKEN }, async (t) => {
const status = getGitLastCommitDate()
const label = 'Deployed'
const color = getGitCurrentBranch() === 'main' ? 'green' : 'cyan'
Expand All @@ -38,6 +35,37 @@ test('/memo: update "depoyed" badge', async (t) => {
assert.deepEqual(result, { status, label, color })
})

test('/vs-marketplace: stable version badge', async (t) => {
const pkg = 'ms-python.vscode-pylance'
const defaultURL = `${BASE_URL}/vs-marketplace/v/${pkg}`
const latestURL = `${BASE_URL}/vs-marketplace/v/${pkg}/latest`

const [defaultRes, latestRes] = await Promise.all([
fetch(defaultURL),
fetch(latestURL)
])

assert.strictEqual(defaultRes.status, 200)
assert.strictEqual(latestRes.status, 200)

const defaultSvg = await defaultRes.text()
const latestSvg = await latestRes.text()

assert.ok(defaultSvg.includes('VS Marketplace'), 'Default SVG should contain "VS Marketplace"')
assert.ok(latestSvg.includes('VS Marketplace'), 'Latest SVG should contain "VS Marketplace"')

const defaultVer = defaultSvg.match(/v(\d+\.\d+\.\d+)/)?.[1]
const latestVer = latestSvg.match(/v(\d+\.\d+\.\d+)/)?.[1]

assert.ok(defaultVer, 'Should find a version in default badge')
assert.ok(latestVer, 'Should find a version in latest badge')

// At the time of testing, latest (pre-release) was 2026.2.101 and default (stable) was 2026.2.1
// Assert that they are different to ensure filtering is working correctly
assert.notStrictEqual(defaultVer, latestVer, `Default version (${defaultVer}) should be different from Latest version (${latestVer}) for ${pkg}`)
console.log(`Verified: Default (Stable: ${defaultVer}) is different from Latest (including Pre-release: ${latestVer})`)
})


test('/codeberg/stars/forgejo/forgejo', async (t) => {
const badgeURL = `${BASE_URL}/codeberg/stars/forgejo/forgejo`
Expand Down
Loading