11import { Hono } from "hono" ;
22import type { Fetcher } from "@cloudflare/workers-types" ;
3- import type { Model } from "./schemas" ;
3+ import type { ApiData } from "./schemas" ;
44
55interface Env {
66 ASSETS : Fetcher ;
77}
88
9- // Define the API data structure
10- interface ApiData {
11- [ providerId : string ] : {
12- name : string ;
13- models : {
14- [ modelId : string ] : Model ;
15- } ;
16- } ;
17- }
18-
199// Create a typed Hono app
2010const app = new Hono < { Bindings : Env } > ( ) ;
2111
@@ -37,14 +27,61 @@ app.get("/", async (c) => {
3727 < html >
3828 < head >
3929 < title > API Data</ title >
30+ < script
31+ dangerouslySetInnerHTML = { {
32+ __html : `
33+ function filterTable() {
34+ const searchInput = document.getElementById('searchInput').value.toLowerCase();
35+ const rows = document.querySelectorAll('table tbody tr');
36+
37+ rows.forEach(row => {
38+ const provider = row.cells[0].textContent.toLowerCase();
39+ const providerId = row.cells[1].textContent.toLowerCase();
40+ const model = row.cells[2].textContent.toLowerCase();
41+ const modelId = row.cells[3].textContent.toLowerCase();
42+
43+ if (provider.includes(searchInput) || model.includes(searchInput) || providerId.includes(searchInput) || modelId.includes(searchInput)) {
44+ row.style.display = '';
45+ } else {
46+ row.style.display = 'none';
47+ }
48+ });
49+ }
50+ ` ,
51+ } }
52+ />
53+ < style
54+ dangerouslySetInnerHTML = { {
55+ __html : `
56+ .search-container {
57+ margin-bottom: 20px;
58+ }
59+ #searchInput {
60+ padding: 8px;
61+ width: 300px;
62+ font-size: 16px;
63+ }
64+ ` ,
65+ } }
66+ />
4067 </ head >
4168 < body >
4269 < h1 > API Data</ h1 >
70+ < div class = "search-container" >
71+ < input
72+ type = "text"
73+ id = "searchInput"
74+ placeholder = "Search by provider or model..."
75+ onkeyup = "filterTable()"
76+ />
77+ </ div >
4378 < table border = "1" cellpadding = "5" cellspacing = "0" >
4479 < thead >
4580 < tr >
4681 < th > Provider</ th >
82+ < th > Provider ID</ th >
4783 < th > Model</ th >
84+ < th > Model ID</ th >
4885 < th > Attachment</ th >
4986 < th > Reasoning</ th >
5087 < th > Input Cost</ th >
@@ -56,22 +93,32 @@ app.get("/", async (c) => {
5693 </ tr >
5794 </ thead >
5895 < tbody >
59- { Object . entries ( apiData ) . map ( ( [ providerId , provider ] ) =>
60- Object . entries ( provider . models ) . map ( ( [ modelId , model ] ) => (
61- < tr key = { `${ providerId } -${ modelId } ` } >
62- < td > { provider . name } </ td >
63- < td > { model . name } </ td >
64- < td > { model . attachment ? "Yes" : "No" } </ td >
65- < td > { model . reasoning ? "Yes" : "No" } </ td >
66- < td > ${ model . cost . input } </ td >
67- < td > ${ model . cost . output } </ td >
68- < td > ${ model . cost . inputCached } </ td >
69- < td > ${ model . cost . outputCached } </ td >
70- < td > { model . limit . context } </ td >
71- < td > { model . limit . output } </ td >
72- </ tr >
73- ) )
74- ) }
96+ { Object . entries ( apiData )
97+ . sort ( ( [ , providerA ] , [ , providerB ] ) =>
98+ providerA . name . localeCompare ( providerB . name )
99+ )
100+ . flatMap ( ( [ providerId , provider ] ) =>
101+ Object . entries ( provider . models )
102+ . sort ( ( [ , modelA ] , [ , modelB ] ) =>
103+ modelA . name . localeCompare ( modelB . name )
104+ )
105+ . map ( ( [ modelId , model ] ) => (
106+ < tr key = { `${ providerId } -${ modelId } ` } >
107+ < td > { provider . name } </ td >
108+ < td > { providerId } </ td >
109+ < td > { model . name } </ td >
110+ < td > { modelId } </ td >
111+ < td > { model . attachment ? "Yes" : "No" } </ td >
112+ < td > { model . reasoning ? "Yes" : "No" } </ td >
113+ < td > ${ model . cost . input } </ td >
114+ < td > ${ model . cost . output } </ td >
115+ < td > ${ model . cost . inputCached } </ td >
116+ < td > ${ model . cost . outputCached } </ td >
117+ < td > { model . limit . context } </ td >
118+ < td > { model . limit . output } </ td >
119+ </ tr >
120+ ) )
121+ ) }
75122 </ tbody >
76123 </ table >
77124 </ body >
0 commit comments