77import { useCallback , useEffect , useMemo , useState } from "react" ;
88import {
99 workersKvNamespaceDeleteKeyValuePair ,
10- workersKvNamespaceGetMultipleKeyValuePairs ,
1110 workersKvNamespaceListANamespace_SKeys ,
1211 workersKvNamespaceReadKeyValuePair ,
1312 workersKvNamespaceWriteKeyValuePairWithMetadata ,
@@ -19,7 +18,7 @@ import { KVTable } from "../../components/KVTable";
1918import { ResourceError } from "../../components/ResourceError" ;
2019import { SearchForm } from "../../components/SearchForm" ;
2120import { getSelectedWorker } from "../../components/WorkerSelector" ;
22- import type { KVEntry } from "../../api" ;
21+ import type { KVEntry , WorkersKvKey } from "../../api" ;
2322
2423export const Route = createFileRoute ( "/kv/$namespaceId" ) ( {
2524 component : NamespaceView ,
@@ -31,27 +30,16 @@ export const Route = createFileRoute("/kv/$namespaceId")({
3130 } ) ;
3231 const keys = keysResponse . data ?. result ?? [ ] ;
3332
34- let values : Record < string , string | null > = { } ;
33+ let values = new Map < WorkersKvKey , string | null > ( ) ;
3534 if ( keys . length > 0 ) {
36- const valuesResponse = await workersKvNamespaceGetMultipleKeyValuePairs ( {
37- path : {
38- namespace_id : params . namespaceId ,
39- } ,
40- body : {
41- keys : keys . map ( ( k ) => k . name ) ,
42- } ,
43- } ) ;
44- values = ( valuesResponse . data ?. result ?. values ?? { } ) as Record <
45- string ,
46- string | null
47- > ;
35+ values = await readKVValues ( params . namespaceId , keys ) ;
4836 }
4937
5038 const cursor = keysResponse . data ?. result_info ?. cursor ?? null ;
5139 const entries = keys . map (
5240 ( key ) : KVEntry => ( {
5341 key,
54- value : values [ key . name ] ?? null ,
42+ value : values . get ( key ) ?? null ,
5543 } )
5644 ) ;
5745
@@ -87,6 +75,49 @@ const entryVisible = (entries: KVEntry[], key: string): boolean =>
8775
8876const rootRoute = getRouteApi ( "__root__" ) ;
8977
78+ function isKeyNotFoundError ( error : unknown ) : boolean {
79+ if ( typeof error !== "object" || error === null || ! ( "errors" in error ) ) {
80+ return false ;
81+ }
82+
83+ const { errors } = error as {
84+ errors ?: Array < {
85+ code ?: number ;
86+ } > ;
87+ } ;
88+
89+ return errors ?. some ( ( entry ) => entry . code === 10009 ) ?? false ;
90+ }
91+
92+ async function readKVValues (
93+ namespaceId : string ,
94+ keys : WorkersKvKey [ ]
95+ ) : Promise < Map < WorkersKvKey , string | null > > {
96+ const data = new Map < WorkersKvKey , string | null > ( ) ;
97+
98+ await Promise . all (
99+ keys . map ( async ( key ) => {
100+ try {
101+ const response = await workersKvNamespaceReadKeyValuePair ( {
102+ path : { namespace_id : namespaceId , key_name : key . name } ,
103+ parseAs : "text" ,
104+ } ) ;
105+
106+ data . set ( key , response . data ?? null ) ;
107+ } catch ( error ) {
108+ if ( isKeyNotFoundError ( error ) ) {
109+ data . set ( key , null ) ;
110+ return ;
111+ }
112+
113+ throw error ;
114+ }
115+ } )
116+ ) ;
117+
118+ return data ;
119+ }
120+
90121function NamespaceView ( ) {
91122 const { namespaceId } = Route . useParams ( ) ;
92123 const loaderData = Route . useLoaderData ( ) ;
@@ -158,22 +189,14 @@ function NamespaceView() {
158189 } ) ;
159190 const keys = keysResponse . data ?. result ?? [ ] ;
160191
161- let values : Record < string , string | null > = { } ;
192+ let values = new Map < WorkersKvKey , string | null > ( ) ;
162193 if ( keys . length > 0 ) {
163- const valuesResponse =
164- await workersKvNamespaceGetMultipleKeyValuePairs ( {
165- path : { namespace_id : namespaceId } ,
166- body : { keys : keys . map ( ( k ) => k . name ) } ,
167- } ) ;
168- values = ( valuesResponse . data ?. result ?. values ?? { } ) as Record <
169- string ,
170- string | null
171- > ;
194+ values = await readKVValues ( namespaceId , keys ) ;
172195 }
173196
174197 const newEntries : KVEntry [ ] = keys . map ( ( key ) => ( {
175198 key,
176- value : values [ key . name ] ?? null ,
199+ value : values . get ( key ) ?? null ,
177200 } ) ) ;
178201
179202 if ( nextCursor ) {
0 commit comments