Commit
·
cecb963
1
Parent(s):
31f50b7
Add index details endpoints and implement data sorting for packages and programs
Browse files- .gitignore +1 -0
- database +1 -0
- src/index.ts +118 -15
.gitignore
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
node_modules/
|
database
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
Subproject commit 456e6be6aacfcec190bee6c48758d7fc9dacb536
|
src/index.ts
CHANGED
@@ -2,6 +2,20 @@ import { serve } from "bun";
|
|
2 |
import packages from "../database/database/packages.json";
|
3 |
import programs from "../database/database/programs.json";
|
4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
serve({
|
6 |
port: 7860,
|
7 |
fetch(req) {
|
@@ -85,25 +99,114 @@ serve({
|
|
85 |
}
|
86 |
|
87 |
if (pathname === "/api/infiniteScrollPrograms") {
|
88 |
-
|
89 |
-
|
90 |
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
|
98 |
-
|
99 |
-
|
100 |
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
106 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
107 |
|
108 |
return new Response("Not Found", {
|
109 |
status: 404,
|
|
|
2 |
import packages from "../database/database/packages.json";
|
3 |
import programs from "../database/database/programs.json";
|
4 |
|
5 |
+
// Pre-sort data for indexDetails endpoints
|
6 |
+
const packagesLatestRepos = [...packages].sort(
|
7 |
+
(a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
|
8 |
+
);
|
9 |
+
const packagesMostUsed = [...packages].sort(
|
10 |
+
(a, b) => (b.usage_count || 0) - (a.usage_count || 0)
|
11 |
+
);
|
12 |
+
const programsLatestRepos = [...programs].sort(
|
13 |
+
(a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
|
14 |
+
);
|
15 |
+
const programsMostUsed = [...programs].sort(
|
16 |
+
(a, b) => (b.usage_count || 0) - (a.usage_count || 0)
|
17 |
+
);
|
18 |
+
|
19 |
serve({
|
20 |
port: 7860,
|
21 |
fetch(req) {
|
|
|
99 |
}
|
100 |
|
101 |
if (pathname === "/api/infiniteScrollPrograms") {
|
102 |
+
const pageNumberParam = url.searchParams.get("pageNumber");
|
103 |
+
const pageNumber = parseInt(pageNumberParam || "0", 10);
|
104 |
|
105 |
+
if (isNaN(pageNumber) || pageNumber < 0) {
|
106 |
+
return new Response(JSON.stringify({ error: "Invalid page number" }), {
|
107 |
+
status: 400,
|
108 |
+
headers: corsHeaders,
|
109 |
+
});
|
110 |
+
}
|
111 |
|
112 |
+
const lowerLimit = pageNumber * 10;
|
113 |
+
const scrollResults = programs.slice(lowerLimit, lowerLimit + 10);
|
114 |
|
115 |
+
return new Response(JSON.stringify(scrollResults), {
|
116 |
+
status: 200,
|
117 |
+
headers: corsHeaders,
|
118 |
+
});
|
119 |
+
}
|
120 |
+
|
121 |
+
// New: Get program by owner and repo name
|
122 |
+
const programMatch = pathname.match(/^\/api\/programs\/([^\/]+)\/([^\/]+)$/);
|
123 |
+
if (programMatch) {
|
124 |
+
const [, owner, repo] = programMatch;
|
125 |
+
const program = programs.find(
|
126 |
+
(p) =>
|
127 |
+
p.owner?.toLowerCase() === owner.toLowerCase() &&
|
128 |
+
p.name?.toLowerCase() === repo.toLowerCase()
|
129 |
+
);
|
130 |
+
if (program) {
|
131 |
+
return new Response(JSON.stringify(program), {
|
132 |
+
status: 200,
|
133 |
+
headers: corsHeaders,
|
134 |
+
});
|
135 |
+
}
|
136 |
+
return new Response(JSON.stringify({ error: "Program not found" }), {
|
137 |
+
status: 404,
|
138 |
+
headers: corsHeaders,
|
139 |
+
});
|
140 |
+
}
|
141 |
|
142 |
+
// New: Get package by owner and repo name
|
143 |
+
const packageMatch = pathname.match(/^\/api\/packages\/([^\/]+)\/([^\/]+)$/);
|
144 |
+
if (packageMatch) {
|
145 |
+
const [, owner, repo] = packageMatch;
|
146 |
+
const pkg = packages.find(
|
147 |
+
(p) =>
|
148 |
+
p.owner?.toLowerCase() === owner.toLowerCase() &&
|
149 |
+
p.name?.toLowerCase() === repo.toLowerCase()
|
150 |
+
);
|
151 |
+
if (pkg) {
|
152 |
+
return new Response(JSON.stringify(pkg), {
|
153 |
+
status: 200,
|
154 |
+
headers: corsHeaders,
|
155 |
+
});
|
156 |
+
}
|
157 |
+
return new Response(JSON.stringify({ error: "Package not found" }), {
|
158 |
+
status: 404,
|
159 |
+
headers: corsHeaders,
|
160 |
+
});
|
161 |
+
}
|
162 |
+
|
163 |
+
// Helper to parse range string like "0..100"
|
164 |
+
function parseRange(rangeStr: string | null, max: number) {
|
165 |
+
if (!rangeStr) return [0, Math.min(10, max)];
|
166 |
+
const match = rangeStr.match(/^(\d+)\.\.(\d+)$/);
|
167 |
+
if (!match) return [0, Math.min(10, max)];
|
168 |
+
const start = Math.max(0, parseInt(match[1], 10));
|
169 |
+
const end = Math.min(max, parseInt(match[2], 10));
|
170 |
+
return [start, end];
|
171 |
+
}
|
172 |
+
|
173 |
+
// /api/indexDetailsPackages
|
174 |
+
if (pathname === "/api/indexDetailsPackages") {
|
175 |
+
const section = url.searchParams.get("section");
|
176 |
+
const rangeStr = url.searchParams.get("range");
|
177 |
+
let data = packages;
|
178 |
+
|
179 |
+
if (section === "latestRepos") {
|
180 |
+
data = packagesLatestRepos;
|
181 |
+
} else if (section === "mostUsed") {
|
182 |
+
data = packagesMostUsed;
|
183 |
+
}
|
184 |
+
|
185 |
+
const [start, end] = parseRange(rangeStr, data.length);
|
186 |
+
return new Response(JSON.stringify(data.slice(start, end)), {
|
187 |
+
status: 200,
|
188 |
+
headers: corsHeaders,
|
189 |
+
});
|
190 |
+
}
|
191 |
+
|
192 |
+
// /api/indexDetailsPrograms
|
193 |
+
if (pathname === "/api/indexDetailsPrograms") {
|
194 |
+
const section = url.searchParams.get("section");
|
195 |
+
const rangeStr = url.searchParams.get("range");
|
196 |
+
let data = programs;
|
197 |
+
|
198 |
+
if (section === "latestRepos") {
|
199 |
+
data = programsLatestRepos;
|
200 |
+
} else if (section === "mostUsed") {
|
201 |
+
data = programsMostUsed;
|
202 |
+
}
|
203 |
+
|
204 |
+
const [start, end] = parseRange(rangeStr, data.length);
|
205 |
+
return new Response(JSON.stringify(data.slice(start, end)), {
|
206 |
+
status: 200,
|
207 |
+
headers: corsHeaders,
|
208 |
+
});
|
209 |
+
}
|
210 |
|
211 |
return new Response("Not Found", {
|
212 |
status: 404,
|