1
- import type { AbsolutePath , Readable } from "@zarrita/storage" ;
1
+ import { FetchStore , type AbsolutePath , type Readable } from "@zarrita/storage" ;
2
2
3
- import { Array , Group , Location } from "./hierarchy.js" ;
3
+ import { Array , Group } from "./hierarchy.js" ;
4
4
import {
5
5
json_decode_object ,
6
+ json_encode_object ,
6
7
v2_to_v3_array_metadata ,
7
8
v2_to_v3_group_metadata ,
8
9
} from "./util.js" ;
9
- import type { ArrayMetadataV2 , DataType , GroupMetadataV2 } from "./metadata.js" ;
10
- import { NodeNotFoundError } from "./errors.js" ;
10
+ import type {
11
+ ArrayMetadata ,
12
+ ArrayMetadataV2 ,
13
+ GroupMetadata ,
14
+ GroupMetadataV2 ,
15
+ Attributes ,
16
+ } from "./metadata.js" ;
11
17
12
18
type ConsolidatedMetadata = {
13
- metadata : Record < string , any > ;
19
+ metadata : Record < string , ArrayMetadataV2 | GroupMetadataV2 > ;
14
20
zarr_consolidated_format : 1 ;
15
21
} ;
16
22
23
+ type Listable < Store extends Readable > = {
24
+ get ( ...args : Parameters < Store [ "get" ] > ) : Promise < Uint8Array | undefined > ;
25
+ contents ( ) : { path : AbsolutePath ; kind : "array" | "group" } [ ] ;
26
+ } ;
27
+
17
28
async function get_consolidated_metadata (
18
29
store : Readable ,
19
30
) : Promise < ConsolidatedMetadata > {
@@ -26,13 +37,72 @@ async function get_consolidated_metadata(
26
37
return meta ;
27
38
}
28
39
29
- /** Proxies requests to the underlying store. */
30
- export async function openConsolidated < Store extends Readable > (
40
+ type Metadata =
41
+ | ArrayMetadataV2
42
+ | GroupMetadataV2
43
+ | ArrayMetadata
44
+ | GroupMetadata
45
+ | Attributes ;
46
+
47
+ function is_meta_key ( key : string ) : boolean {
48
+ return (
49
+ key . endsWith ( ".zarray" ) ||
50
+ key . endsWith ( ".zgroup" ) ||
51
+ key . endsWith ( ".zattrs" ) ||
52
+ key . endsWith ( "zarr.json" )
53
+ ) ;
54
+ }
55
+
56
+ function is_v3 ( meta : Metadata ) : meta is ArrayMetadata | GroupMetadata {
57
+ return "zarr_format" in meta && meta . zarr_format === 3 ;
58
+ }
59
+
60
+ async function withConsolidated < Store extends Readable > (
31
61
store : Store ,
32
- ) {
33
- let { metadata } = await get_consolidated_metadata ( store ) ;
34
- let meta_nodes = Object
35
- . entries ( metadata )
62
+ ) : Promise < Listable < Store > > {
63
+ let known_meta : Record < AbsolutePath , Metadata > =
64
+ await get_consolidated_metadata ( store )
65
+ . then ( ( meta ) => {
66
+ let new_meta : Record < AbsolutePath , Metadata > = { } ;
67
+ for ( let [ key , value ] of Object . entries ( meta . metadata ) ) {
68
+ new_meta [ `/${ key } ` ] = value ;
69
+ }
70
+ return new_meta ;
71
+ } )
72
+ . catch ( ( ) => ( { } ) ) ;
73
+
74
+ return {
75
+ async get ( ...args : Parameters < Store [ "get" ] > ) : Promise < Uint8Array | undefined > {
76
+ let [ key , opts ] = args ;
77
+ if ( known_meta [ key ] ) {
78
+ return json_encode_object ( known_meta [ key ] ) ;
79
+ }
80
+ let maybe_bytes = await store . get ( key , opts ) ;
81
+ if ( is_meta_key ( key ) && maybe_bytes ) {
82
+ let meta = json_decode_object ( maybe_bytes ) ;
83
+ known_meta [ key ] = meta ;
84
+ }
85
+ return maybe_bytes ;
86
+ } ,
87
+ contents ( ) : { path : AbsolutePath ; kind : "array" | "group" } [ ] {
88
+ let contents : { path : AbsolutePath , kind : "array" | "group" } [ ] = [ ] ;
89
+ for ( let [ key , value ] of Object . entries ( known_meta ) ) {
90
+ let path = key as AbsolutePath ;
91
+ if ( key . endsWith ( ".zarray" ) ) contents . push ( { path, kind : "array" } ) ;
92
+ if ( key . endsWith ( ".zgroup" ) ) contents . push ( { path, kind : "group" } ) ;
93
+ if ( is_v3 ( value ) ) contents . push ( { path, kind : value . node_type } ) ;
94
+ }
95
+ return contents ;
96
+ }
97
+ } ;
98
+ }
99
+
100
+ async function openListable < Store extends Readable > ( store : Listable < Store > ) {
101
+ let metadata = await Promise . all (
102
+ store . contents ( ) . map ( ( { path } ) => [ path , store . get ( path ) ] as const )
103
+ ) ;
104
+
105
+ metadata
36
106
. reduce (
37
107
( acc , [ path , content ] ) => {
38
108
let parts = path . split ( "/" ) ;
@@ -56,47 +126,6 @@ export async function openConsolidated<Store extends Readable>(
56
126
}
57
127
> ,
58
128
) ;
59
- let nodes = new Map < AbsolutePath , Array < DataType , Store > | Group < Store > > ( ) ;
60
- for ( let [ path , { meta, attrs } ] of Object . entries ( meta_nodes ) ) {
61
- if ( ! meta ) throw new Error ( "missing metadata" ) ;
62
- let node : Array < DataType , Store > | Group < Store > ;
63
- if ( "shape" in meta ) {
64
- let metadata = v2_to_v3_array_metadata ( meta , attrs ) ;
65
- node = new Array ( store , path as AbsolutePath , metadata ) ;
66
- } else {
67
- let metadata = v2_to_v3_group_metadata ( meta , attrs ) ;
68
- node = new Group ( store , path as AbsolutePath , metadata ) ;
69
- }
70
- nodes . set ( path as AbsolutePath , node ) ;
71
- }
72
- return new ConsolidatedHierarchy ( nodes ) ;
73
- }
74
129
75
- class ConsolidatedHierarchy < Store extends Readable > {
76
- constructor (
77
- public contents : Map < AbsolutePath , Array < DataType , Store > | Group < Store > > ,
78
- ) { }
79
- open (
80
- where : AbsolutePath | Location < unknown > ,
81
- options : { kind : "group" } ,
82
- ) : Group < Store > ;
83
- open (
84
- where : AbsolutePath | Location < unknown > ,
85
- options : { kind : "array" } ,
86
- ) : Array < DataType , Store > ;
87
- open (
88
- where : AbsolutePath | Location < unknown > ,
89
- ) : Array < DataType , Store > | Group < Store > ;
90
- open (
91
- where : AbsolutePath | Location < unknown > ,
92
- options : { kind ?: "array" | "group" } = { } ,
93
- ) {
94
- let path = typeof where === "string" ? where : where . path ;
95
- let node = this . contents . get ( path ) ;
96
- if ( node && ( ! options . kind || options . kind == node . kind ) ) return node ;
97
- throw new NodeNotFoundError ( path ) ;
98
- }
99
- root ( ) {
100
- return this . open ( "/" , { kind : "group" } ) ;
101
- }
130
+
102
131
}
0 commit comments