3 Коммитууд b54bea36aa ... a6908320e6

Эзэн SHA1 Мессеж Огноо
  Aditya Arora a6908320e6 feat(dev-hub) Requested changes 1 өдөр өмнө
  Aditya Arora 2b80b9c35a feat(dev-hub) Search Feeds bug fix 2 өдөр өмнө
  Aditya Arora a916e1c07a feat(dev-hub) Include feeds in the search 2 өдөр өмнө

+ 114 - 2
apps/developer-hub/src/app/api/search/route.ts

@@ -1,5 +1,117 @@
-import { createFromSource } from "fumadocs-core/search/server";
+import type { AdvancedIndex } from "fumadocs-core/search/server";
+import { createSearchAPI } from "fumadocs-core/search/server";
+import { z } from "zod";
 
 import { source } from "../../../lib/source";
 
-export const { GET } = createFromSource(source);
+// Define schemas for type safety
+const hermesSchema = z.array(
+  z.object({
+    id: z.string(),
+    attributes: z.object({ symbol: z.string() }),
+  }),
+);
+
+const lazerSchema = z.array(
+  z.object({
+    symbol: z.string(),
+    name: z.string(),
+    pyth_lazer_id: z.number(),
+    description: z.string(),
+  }),
+);
+
+function toAdvancedIndex(
+  fee: z.infer<typeof hermesSchema>[number],
+): AdvancedIndex {
+  return {
+    title: `${fee.attributes.symbol} (Core)`,
+    description: `Price Feed ID: ${fee.id}`,
+    url: `/price-feeds/core/price-feeds/price-feed-ids?search=${fee.attributes.symbol}`,
+    id: fee.id,
+    tag: "price-feed-core",
+    structuredData: {
+      headings: [],
+      contents: [
+        { heading: "Symbol", content: fee.attributes.symbol },
+        { heading: "ID", content: fee.id },
+      ],
+    },
+  };
+}
+
+async function getHermesFeeds(): Promise<AdvancedIndex[]> {
+  try {
+    const results = await Promise.all(
+      ["https://hermes.pyth.network", "https://hermes-beta.pyth.network"].map(
+        async (url): Promise<AdvancedIndex[]> => {
+          const hermesResult = await fetch(new URL("/v2/price_feeds", url), {
+            next: { revalidate: 3600 },
+          });
+          const parsed = hermesSchema.safeParse(await hermesResult.json());
+          return parsed.success
+            ? parsed.data.map((feed) => toAdvancedIndex(feed))
+            : [];
+        },
+      ),
+    );
+
+    return results.flat();
+  } catch (error: unknown) {
+    throw new Error("Failed to fetch Hermes feeds", { cause: error });
+  }
+}
+
+async function getLazerFeeds(): Promise<AdvancedIndex[]> {
+  try {
+    const res = await fetch(
+      "https://history.pyth-lazer.dourolabs.app/history/v1/symbols",
+      { next: { revalidate: 3600 } },
+    );
+    const parsed = lazerSchema.safeParse(await res.json());
+
+    if (!parsed.success) {
+      return [];
+    }
+
+    return parsed.data.map((feed) => ({
+      title: `${feed.name} (Pro)`,
+      description: `${feed.symbol} - ${feed.description} (ID: ${String(feed.pyth_lazer_id)})`,
+      url: `/price-feeds/pro/price-feed-ids?search=${feed.symbol}`,
+      id: `lazer-${String(feed.pyth_lazer_id)}`,
+      tag: "price-feed-pro",
+      structuredData: {
+        headings: [],
+        contents: [
+          { heading: "Symbol", content: feed.symbol },
+          { heading: "Name", content: feed.name },
+          { heading: "Description", content: feed.description },
+          { heading: "ID", content: String(feed.pyth_lazer_id) },
+        ],
+      },
+    }));
+  } catch (error: unknown) {
+    throw new Error("Failed to fetch Lazer feeds", { cause: error });
+  }
+}
+
+export const { GET } = createSearchAPI("advanced", {
+  indexes: async () => {
+    const staticPages = source.getPages().map((page) => ({
+      title: page.data.title,
+      description: page.data.description,
+      url: page.url,
+      id: page.url,
+      structuredData: page.data.structuredData,
+    })) as AdvancedIndex[];
+
+    // Added these two functions to get the price feeds from the Hermes and Pro APIs
+    const [hermesFeeds, lazerFeeds] = await Promise.all([
+      getHermesFeeds(),
+      getLazerFeeds(),
+    ]);
+
+    // Combine the static pages, Hermes feeds, and Pro feeds
+    return [...staticPages, ...hermesFeeds, ...lazerFeeds];
+  },
+});

+ 3 - 3
apps/developer-hub/src/components/Pages/Homepage/index.tsx

@@ -51,21 +51,21 @@ export const Homepage = () => {
             title="Pyth Token"
             description="The native token powering governance and staking across the Pyth Network."
             url="/pyth-token"
-            urlLabel="Link"
+            urlLabel="Read more"
             image={<SignalImage />}
           />
           <SectionCard
             title="Oracle Integrity Staking"
             description="Stake PYTH to support data publishers and secure the integrity of Pyth price feeds."
             url="/oracle-integrity-staking"
-            urlLabel="Link"
+            urlLabel="Read more"
             image={<SignalImage />}
           />
           <SectionCard
             title="Pyth Metrics"
             description="Track network performance, feed activity, and ecosystem growth in real time."
             url="/metrics"
-            urlLabel="Link"
+            urlLabel="Read more"
             image={<SignalImage />}
           />
         </SectionCards>

+ 1 - 1
apps/developer-hub/src/components/PriceFeedIdsProTable/index.tsx

@@ -62,7 +62,7 @@ export const PriceFeedIdsProTable = () => {
         return items;
       }
       return matchSorter(items, searchString, {
-        keys: ["pyth_lazer_id"],
+        keys: ["pyth_lazer_id", "symbol", "name", "description"],
       });
     },
     {