refactor: extract setMeta helper for PaginatedResponseArray
This commit is contained in:
@ -52,10 +52,7 @@ const makePaginatedResponseQueryOptions =
|
||||
data.pages.flatMap((page) =>
|
||||
Array.isArray(page.items) ? page.items : [page.items],
|
||||
),
|
||||
);
|
||||
|
||||
Object.defineProperty(items, 'total', { value: lastPage.total, writable: true, enumerable: false, configurable: true });
|
||||
Object.defineProperty(items, 'partial', { value: lastPage.partial, writable: true, enumerable: false, configurable: true });
|
||||
).setMeta(lastPage.total, lastPage.partial);
|
||||
|
||||
return items as T3;
|
||||
}
|
||||
|
||||
@ -21,6 +21,13 @@ class PaginatedResponseArray<T> extends Array<T> {
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
/** Set metadata as non-enumerable to preserve TanStack Query structural sharing. */
|
||||
setMeta(total: number | undefined, partial: boolean | undefined): this {
|
||||
Object.defineProperty(this, 'total', { value: total, writable: true, enumerable: false, configurable: true });
|
||||
Object.defineProperty(this, 'partial', { value: partial, writable: true, enumerable: false, configurable: true });
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
type PaginatedResponseQueryResult<T, IsArray extends boolean> = IsArray extends true
|
||||
@ -71,10 +78,7 @@ const makePaginatedResponseQuery =
|
||||
data.pages.flatMap((page) =>
|
||||
Array.isArray(page.items) ? page.items : [page.items],
|
||||
),
|
||||
);
|
||||
|
||||
Object.defineProperty(items, 'total', { value: lastPage.total, writable: true, enumerable: false, configurable: true });
|
||||
Object.defineProperty(items, 'partial', { value: lastPage.partial, writable: true, enumerable: false, configurable: true });
|
||||
).setMeta(lastPage.total, lastPage.partial);
|
||||
|
||||
return items as T3;
|
||||
}
|
||||
|
||||
@ -24,26 +24,21 @@ describe('PaginatedResponseArray', () => {
|
||||
expect(items.length).toBe(100_000);
|
||||
});
|
||||
|
||||
it('supports non-enumerable total and partial properties', () => {
|
||||
const items = PaginatedResponseArray.from(['a', 'b', 'c']);
|
||||
Object.defineProperty(items, 'total', { value: 42, writable: true, enumerable: false, configurable: true });
|
||||
Object.defineProperty(items, 'partial', { value: true, writable: true, enumerable: false, configurable: true });
|
||||
it('supports non-enumerable total and partial properties via setMeta', () => {
|
||||
const items = PaginatedResponseArray.from(['a', 'b', 'c']).setMeta(42, true);
|
||||
|
||||
expect(items.total).toBe(42);
|
||||
expect(items.partial).toBe(true);
|
||||
});
|
||||
|
||||
it('passes isPlainArray check with non-enumerable properties for structural sharing', () => {
|
||||
const items = PaginatedResponseArray.from([1, 2, 3]);
|
||||
Object.defineProperty(items, 'total', { value: 10, writable: true, enumerable: false, configurable: true });
|
||||
Object.defineProperty(items, 'partial', { value: false, writable: true, enumerable: false, configurable: true });
|
||||
const items = PaginatedResponseArray.from([1, 2, 3]).setMeta(10, false);
|
||||
|
||||
expect(isPlainArray(items)).toBe(true);
|
||||
});
|
||||
|
||||
it('total and partial properties are writable', () => {
|
||||
const items = PaginatedResponseArray.from([1]);
|
||||
Object.defineProperty(items, 'total', { value: 5, writable: true, enumerable: false, configurable: true });
|
||||
it('total and partial properties are writable after setMeta', () => {
|
||||
const items = PaginatedResponseArray.from([1]).setMeta(5, false);
|
||||
|
||||
items.total = 10;
|
||||
expect(items.total).toBe(10);
|
||||
|
||||
Reference in New Issue
Block a user