diff --git a/next-env.d.ts b/next-env.d.ts
index 7996d352..19709046 100644
--- a/next-env.d.ts
+++ b/next-env.d.ts
@@ -1,6 +1,6 @@
///
///
-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.
diff --git a/pages/api/vs-marketplace.ts b/pages/api/vs-marketplace.ts
index 4ddd68b4..a6900cc2 100644
--- a/pages/api/vs-marketplace.ts
+++ b/pages/api/vs-marketplace.ts
@@ -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/:pkg': handler
+ '/vs-marketplace/:topic/: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) {
@@ -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),
@@ -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()
}
diff --git a/test/e2e.test.mjs b/test/e2e.test.mjs
index 9cc5a50a..81ab0057 100644
--- a/test/e2e.test.mjs
+++ b/test/e2e.test.mjs
@@ -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'
@@ -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`