itismyskillmarket 1.3.7 → 1.3.8

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.
package/dist/index.js CHANGED
@@ -1528,6 +1528,31 @@ import { fileURLToPath as fileURLToPath3 } from "url";
1528
1528
  var __filename2 = fileURLToPath3(import.meta.url);
1529
1529
  var __dirname2 = dirname(__filename2);
1530
1530
  var guiDir = join4(__dirname2, "..", "gui");
1531
+ var cache = /* @__PURE__ */ new Map();
1532
+ function getCached(key) {
1533
+ const entry = cache.get(key);
1534
+ if (!entry) return null;
1535
+ if (Date.now() > entry.expiry) {
1536
+ cache.delete(key);
1537
+ return null;
1538
+ }
1539
+ return entry.data;
1540
+ }
1541
+ function setCache(key, data, ttlMs = 6e4) {
1542
+ cache.set(key, { data, expiry: Date.now() + ttlMs });
1543
+ }
1544
+ async function throttledMap(items, fn, concurrency = 3) {
1545
+ const results = [];
1546
+ for (let i = 0; i < items.length; i += concurrency) {
1547
+ const batch = items.slice(i, i + concurrency);
1548
+ const batchResults = await Promise.all(batch.map((item, idx) => fn(item, i + idx)));
1549
+ results.push(...batchResults);
1550
+ if (i + concurrency < items.length) {
1551
+ await new Promise((r) => setTimeout(r, 200));
1552
+ }
1553
+ }
1554
+ return results;
1555
+ }
1531
1556
  var MIME_TYPES = {
1532
1557
  ".html": "text/html; charset=utf-8",
1533
1558
  ".js": "application/javascript; charset=utf-8",
@@ -1570,36 +1595,46 @@ API_ROUTES.GET["/api/skills"] = async (_req, res, url) => {
1570
1595
  const page = Math.max(1, parseInt(url.searchParams.get("page") || "1"));
1571
1596
  const limit = Math.min(100, Math.max(1, parseInt(url.searchParams.get("limit") || "20")));
1572
1597
  const search = url.searchParams.get("search") || "";
1573
- const offset = (page - 1) * limit;
1574
- const { packages, total } = await searchSkillmarketPackages({
1575
- from: offset,
1576
- size: limit,
1577
- keyword: search || void 0
1578
- });
1579
- const skills = (await Promise.all(
1580
- packages.map(async (pkgName) => {
1581
- try {
1582
- const info = await fetchNpmPackage(pkgName);
1583
- if (!info) return null;
1584
- const latestVersion = info["dist-tags"]?.latest || "unknown";
1585
- const pkg = info.versions?.[latestVersion];
1586
- const meta = pkg?.skillmarket;
1587
- return {
1588
- id: meta?.id || info.name.replace(/^@[^/]+\//, ""),
1589
- name: info.name,
1590
- displayName: meta?.displayName || info.name,
1591
- version: latestVersion,
1592
- description: pkg?.description || "",
1593
- platforms: meta?.platforms || [],
1594
- author: info.author?.name || pkg?.author?.name || "",
1595
- homepage: pkg?.homepage || "",
1596
- repository: pkg?.repository?.url || ""
1597
- };
1598
- } catch {
1599
- return null;
1598
+ const cacheKey = `search:${search}:limit:${limit}`;
1599
+ let searchResult = getCached(cacheKey);
1600
+ if (!searchResult) {
1601
+ searchResult = await searchSkillmarketPackages({
1602
+ from: 0,
1603
+ size: 100,
1604
+ // 一次拉取更多,避免分页
1605
+ keyword: search || void 0
1606
+ });
1607
+ setCache(cacheKey, searchResult, 3e4);
1608
+ }
1609
+ const { packages, total } = searchResult;
1610
+ const skillDetails = await throttledMap(packages, async (pkgName) => {
1611
+ try {
1612
+ const pkgCacheKey = `pkg:${pkgName}`;
1613
+ let info = getCached(pkgCacheKey);
1614
+ if (!info) {
1615
+ info = await fetchNpmPackage(pkgName);
1616
+ if (info) setCache(pkgCacheKey, info, 3e4);
1600
1617
  }
1601
- })
1602
- )).filter(Boolean);
1618
+ if (!info) return null;
1619
+ const latestVersion = info["dist-tags"]?.latest || "unknown";
1620
+ const pkg = info.versions?.[latestVersion];
1621
+ const meta = pkg?.skillmarket;
1622
+ return {
1623
+ id: meta?.id || info.name.replace(/^@[^/]+\//, ""),
1624
+ name: info.name,
1625
+ displayName: meta?.displayName || info.name,
1626
+ version: latestVersion,
1627
+ description: pkg?.description || "",
1628
+ platforms: meta?.platforms || [],
1629
+ author: info.author?.name || pkg?.author?.name || "",
1630
+ homepage: pkg?.homepage || "",
1631
+ repository: pkg?.repository?.url || ""
1632
+ };
1633
+ } catch {
1634
+ return null;
1635
+ }
1636
+ }, 3);
1637
+ const skills = skillDetails.filter(Boolean);
1603
1638
  const totalPages = Math.ceil(total / limit) || 1;
1604
1639
  jsonResponse(res, 200, { skills, page, totalPages, total });
1605
1640
  } catch (err) {
@@ -1654,7 +1689,12 @@ API_ROUTES.GET["/api/skill-info"] = async (_req, res, url) => {
1654
1689
  jsonResponse(res, 400, { error: 'Missing "skill" query parameter' });
1655
1690
  return;
1656
1691
  }
1657
- const info = await fetchNpmPackage(skillName);
1692
+ const cacheKey = `skill-info:${skillName}`;
1693
+ let info = getCached(cacheKey);
1694
+ if (!info) {
1695
+ info = await fetchNpmPackage(skillName);
1696
+ if (info) setCache(cacheKey, info, 3e4);
1697
+ }
1658
1698
  if (!info) {
1659
1699
  jsonResponse(res, 404, { error: `Skill "${skillName}" not found` });
1660
1700
  return;
package/gui/index.html CHANGED
@@ -25,7 +25,7 @@
25
25
  </button>
26
26
  </nav>
27
27
  <div class="sidebar-footer">
28
- <span class="version">v1.3.6</span>
28
+ <span class="version" id="gui-version">v1.3.8</span>
29
29
  </div>
30
30
  </aside>
31
31
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "itismyskillmarket",
3
- "version": "1.3.7",
3
+ "version": "1.3.8",
4
4
  "description": "Cross-platform skill manager for AI coding tools",
5
5
  "type": "module",
6
6
  "bin": {