Skip to content

Commit 882b8f4

Browse files
committed
Prettify middleware result types
The middleware result type was an opaque intersection chain like `FetchStore & { contents: ... } & { stats: ... }` which was hard to read in tooltips and error messages. This collapses the store's `get`/`getRange` back into `AsyncReadable<O>` and shows only the middleware extensions separately, so the result reads as `AsyncReadable<RequestInit> & { contents: ..., stats: ... }`. If the store or any middleware provides a concrete `getRange`, the collapsed type uses `Required<AsyncReadable<O>>` to preserve the non-optional guarantee. A store that only has `get` shows the default `AsyncReadable<O>` with `getRange?` optional.
1 parent 962409f commit 882b8f4

File tree

3 files changed

+38
-9
lines changed

3 files changed

+38
-9
lines changed

packages/zarrita/__tests__/middleware-types.test.ts

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ describe("storeFrom", () => {
2323
);
2424
expectType(store).toMatchInlineSnapshot(`
2525
Promise<
26-
zarr.FetchStore & { stats: Readonly<zarr.RangeBatchingStats> }
26+
Required<AsyncReadable<RequestInit>> & {
27+
stats: Readonly<zarr.RangeBatchingStats>;
28+
url: string | URL;
29+
}
2730
>
2831
`);
2932
});
@@ -38,9 +41,11 @@ describe("storeFrom", () => {
3841
}
3942
expectType(check).toMatchInlineSnapshot(`
4043
() => Promise<
41-
zarr.FetchStore & {
44+
Required<AsyncReadable<RequestInit>> & {
45+
stats: Readonly<zarr.RangeBatchingStats>;
46+
url: string | URL;
4247
contents: () => { path: AbsolutePath; kind: "array" | "group" }[];
43-
} & { stats: Readonly<zarr.RangeBatchingStats> }
48+
}
4449
>
4550
`);
4651
});
@@ -62,7 +67,12 @@ describe("defineStoreMiddleware", () => {
6267
);
6368
let store = withCustom(new zarr.FetchStore(""), { flag: true });
6469
expectType(store).toMatchInlineSnapshot(
65-
`zarr.FetchStore & { hello: () => string }`,
70+
`
71+
Required<AsyncReadable<RequestInit>> & {
72+
url: string | URL;
73+
hello: () => string;
74+
}
75+
`,
6676
);
6777
});
6878

@@ -88,7 +98,12 @@ describe("defineStoreMiddleware", () => {
8898
retries: 5,
8999
});
90100
expectType(store).toMatchInlineSnapshot(
91-
`zarr.FetchStore & { retries: number }`,
101+
`
102+
Required<AsyncReadable<RequestInit>> & {
103+
url: string | URL;
104+
retries: number;
105+
}
106+
`,
92107
);
93108
});
94109

@@ -119,8 +134,10 @@ describe("defineStoreMiddleware", () => {
119134
);
120135
let store = withB(withA(new zarr.FetchStore(""), { a: 1 }), { b: "x" });
121136
expectType(store).toMatchInlineSnapshot(`
122-
zarr.FetchStore & { methodA: () => number } & {
137+
Required<AsyncReadable<RequestInit>> & {
138+
url: string | URL;
123139
methodB: () => string;
140+
methodA: () => number;
124141
}
125142
`);
126143
});

packages/zarrita/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// re-export all the storage interface types
22
export type * from "@zarrita/storage";
33
// re-export fetch store from storage
4-
export { default as FetchStore } from "@zarrita/storage/fetch";
4+
export { FetchStore, FileSystemStore } from "@zarrita/storage";
55
// core
66
export { registry } from "./codecs.js";
77
export { create } from "./create.js";

packages/zarrita/src/middleware/define.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,22 @@ type InferStoreOpts<S> = S extends { get(key: any, opts?: infer O): any }
3333
: unknown;
3434

3535
/** If factory returns a Promise, wrap the result in Promise; otherwise keep it sync. */
36+
type Prettify<T> = { [K in keyof T]: T[K] } & {};
37+
38+
/** Collapse get/getRange into AsyncReadable<O>, show extras separately. */
39+
type CollapseStore<T> =
40+
T extends AsyncReadable<infer O>
41+
? // biome-ignore lint/suspicious/noExplicitAny: needed for getRange optionality check
42+
(T extends { getRange: (...args: any[]) => any }
43+
? Required<AsyncReadable<O>>
44+
: AsyncReadable<O>) &
45+
Prettify<Omit<T, keyof AsyncReadable>>
46+
: T;
47+
3648
type WrapperResult<Ext, S> =
3749
Ext extends Promise<infer Inner>
38-
? Promise<S & Extensions<Inner>>
39-
: S & Extensions<Ext>;
50+
? Promise<CollapseStore<S & Extensions<Inner>>>
51+
: CollapseStore<S & Extensions<Ext>>;
4052

4153
function createProxy(
4254
store: object,

0 commit comments

Comments
 (0)