@shnitzel/plugscout 0.3.26 → 0.3.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -107,6 +107,9 @@ async function checkNpmRegistry(pkg) {
107
107
  }
108
108
  async function checkVscodeMarketplace(vsixId) {
109
109
  const checkedAt = new Date().toISOString();
110
+ const error = (status, text) => ({
111
+ result: { source: 'vscode-marketplace', label: 'VS Code Marketplace', status, findings: text ? [{ severity: 'info', text }] : [], checkedAt },
112
+ });
110
113
  try {
111
114
  const res = await fetchWithTimeout('https://marketplace.visualstudio.com/_apis/public/gallery/extensionquery', {
112
115
  method: 'POST',
@@ -117,21 +120,28 @@ async function checkVscodeMarketplace(vsixId) {
117
120
  },
118
121
  body: JSON.stringify({
119
122
  filters: [{ criteria: [{ filterType: 7, value: vsixId }] }],
120
- flags: 0x200 | 0x100 | 0x20, // statistics + assetUri + excludeNonValidated
123
+ // statistics (0x200) + assetUri (0x100) + excludeNonValidated (0x20) + versionProperties (0x10)
124
+ flags: 0x200 | 0x100 | 0x20 | 0x10,
121
125
  }),
122
126
  }, 8000);
123
- if (!res.ok) {
124
- return { source: 'vscode-marketplace', label: 'VS Code Marketplace', status: 'error', findings: [], checkedAt };
125
- }
127
+ if (!res.ok)
128
+ return error('error');
126
129
  const data = await res.json();
127
130
  const ext = data.results?.[0]?.extensions?.[0];
128
131
  if (!ext) {
129
132
  return {
130
- source: 'vscode-marketplace', label: 'VS Code Marketplace', status: 'unavailable',
131
- findings: [{ severity: 'warn', text: 'Extension not found in marketplace — may have been removed' }],
132
- checkedAt,
133
+ result: {
134
+ source: 'vscode-marketplace', label: 'VS Code Marketplace', status: 'unavailable',
135
+ findings: [{ severity: 'warn', text: 'Extension not found in marketplace — may have been removed' }],
136
+ checkedAt,
137
+ },
133
138
  };
134
139
  }
140
+ // Extract GitHub repository URL from version properties
141
+ const props = ext.versions?.[0]?.properties ?? [];
142
+ const repoProp = props.find(p => p.key === 'Microsoft.VisualStudio.Services.Links.Source' ||
143
+ p.key === 'Microsoft.VisualStudio.Services.Links.GitHub');
144
+ const repositoryUrl = repoProp?.value?.includes('github.com') ? repoProp.value : undefined;
135
145
  const findings = [];
136
146
  const verified = ext.publisher.isDomainVerified ?? false;
137
147
  const latest = ext.versions?.[0];
@@ -147,13 +157,16 @@ async function checkVscodeMarketplace(vsixId) {
147
157
  findings.push({ severity: 'info', text: `${installs.toLocaleString()} installs` });
148
158
  }
149
159
  return {
150
- source: 'vscode-marketplace', label: 'VS Code Marketplace',
151
- status: verified ? 'clean' : 'flagged',
152
- findings, checkedAt,
160
+ result: {
161
+ source: 'vscode-marketplace', label: 'VS Code Marketplace',
162
+ status: verified ? 'clean' : 'flagged',
163
+ findings, checkedAt,
164
+ },
165
+ repositoryUrl,
153
166
  };
154
167
  }
155
168
  catch {
156
- return { source: 'vscode-marketplace', label: 'VS Code Marketplace', status: 'error', findings: [{ severity: 'info', text: 'Check timed out' }], checkedAt };
169
+ return error('error', 'Check timed out');
157
170
  }
158
171
  }
159
172
  function extractGithubOwnerRepo(url) {
@@ -258,15 +271,24 @@ export async function runLiveChecks(item, opts = {}) {
258
271
  checks.push(checkOsv(npmPkg));
259
272
  checks.push(checkNpmRegistry(npmPkg));
260
273
  }
274
+ // cursor-extension: marketplace first (to extract repo URL), then github check if found
275
+ const cursorMarketplaceResults = [];
261
276
  if (item.kind === 'cursor-extension') {
262
277
  const vsixId = typeof meta.vsixId === 'string' ? meta.vsixId : null;
263
278
  if (vsixId) {
264
- checks.push(checkVscodeMarketplace(vsixId));
279
+ const mkt = await checkVscodeMarketplace(vsixId);
280
+ cursorMarketplaceResults.push(mkt.result);
281
+ const ghOwnerRepo = mkt.repositoryUrl ? extractGithubOwnerRepo(mkt.repositoryUrl) : findGithubOwnerRepo(item, meta);
282
+ if (ghOwnerRepo) {
283
+ checks.push(checkGithubRepo(ghOwnerRepo));
284
+ }
265
285
  }
266
286
  }
267
- const ghOwnerRepo = findGithubOwnerRepo(item, meta);
268
- if (ghOwnerRepo) {
269
- checks.push(checkGithubRepo(ghOwnerRepo));
287
+ else {
288
+ const ghOwnerRepo = findGithubOwnerRepo(item, meta);
289
+ if (ghOwnerRepo) {
290
+ checks.push(checkGithubRepo(ghOwnerRepo));
291
+ }
270
292
  }
271
293
  if (item.kind === 'claude-plugin' || item.kind === 'claude-connector') {
272
294
  const installUrl = item.install.url;
@@ -274,9 +296,9 @@ export async function runLiveChecks(item, opts = {}) {
274
296
  checks.push(checkUrlHealth(installUrl));
275
297
  }
276
298
  }
277
- if (checks.length === 0)
299
+ const results = [...cursorMarketplaceResults, ...(checks.length > 0 ? await Promise.all(checks) : [])];
300
+ if (results.length === 0)
278
301
  return [];
279
- const results = await Promise.all(checks);
280
302
  await writeCache(item.id, results);
281
303
  return results;
282
304
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shnitzel/plugscout",
3
- "version": "0.3.26",
3
+ "version": "0.3.27",
4
4
  "description": "Claude plugins + Claude connectors + Copilot extensions + Skills + MCP security intelligence framework",
5
5
  "private": false,
6
6
  "type": "module",