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`