@stackframe/stack-shared 2.8.36 → 2.8.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/dist/config/schema.d.mts +91 -15
- package/dist/config/schema.d.ts +91 -15
- package/dist/config/schema.js +24 -4
- package/dist/config/schema.js.map +1 -1
- package/dist/esm/config/schema.js +24 -4
- package/dist/esm/config/schema.js.map +1 -1
- package/dist/esm/helpers/vault/server-side.js +5 -1
- package/dist/esm/helpers/vault/server-side.js.map +1 -1
- package/dist/esm/interface/admin-interface.js +53 -2
- package/dist/esm/interface/admin-interface.js.map +1 -1
- package/dist/esm/interface/client-interface.js +29 -26
- package/dist/esm/interface/client-interface.js.map +1 -1
- package/dist/esm/interface/crud/oauth-providers.js +2 -0
- package/dist/esm/interface/crud/oauth-providers.js.map +1 -1
- package/dist/esm/interface/crud/transactions.js +21 -0
- package/dist/esm/interface/crud/transactions.js.map +1 -0
- package/dist/esm/interface/server-interface.js +5 -7
- package/dist/esm/interface/server-interface.js.map +1 -1
- package/dist/esm/known-errors.js +21 -1
- package/dist/esm/known-errors.js.map +1 -1
- package/dist/esm/schema-fields.js +23 -4
- package/dist/esm/schema-fields.js.map +1 -1
- package/dist/esm/sessions.js +19 -9
- package/dist/esm/sessions.js.map +1 -1
- package/dist/esm/utils/arrays.js +25 -0
- package/dist/esm/utils/arrays.js.map +1 -1
- package/dist/esm/utils/esbuild.js +63 -6
- package/dist/esm/utils/esbuild.js.map +1 -1
- package/dist/esm/utils/jwt.js +16 -1
- package/dist/esm/utils/jwt.js.map +1 -1
- package/dist/esm/utils/numbers.js +14 -9
- package/dist/esm/utils/numbers.js.map +1 -1
- package/dist/esm/utils/paginated-lists.js +230 -0
- package/dist/esm/utils/paginated-lists.js.map +1 -0
- package/dist/esm/utils/promises.js +2 -1
- package/dist/esm/utils/promises.js.map +1 -1
- package/dist/esm/utils/types.js.map +1 -1
- package/dist/helpers/password.d.mts +3 -3
- package/dist/helpers/password.d.ts +3 -3
- package/dist/helpers/vault/server-side.js +5 -1
- package/dist/helpers/vault/server-side.js.map +1 -1
- package/dist/index.d.mts +6 -5
- package/dist/index.d.ts +6 -5
- package/dist/interface/admin-interface.d.mts +37 -7
- package/dist/interface/admin-interface.d.ts +37 -7
- package/dist/interface/admin-interface.js +53 -2
- package/dist/interface/admin-interface.js.map +1 -1
- package/dist/interface/client-interface.d.mts +5 -22
- package/dist/interface/client-interface.d.ts +5 -22
- package/dist/interface/client-interface.js +29 -26
- package/dist/interface/client-interface.js.map +1 -1
- package/dist/interface/crud/current-user.d.mts +4 -4
- package/dist/interface/crud/current-user.d.ts +4 -4
- package/dist/interface/crud/oauth-providers.d.mts +12 -4
- package/dist/interface/crud/oauth-providers.d.ts +12 -4
- package/dist/interface/crud/oauth-providers.js +1 -0
- package/dist/interface/crud/oauth-providers.js.map +1 -1
- package/dist/interface/crud/project-api-keys.d.mts +2 -2
- package/dist/interface/crud/project-api-keys.d.ts +2 -2
- package/dist/interface/crud/projects.d.mts +12 -12
- package/dist/interface/crud/projects.d.ts +12 -12
- package/dist/interface/crud/team-member-profiles.d.mts +6 -6
- package/dist/interface/crud/team-member-profiles.d.ts +6 -6
- package/dist/interface/crud/transactions.d.mts +56 -0
- package/dist/interface/crud/transactions.d.ts +56 -0
- package/dist/interface/crud/transactions.js +46 -0
- package/dist/interface/crud/transactions.js.map +1 -0
- package/dist/interface/crud/users.d.mts +6 -6
- package/dist/interface/crud/users.d.ts +6 -6
- package/dist/interface/server-interface.d.mts +8 -44
- package/dist/interface/server-interface.d.ts +8 -44
- package/dist/interface/server-interface.js +5 -7
- package/dist/interface/server-interface.js.map +1 -1
- package/dist/known-errors.d.mts +9 -3
- package/dist/known-errors.d.ts +9 -3
- package/dist/known-errors.js +21 -1
- package/dist/known-errors.js.map +1 -1
- package/dist/schema-fields.d.mts +38 -8
- package/dist/schema-fields.d.ts +38 -8
- package/dist/schema-fields.js +26 -5
- package/dist/schema-fields.js.map +1 -1
- package/dist/sessions.d.mts +26 -4
- package/dist/sessions.d.ts +26 -4
- package/dist/sessions.js +19 -9
- package/dist/sessions.js.map +1 -1
- package/dist/utils/arrays.d.mts +6 -1
- package/dist/utils/arrays.d.ts +6 -1
- package/dist/utils/arrays.js +30 -0
- package/dist/utils/arrays.js.map +1 -1
- package/dist/utils/esbuild.d.mts +1 -0
- package/dist/utils/esbuild.d.ts +1 -0
- package/dist/utils/esbuild.js +63 -6
- package/dist/utils/esbuild.js.map +1 -1
- package/dist/utils/jwt.d.mts +34 -1
- package/dist/utils/jwt.d.ts +34 -1
- package/dist/utils/jwt.js +16 -0
- package/dist/utils/jwt.js.map +1 -1
- package/dist/utils/numbers.js +14 -9
- package/dist/utils/numbers.js.map +1 -1
- package/dist/utils/paginated-lists.d.mts +176 -0
- package/dist/utils/paginated-lists.d.ts +176 -0
- package/dist/utils/paginated-lists.js +256 -0
- package/dist/utils/paginated-lists.js.map +1 -0
- package/dist/utils/promises.d.mts +1 -1
- package/dist/utils/promises.d.ts +1 -1
- package/dist/utils/promises.js +2 -1
- package/dist/utils/promises.js.map +1 -1
- package/dist/utils/stores.d.mts +6 -6
- package/dist/utils/stores.d.ts +6 -6
- package/dist/utils/types.d.mts +10 -1
- package/dist/utils/types.d.ts +10 -1
- package/dist/utils/types.js.map +1 -1
- package/package.json +3 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/numbers.tsx"],"sourcesContent":["const magnitudes = [\n [
|
|
1
|
+
{"version":3,"sources":["../../src/utils/numbers.tsx"],"sourcesContent":["const magnitudes = [\n [1_000, \"k\"],\n [1_000, \"M\"],\n [1_000, \"bn\"],\n [1_000, \"bln\"],\n [1_000, \"trln\"],\n] as const;\n\nexport function prettyPrintWithMagnitudes(num: number): string {\n if (typeof num !== \"number\") throw new Error(\"Expected a number\");\n if (Number.isNaN(num)) return \"NaN\";\n if (num < 0) return \"-\" + prettyPrintWithMagnitudes(-num);\n if (!Number.isFinite(num)) return \"∞\";\n\n let current = toFixedMax(num, 1);\n let lastSuffix = \"\";\n for (const [difference, suffix] of magnitudes) {\n if (+current >= difference) {\n current = toFixedMax(+current / difference, 1);\n lastSuffix = suffix;\n } else {\n break;\n }\n }\n return current + lastSuffix;\n}\nundefined?.test(\"prettyPrintWithMagnitudes\", ({ expect }) => {\n // Test different magnitudes\n expect(prettyPrintWithMagnitudes(999)).toBe(\"999\");\n expect(prettyPrintWithMagnitudes(1000)).toBe(\"1k\");\n expect(prettyPrintWithMagnitudes(1500)).toBe(\"1.5k\");\n expect(prettyPrintWithMagnitudes(999499)).toBe(\"999.5k\");\n expect(prettyPrintWithMagnitudes(999500)).toBe(\"999.5k\");\n expect(prettyPrintWithMagnitudes(999949)).toBe(\"999.9k\");\n expect(prettyPrintWithMagnitudes(999950)).toBe(\"1M\");\n expect(prettyPrintWithMagnitudes(1000000)).toBe(\"1M\");\n expect(prettyPrintWithMagnitudes(1500000)).toBe(\"1.5M\");\n expect(prettyPrintWithMagnitudes(1000000000)).toBe(\"1bn\");\n expect(prettyPrintWithMagnitudes(1500000000)).toBe(\"1.5bn\");\n expect(prettyPrintWithMagnitudes(1000000000000)).toBe(\"1bln\");\n expect(prettyPrintWithMagnitudes(1500000000000)).toBe(\"1.5bln\");\n expect(prettyPrintWithMagnitudes(1000000000000000)).toBe(\"1trln\");\n expect(prettyPrintWithMagnitudes(1500000000000000)).toBe(\"1.5trln\");\n // Test small numbers\n expect(prettyPrintWithMagnitudes(100)).toBe(\"100\");\n expect(prettyPrintWithMagnitudes(0)).toBe(\"0\");\n expect(prettyPrintWithMagnitudes(0.5)).toBe(\"0.5\");\n // Test negative numbers\n expect(prettyPrintWithMagnitudes(-1000)).toBe(\"-1k\");\n expect(prettyPrintWithMagnitudes(-1500000)).toBe(\"-1.5M\");\n // Test special cases\n expect(prettyPrintWithMagnitudes(NaN)).toBe(\"NaN\");\n expect(prettyPrintWithMagnitudes(Infinity)).toBe(\"∞\");\n expect(prettyPrintWithMagnitudes(-Infinity)).toBe(\"-∞\");\n});\n\nexport function toFixedMax(num: number, maxDecimals: number): string {\n return num.toFixed(maxDecimals).replace(/\\.?0+$/, \"\");\n}\nundefined?.test(\"toFixedMax\", ({ expect }) => {\n expect(toFixedMax(1, 2)).toBe(\"1\");\n expect(toFixedMax(1.2, 2)).toBe(\"1.2\");\n expect(toFixedMax(1.23, 2)).toBe(\"1.23\");\n expect(toFixedMax(1.234, 2)).toBe(\"1.23\");\n expect(toFixedMax(1.0, 2)).toBe(\"1\");\n expect(toFixedMax(1.20, 2)).toBe(\"1.2\");\n expect(toFixedMax(0, 2)).toBe(\"0\");\n});\n\nexport function numberCompare(a: number, b: number): number {\n return Math.sign(a - b);\n}\nundefined?.test(\"numberCompare\", ({ expect }) => {\n expect(numberCompare(1, 2)).toBe(-1);\n expect(numberCompare(2, 1)).toBe(1);\n expect(numberCompare(1, 1)).toBe(0);\n expect(numberCompare(0, 0)).toBe(0);\n expect(numberCompare(-1, -2)).toBe(1);\n expect(numberCompare(-2, -1)).toBe(-1);\n expect(numberCompare(-1, 1)).toBe(-1);\n expect(numberCompare(1, -1)).toBe(1);\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAM,aAAa;AAAA,EACjB,CAAC,KAAO,GAAG;AAAA,EACX,CAAC,KAAO,GAAG;AAAA,EACX,CAAC,KAAO,IAAI;AAAA,EACZ,CAAC,KAAO,KAAK;AAAA,EACb,CAAC,KAAO,MAAM;AAChB;AAEO,SAAS,0BAA0B,KAAqB;AAC7D,MAAI,OAAO,QAAQ,SAAU,OAAM,IAAI,MAAM,mBAAmB;AAChE,MAAI,OAAO,MAAM,GAAG,EAAG,QAAO;AAC9B,MAAI,MAAM,EAAG,QAAO,MAAM,0BAA0B,CAAC,GAAG;AACxD,MAAI,CAAC,OAAO,SAAS,GAAG,EAAG,QAAO;AAElC,MAAI,UAAU,WAAW,KAAK,CAAC;AAC/B,MAAI,aAAa;AACjB,aAAW,CAAC,YAAY,MAAM,KAAK,YAAY;AAC7C,QAAI,CAAC,WAAW,YAAY;AAC1B,gBAAU,WAAW,CAAC,UAAU,YAAY,CAAC;AAC7C,mBAAa;AAAA,IACf,OAAO;AACL;AAAA,IACF;AAAA,EACF;AACA,SAAO,UAAU;AACnB;AA+BO,SAAS,WAAW,KAAa,aAA6B;AACnE,SAAO,IAAI,QAAQ,WAAW,EAAE,QAAQ,UAAU,EAAE;AACtD;AAWO,SAAS,cAAc,GAAW,GAAmB;AAC1D,SAAO,KAAK,KAAK,IAAI,CAAC;AACxB;","names":[]}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
type QueryOptions<Type extends 'next' | 'prev', Cursor, Filter, OrderBy> = {
|
|
2
|
+
filter: Filter;
|
|
3
|
+
orderBy: OrderBy;
|
|
4
|
+
limit: number;
|
|
5
|
+
/**
|
|
6
|
+
* Whether the limit should be treated as an exact value, or an approximate value.
|
|
7
|
+
*
|
|
8
|
+
* If set to 'exact', less items will only be returned if the list item is the first or last item.
|
|
9
|
+
*
|
|
10
|
+
* If set to 'at-least' or 'approximate', the implementation may decide to return more items than the limit requested if doing so comes at no (or negligible) extra cost.
|
|
11
|
+
*
|
|
12
|
+
* If set to 'at-most' or 'approximate', the implementation may decide to return less items than the limit requested if requesting more items would come at a non-negligible extra cost. In this case, if limit > 0, the implementation must still make progress towards the end of the list and the returned cursor must be different from the one passed in.
|
|
13
|
+
*
|
|
14
|
+
* Defaults to 'exact'.
|
|
15
|
+
*/
|
|
16
|
+
limitPrecision: 'exact' | 'at-least' | 'at-most' | 'approximate';
|
|
17
|
+
} & ([Type] extends [never] ? unknown : [Type] extends ['next'] ? {
|
|
18
|
+
after: Cursor;
|
|
19
|
+
} : [Type] extends ['prev'] ? {
|
|
20
|
+
before: Cursor;
|
|
21
|
+
} : {
|
|
22
|
+
cursor: Cursor;
|
|
23
|
+
});
|
|
24
|
+
type ImplQueryOptions<Type extends 'next' | 'prev', Cursor, Filter, OrderBy> = QueryOptions<Type, Cursor, Filter, OrderBy> & {
|
|
25
|
+
limitPrecision: 'approximate';
|
|
26
|
+
};
|
|
27
|
+
type QueryResult<Item, Cursor> = {
|
|
28
|
+
items: {
|
|
29
|
+
item: Item;
|
|
30
|
+
itemCursor: Cursor;
|
|
31
|
+
}[];
|
|
32
|
+
isFirst: boolean;
|
|
33
|
+
isLast: boolean;
|
|
34
|
+
cursor: Cursor;
|
|
35
|
+
};
|
|
36
|
+
type ImplQueryResult<Item, Cursor> = {
|
|
37
|
+
items: {
|
|
38
|
+
item: Item;
|
|
39
|
+
itemCursor: Cursor;
|
|
40
|
+
}[];
|
|
41
|
+
isFirst: boolean;
|
|
42
|
+
isLast: boolean;
|
|
43
|
+
cursor: Cursor;
|
|
44
|
+
};
|
|
45
|
+
declare abstract class PaginatedList<Item, Cursor extends string, Filter extends unknown, OrderBy extends unknown> {
|
|
46
|
+
protected abstract _getFirstCursor(): Cursor;
|
|
47
|
+
protected abstract _getLastCursor(): Cursor;
|
|
48
|
+
protected abstract _compare(orderBy: OrderBy, a: Item, b: Item): number;
|
|
49
|
+
protected abstract _nextOrPrev(type: 'next' | 'prev', options: ImplQueryOptions<'next' | 'prev', Cursor, Filter, OrderBy>): Promise<ImplQueryResult<Item, Cursor>>;
|
|
50
|
+
getFirstCursor(): Cursor;
|
|
51
|
+
getLastCursor(): Cursor;
|
|
52
|
+
compare(orderBy: OrderBy, a: Item, b: Item): number;
|
|
53
|
+
nextOrPrev(type: 'next' | 'prev', options: QueryOptions<'next' | 'prev', Cursor, Filter, OrderBy>): Promise<QueryResult<Item, Cursor>>;
|
|
54
|
+
next({ after, ...rest }: QueryOptions<'next', Cursor, Filter, OrderBy>): Promise<QueryResult<Item, Cursor>>;
|
|
55
|
+
prev({ before, ...rest }: QueryOptions<'prev', Cursor, Filter, OrderBy>): Promise<QueryResult<Item, Cursor>>;
|
|
56
|
+
flatMap<Item2, Cursor2 extends string, Filter2 extends unknown, OrderBy2 extends unknown>(options: {
|
|
57
|
+
itemMapper: (itemEntry: {
|
|
58
|
+
item: Item;
|
|
59
|
+
itemCursor: Cursor;
|
|
60
|
+
}, filter: Filter2, orderBy: OrderBy2) => {
|
|
61
|
+
item: Item2;
|
|
62
|
+
itemCursor: Cursor2;
|
|
63
|
+
}[];
|
|
64
|
+
compare: (orderBy: OrderBy2, a: Item2, b: Item2) => number;
|
|
65
|
+
newCursorFromOldCursor: (cursor: Cursor) => Cursor2;
|
|
66
|
+
oldCursorFromNewCursor: (cursor: Cursor2) => Cursor;
|
|
67
|
+
oldFilterFromNewFilter: (filter: Filter2) => Filter;
|
|
68
|
+
oldOrderByFromNewOrderBy: (orderBy: OrderBy2) => OrderBy;
|
|
69
|
+
estimateItemsToFetch: (options: {
|
|
70
|
+
filter: Filter2;
|
|
71
|
+
orderBy: OrderBy2;
|
|
72
|
+
limit: number;
|
|
73
|
+
}) => number;
|
|
74
|
+
}): PaginatedList<Item2, Cursor2, Filter2, OrderBy2>;
|
|
75
|
+
map<Item2, Filter2 extends unknown, OrderBy2 extends unknown>(options: {
|
|
76
|
+
itemMapper: (item: Item) => Item2;
|
|
77
|
+
oldItemFromNewItem: (item: Item2) => Item;
|
|
78
|
+
oldFilterFromNewFilter: (filter: Filter2) => Filter;
|
|
79
|
+
oldOrderByFromNewOrderBy: (orderBy: OrderBy2) => OrderBy;
|
|
80
|
+
}): PaginatedList<Item2, Cursor, Filter2, OrderBy2>;
|
|
81
|
+
filter<Filter2 extends unknown>(options: {
|
|
82
|
+
filter: (item: Item, filter: Filter2) => boolean;
|
|
83
|
+
oldFilterFromNewFilter: (filter: Filter2) => Filter;
|
|
84
|
+
estimateItemsToFetch: (options: {
|
|
85
|
+
filter: Filter2;
|
|
86
|
+
orderBy: OrderBy;
|
|
87
|
+
limit: number;
|
|
88
|
+
}) => number;
|
|
89
|
+
}): PaginatedList<Item, Cursor, Filter2, OrderBy>;
|
|
90
|
+
addFilter<AddedFilter extends unknown>(options: {
|
|
91
|
+
filter: (item: Item, filter: Filter & AddedFilter) => boolean;
|
|
92
|
+
estimateItemsToFetch: (options: {
|
|
93
|
+
filter: Filter & AddedFilter;
|
|
94
|
+
orderBy: OrderBy;
|
|
95
|
+
limit: number;
|
|
96
|
+
}) => number;
|
|
97
|
+
}): PaginatedList<Item, Cursor, Filter & AddedFilter, OrderBy>;
|
|
98
|
+
static merge<Item, Filter extends unknown, OrderBy extends unknown>(...lists: PaginatedList<Item, any, Filter, OrderBy>[]): PaginatedList<Item, string, Filter, OrderBy>;
|
|
99
|
+
static empty(): {
|
|
100
|
+
_getFirstCursor(): "first";
|
|
101
|
+
_getLastCursor(): "last";
|
|
102
|
+
_compare(orderBy: any, a: any, b: any): number;
|
|
103
|
+
_nextOrPrev(type: 'next' | 'prev', options: ImplQueryOptions<'next' | 'prev', string, any, any>): Promise<{
|
|
104
|
+
items: never[];
|
|
105
|
+
isFirst: boolean;
|
|
106
|
+
isLast: boolean;
|
|
107
|
+
cursor: "first";
|
|
108
|
+
}>;
|
|
109
|
+
getFirstCursor(): "first" | "last";
|
|
110
|
+
getLastCursor(): "first" | "last";
|
|
111
|
+
compare(orderBy: any, a: never, b: never): number;
|
|
112
|
+
nextOrPrev(type: "next" | "prev", options: QueryOptions<"next" | "prev", "first" | "last", any, any>): Promise<QueryResult<never, "first" | "last">>;
|
|
113
|
+
next({ after, ...rest }: QueryOptions<"next", "first" | "last", any, any>): Promise<QueryResult<never, "first" | "last">>;
|
|
114
|
+
prev({ before, ...rest }: QueryOptions<"prev", "first" | "last", any, any>): Promise<QueryResult<never, "first" | "last">>;
|
|
115
|
+
flatMap<Item2, Cursor2 extends string, Filter2 extends unknown, OrderBy2 extends unknown>(options: {
|
|
116
|
+
itemMapper: (itemEntry: {
|
|
117
|
+
item: never;
|
|
118
|
+
itemCursor: "first" | "last";
|
|
119
|
+
}, filter: Filter2, orderBy: OrderBy2) => {
|
|
120
|
+
item: Item2;
|
|
121
|
+
itemCursor: Cursor2;
|
|
122
|
+
}[];
|
|
123
|
+
compare: (orderBy: OrderBy2, a: Item2, b: Item2) => number;
|
|
124
|
+
newCursorFromOldCursor: (cursor: "first" | "last") => Cursor2;
|
|
125
|
+
oldCursorFromNewCursor: (cursor: Cursor2) => "first" | "last";
|
|
126
|
+
oldFilterFromNewFilter: (filter: Filter2) => any;
|
|
127
|
+
oldOrderByFromNewOrderBy: (orderBy: OrderBy2) => any;
|
|
128
|
+
estimateItemsToFetch: (options: {
|
|
129
|
+
filter: Filter2;
|
|
130
|
+
orderBy: OrderBy2;
|
|
131
|
+
limit: number;
|
|
132
|
+
}) => number;
|
|
133
|
+
}): PaginatedList<Item2, Cursor2, Filter2, OrderBy2>;
|
|
134
|
+
map<Item2_1, Filter2_1 extends unknown, OrderBy2_1 extends unknown>(options: {
|
|
135
|
+
itemMapper: (item: never) => Item2_1;
|
|
136
|
+
oldItemFromNewItem: (item: Item2_1) => never;
|
|
137
|
+
oldFilterFromNewFilter: (filter: Filter2_1) => any;
|
|
138
|
+
oldOrderByFromNewOrderBy: (orderBy: OrderBy2_1) => any;
|
|
139
|
+
}): PaginatedList<Item2_1, "first" | "last", Filter2_1, OrderBy2_1>;
|
|
140
|
+
filter<Filter2_2 extends unknown>(options: {
|
|
141
|
+
filter: (item: never, filter: Filter2_2) => boolean;
|
|
142
|
+
oldFilterFromNewFilter: (filter: Filter2_2) => any;
|
|
143
|
+
estimateItemsToFetch: (options: {
|
|
144
|
+
filter: Filter2_2;
|
|
145
|
+
orderBy: any;
|
|
146
|
+
limit: number;
|
|
147
|
+
}) => number;
|
|
148
|
+
}): PaginatedList<never, "first" | "last", Filter2_2, any>;
|
|
149
|
+
addFilter<AddedFilter extends unknown>(options: {
|
|
150
|
+
filter: (item: never, filter: any) => boolean;
|
|
151
|
+
estimateItemsToFetch: (options: {
|
|
152
|
+
filter: any;
|
|
153
|
+
orderBy: any;
|
|
154
|
+
limit: number;
|
|
155
|
+
}) => number;
|
|
156
|
+
}): PaginatedList<never, "first" | "last", any, any>;
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
declare class ArrayPaginatedList<Item> extends PaginatedList<Item, `${number}`, (item: Item) => boolean, (a: Item, b: Item) => number> {
|
|
160
|
+
private readonly array;
|
|
161
|
+
constructor(array: Item[]);
|
|
162
|
+
_getFirstCursor(): "0";
|
|
163
|
+
_getLastCursor(): `${number}`;
|
|
164
|
+
_compare(orderBy: (a: Item, b: Item) => number, a: Item, b: Item): number;
|
|
165
|
+
_nextOrPrev(type: 'next' | 'prev', options: ImplQueryOptions<'next' | 'prev', `${number}`, (item: Item) => boolean, (a: Item, b: Item) => number>): Promise<{
|
|
166
|
+
items: {
|
|
167
|
+
item: Item;
|
|
168
|
+
itemCursor: `${number}`;
|
|
169
|
+
}[];
|
|
170
|
+
isFirst: boolean;
|
|
171
|
+
isLast: boolean;
|
|
172
|
+
cursor: `${number}`;
|
|
173
|
+
}>;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export { ArrayPaginatedList, PaginatedList };
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
type QueryOptions<Type extends 'next' | 'prev', Cursor, Filter, OrderBy> = {
|
|
2
|
+
filter: Filter;
|
|
3
|
+
orderBy: OrderBy;
|
|
4
|
+
limit: number;
|
|
5
|
+
/**
|
|
6
|
+
* Whether the limit should be treated as an exact value, or an approximate value.
|
|
7
|
+
*
|
|
8
|
+
* If set to 'exact', less items will only be returned if the list item is the first or last item.
|
|
9
|
+
*
|
|
10
|
+
* If set to 'at-least' or 'approximate', the implementation may decide to return more items than the limit requested if doing so comes at no (or negligible) extra cost.
|
|
11
|
+
*
|
|
12
|
+
* If set to 'at-most' or 'approximate', the implementation may decide to return less items than the limit requested if requesting more items would come at a non-negligible extra cost. In this case, if limit > 0, the implementation must still make progress towards the end of the list and the returned cursor must be different from the one passed in.
|
|
13
|
+
*
|
|
14
|
+
* Defaults to 'exact'.
|
|
15
|
+
*/
|
|
16
|
+
limitPrecision: 'exact' | 'at-least' | 'at-most' | 'approximate';
|
|
17
|
+
} & ([Type] extends [never] ? unknown : [Type] extends ['next'] ? {
|
|
18
|
+
after: Cursor;
|
|
19
|
+
} : [Type] extends ['prev'] ? {
|
|
20
|
+
before: Cursor;
|
|
21
|
+
} : {
|
|
22
|
+
cursor: Cursor;
|
|
23
|
+
});
|
|
24
|
+
type ImplQueryOptions<Type extends 'next' | 'prev', Cursor, Filter, OrderBy> = QueryOptions<Type, Cursor, Filter, OrderBy> & {
|
|
25
|
+
limitPrecision: 'approximate';
|
|
26
|
+
};
|
|
27
|
+
type QueryResult<Item, Cursor> = {
|
|
28
|
+
items: {
|
|
29
|
+
item: Item;
|
|
30
|
+
itemCursor: Cursor;
|
|
31
|
+
}[];
|
|
32
|
+
isFirst: boolean;
|
|
33
|
+
isLast: boolean;
|
|
34
|
+
cursor: Cursor;
|
|
35
|
+
};
|
|
36
|
+
type ImplQueryResult<Item, Cursor> = {
|
|
37
|
+
items: {
|
|
38
|
+
item: Item;
|
|
39
|
+
itemCursor: Cursor;
|
|
40
|
+
}[];
|
|
41
|
+
isFirst: boolean;
|
|
42
|
+
isLast: boolean;
|
|
43
|
+
cursor: Cursor;
|
|
44
|
+
};
|
|
45
|
+
declare abstract class PaginatedList<Item, Cursor extends string, Filter extends unknown, OrderBy extends unknown> {
|
|
46
|
+
protected abstract _getFirstCursor(): Cursor;
|
|
47
|
+
protected abstract _getLastCursor(): Cursor;
|
|
48
|
+
protected abstract _compare(orderBy: OrderBy, a: Item, b: Item): number;
|
|
49
|
+
protected abstract _nextOrPrev(type: 'next' | 'prev', options: ImplQueryOptions<'next' | 'prev', Cursor, Filter, OrderBy>): Promise<ImplQueryResult<Item, Cursor>>;
|
|
50
|
+
getFirstCursor(): Cursor;
|
|
51
|
+
getLastCursor(): Cursor;
|
|
52
|
+
compare(orderBy: OrderBy, a: Item, b: Item): number;
|
|
53
|
+
nextOrPrev(type: 'next' | 'prev', options: QueryOptions<'next' | 'prev', Cursor, Filter, OrderBy>): Promise<QueryResult<Item, Cursor>>;
|
|
54
|
+
next({ after, ...rest }: QueryOptions<'next', Cursor, Filter, OrderBy>): Promise<QueryResult<Item, Cursor>>;
|
|
55
|
+
prev({ before, ...rest }: QueryOptions<'prev', Cursor, Filter, OrderBy>): Promise<QueryResult<Item, Cursor>>;
|
|
56
|
+
flatMap<Item2, Cursor2 extends string, Filter2 extends unknown, OrderBy2 extends unknown>(options: {
|
|
57
|
+
itemMapper: (itemEntry: {
|
|
58
|
+
item: Item;
|
|
59
|
+
itemCursor: Cursor;
|
|
60
|
+
}, filter: Filter2, orderBy: OrderBy2) => {
|
|
61
|
+
item: Item2;
|
|
62
|
+
itemCursor: Cursor2;
|
|
63
|
+
}[];
|
|
64
|
+
compare: (orderBy: OrderBy2, a: Item2, b: Item2) => number;
|
|
65
|
+
newCursorFromOldCursor: (cursor: Cursor) => Cursor2;
|
|
66
|
+
oldCursorFromNewCursor: (cursor: Cursor2) => Cursor;
|
|
67
|
+
oldFilterFromNewFilter: (filter: Filter2) => Filter;
|
|
68
|
+
oldOrderByFromNewOrderBy: (orderBy: OrderBy2) => OrderBy;
|
|
69
|
+
estimateItemsToFetch: (options: {
|
|
70
|
+
filter: Filter2;
|
|
71
|
+
orderBy: OrderBy2;
|
|
72
|
+
limit: number;
|
|
73
|
+
}) => number;
|
|
74
|
+
}): PaginatedList<Item2, Cursor2, Filter2, OrderBy2>;
|
|
75
|
+
map<Item2, Filter2 extends unknown, OrderBy2 extends unknown>(options: {
|
|
76
|
+
itemMapper: (item: Item) => Item2;
|
|
77
|
+
oldItemFromNewItem: (item: Item2) => Item;
|
|
78
|
+
oldFilterFromNewFilter: (filter: Filter2) => Filter;
|
|
79
|
+
oldOrderByFromNewOrderBy: (orderBy: OrderBy2) => OrderBy;
|
|
80
|
+
}): PaginatedList<Item2, Cursor, Filter2, OrderBy2>;
|
|
81
|
+
filter<Filter2 extends unknown>(options: {
|
|
82
|
+
filter: (item: Item, filter: Filter2) => boolean;
|
|
83
|
+
oldFilterFromNewFilter: (filter: Filter2) => Filter;
|
|
84
|
+
estimateItemsToFetch: (options: {
|
|
85
|
+
filter: Filter2;
|
|
86
|
+
orderBy: OrderBy;
|
|
87
|
+
limit: number;
|
|
88
|
+
}) => number;
|
|
89
|
+
}): PaginatedList<Item, Cursor, Filter2, OrderBy>;
|
|
90
|
+
addFilter<AddedFilter extends unknown>(options: {
|
|
91
|
+
filter: (item: Item, filter: Filter & AddedFilter) => boolean;
|
|
92
|
+
estimateItemsToFetch: (options: {
|
|
93
|
+
filter: Filter & AddedFilter;
|
|
94
|
+
orderBy: OrderBy;
|
|
95
|
+
limit: number;
|
|
96
|
+
}) => number;
|
|
97
|
+
}): PaginatedList<Item, Cursor, Filter & AddedFilter, OrderBy>;
|
|
98
|
+
static merge<Item, Filter extends unknown, OrderBy extends unknown>(...lists: PaginatedList<Item, any, Filter, OrderBy>[]): PaginatedList<Item, string, Filter, OrderBy>;
|
|
99
|
+
static empty(): {
|
|
100
|
+
_getFirstCursor(): "first";
|
|
101
|
+
_getLastCursor(): "last";
|
|
102
|
+
_compare(orderBy: any, a: any, b: any): number;
|
|
103
|
+
_nextOrPrev(type: 'next' | 'prev', options: ImplQueryOptions<'next' | 'prev', string, any, any>): Promise<{
|
|
104
|
+
items: never[];
|
|
105
|
+
isFirst: boolean;
|
|
106
|
+
isLast: boolean;
|
|
107
|
+
cursor: "first";
|
|
108
|
+
}>;
|
|
109
|
+
getFirstCursor(): "first" | "last";
|
|
110
|
+
getLastCursor(): "first" | "last";
|
|
111
|
+
compare(orderBy: any, a: never, b: never): number;
|
|
112
|
+
nextOrPrev(type: "next" | "prev", options: QueryOptions<"next" | "prev", "first" | "last", any, any>): Promise<QueryResult<never, "first" | "last">>;
|
|
113
|
+
next({ after, ...rest }: QueryOptions<"next", "first" | "last", any, any>): Promise<QueryResult<never, "first" | "last">>;
|
|
114
|
+
prev({ before, ...rest }: QueryOptions<"prev", "first" | "last", any, any>): Promise<QueryResult<never, "first" | "last">>;
|
|
115
|
+
flatMap<Item2, Cursor2 extends string, Filter2 extends unknown, OrderBy2 extends unknown>(options: {
|
|
116
|
+
itemMapper: (itemEntry: {
|
|
117
|
+
item: never;
|
|
118
|
+
itemCursor: "first" | "last";
|
|
119
|
+
}, filter: Filter2, orderBy: OrderBy2) => {
|
|
120
|
+
item: Item2;
|
|
121
|
+
itemCursor: Cursor2;
|
|
122
|
+
}[];
|
|
123
|
+
compare: (orderBy: OrderBy2, a: Item2, b: Item2) => number;
|
|
124
|
+
newCursorFromOldCursor: (cursor: "first" | "last") => Cursor2;
|
|
125
|
+
oldCursorFromNewCursor: (cursor: Cursor2) => "first" | "last";
|
|
126
|
+
oldFilterFromNewFilter: (filter: Filter2) => any;
|
|
127
|
+
oldOrderByFromNewOrderBy: (orderBy: OrderBy2) => any;
|
|
128
|
+
estimateItemsToFetch: (options: {
|
|
129
|
+
filter: Filter2;
|
|
130
|
+
orderBy: OrderBy2;
|
|
131
|
+
limit: number;
|
|
132
|
+
}) => number;
|
|
133
|
+
}): PaginatedList<Item2, Cursor2, Filter2, OrderBy2>;
|
|
134
|
+
map<Item2_1, Filter2_1 extends unknown, OrderBy2_1 extends unknown>(options: {
|
|
135
|
+
itemMapper: (item: never) => Item2_1;
|
|
136
|
+
oldItemFromNewItem: (item: Item2_1) => never;
|
|
137
|
+
oldFilterFromNewFilter: (filter: Filter2_1) => any;
|
|
138
|
+
oldOrderByFromNewOrderBy: (orderBy: OrderBy2_1) => any;
|
|
139
|
+
}): PaginatedList<Item2_1, "first" | "last", Filter2_1, OrderBy2_1>;
|
|
140
|
+
filter<Filter2_2 extends unknown>(options: {
|
|
141
|
+
filter: (item: never, filter: Filter2_2) => boolean;
|
|
142
|
+
oldFilterFromNewFilter: (filter: Filter2_2) => any;
|
|
143
|
+
estimateItemsToFetch: (options: {
|
|
144
|
+
filter: Filter2_2;
|
|
145
|
+
orderBy: any;
|
|
146
|
+
limit: number;
|
|
147
|
+
}) => number;
|
|
148
|
+
}): PaginatedList<never, "first" | "last", Filter2_2, any>;
|
|
149
|
+
addFilter<AddedFilter extends unknown>(options: {
|
|
150
|
+
filter: (item: never, filter: any) => boolean;
|
|
151
|
+
estimateItemsToFetch: (options: {
|
|
152
|
+
filter: any;
|
|
153
|
+
orderBy: any;
|
|
154
|
+
limit: number;
|
|
155
|
+
}) => number;
|
|
156
|
+
}): PaginatedList<never, "first" | "last", any, any>;
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
declare class ArrayPaginatedList<Item> extends PaginatedList<Item, `${number}`, (item: Item) => boolean, (a: Item, b: Item) => number> {
|
|
160
|
+
private readonly array;
|
|
161
|
+
constructor(array: Item[]);
|
|
162
|
+
_getFirstCursor(): "0";
|
|
163
|
+
_getLastCursor(): `${number}`;
|
|
164
|
+
_compare(orderBy: (a: Item, b: Item) => number, a: Item, b: Item): number;
|
|
165
|
+
_nextOrPrev(type: 'next' | 'prev', options: ImplQueryOptions<'next' | 'prev', `${number}`, (item: Item) => boolean, (a: Item, b: Item) => number>): Promise<{
|
|
166
|
+
items: {
|
|
167
|
+
item: Item;
|
|
168
|
+
itemCursor: `${number}`;
|
|
169
|
+
}[];
|
|
170
|
+
isFirst: boolean;
|
|
171
|
+
isLast: boolean;
|
|
172
|
+
cursor: `${number}`;
|
|
173
|
+
}>;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export { ArrayPaginatedList, PaginatedList };
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/utils/paginated-lists.tsx
|
|
21
|
+
var paginated_lists_exports = {};
|
|
22
|
+
__export(paginated_lists_exports, {
|
|
23
|
+
ArrayPaginatedList: () => ArrayPaginatedList,
|
|
24
|
+
PaginatedList: () => PaginatedList
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(paginated_lists_exports);
|
|
27
|
+
var import_arrays = require("./arrays.js");
|
|
28
|
+
var import_errors = require("./errors.js");
|
|
29
|
+
var PaginatedList = class _PaginatedList {
|
|
30
|
+
// Implementations
|
|
31
|
+
getFirstCursor() {
|
|
32
|
+
return this._getFirstCursor();
|
|
33
|
+
}
|
|
34
|
+
getLastCursor() {
|
|
35
|
+
return this._getLastCursor();
|
|
36
|
+
}
|
|
37
|
+
compare(orderBy, a, b) {
|
|
38
|
+
return this._compare(orderBy, a, b);
|
|
39
|
+
}
|
|
40
|
+
async nextOrPrev(type, options) {
|
|
41
|
+
let result = [];
|
|
42
|
+
let includesFirst = false;
|
|
43
|
+
let includesLast = false;
|
|
44
|
+
let cursor = options.cursor;
|
|
45
|
+
let limitRemaining = options.limit;
|
|
46
|
+
while (limitRemaining > 0 || type === "next" && includesLast || type === "prev" && includesFirst) {
|
|
47
|
+
const iterationRes = await this._nextOrPrev(type, {
|
|
48
|
+
cursor,
|
|
49
|
+
limit: options.limit,
|
|
50
|
+
limitPrecision: "approximate",
|
|
51
|
+
filter: options.filter,
|
|
52
|
+
orderBy: options.orderBy
|
|
53
|
+
});
|
|
54
|
+
result[type === "next" ? "push" : "unshift"](...iterationRes.items);
|
|
55
|
+
limitRemaining -= iterationRes.items.length;
|
|
56
|
+
includesFirst ||= iterationRes.isFirst;
|
|
57
|
+
includesLast ||= iterationRes.isLast;
|
|
58
|
+
cursor = iterationRes.cursor;
|
|
59
|
+
if (["approximate", "at-most"].includes(options.limitPrecision)) break;
|
|
60
|
+
}
|
|
61
|
+
for (let i = 1; i < result.length; i++) {
|
|
62
|
+
if (this._compare(options.orderBy, result[i].item, result[i - 1].item) < 0) {
|
|
63
|
+
throw new import_errors.StackAssertionError("Paginated list result is not sorted; something is wrong with the implementation", {
|
|
64
|
+
i,
|
|
65
|
+
options,
|
|
66
|
+
result
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (["exact", "at-most"].includes(options.limitPrecision) && result.length > options.limit) {
|
|
71
|
+
if (type === "next") {
|
|
72
|
+
result = result.slice(0, options.limit);
|
|
73
|
+
includesLast = false;
|
|
74
|
+
if (options.limit > 0) cursor = result[result.length - 1].itemCursor;
|
|
75
|
+
} else {
|
|
76
|
+
result = result.slice(result.length - options.limit);
|
|
77
|
+
includesFirst = false;
|
|
78
|
+
if (options.limit > 0) cursor = result[0].itemCursor;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return { items: result, isFirst: includesFirst, isLast: includesLast, cursor };
|
|
82
|
+
}
|
|
83
|
+
async next({ after, ...rest }) {
|
|
84
|
+
return await this.nextOrPrev("next", {
|
|
85
|
+
...rest,
|
|
86
|
+
cursor: after
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
async prev({ before, ...rest }) {
|
|
90
|
+
return await this.nextOrPrev("prev", {
|
|
91
|
+
...rest,
|
|
92
|
+
cursor: before
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
// Utility methods below
|
|
96
|
+
flatMap(options) {
|
|
97
|
+
const that = this;
|
|
98
|
+
class FlatMapPaginatedList extends _PaginatedList {
|
|
99
|
+
_getFirstCursor() {
|
|
100
|
+
return options.newCursorFromOldCursor(that.getFirstCursor());
|
|
101
|
+
}
|
|
102
|
+
_getLastCursor() {
|
|
103
|
+
return options.newCursorFromOldCursor(that.getLastCursor());
|
|
104
|
+
}
|
|
105
|
+
_compare(orderBy, a, b) {
|
|
106
|
+
return options.compare(orderBy, a, b);
|
|
107
|
+
}
|
|
108
|
+
async _nextOrPrev(type, { limit, filter, orderBy, cursor }) {
|
|
109
|
+
const estimatedItems = options.estimateItemsToFetch({ limit, filter, orderBy });
|
|
110
|
+
const original = await that.nextOrPrev(type, {
|
|
111
|
+
limit: estimatedItems,
|
|
112
|
+
limitPrecision: "approximate",
|
|
113
|
+
cursor: options.oldCursorFromNewCursor(cursor),
|
|
114
|
+
filter: options.oldFilterFromNewFilter(filter),
|
|
115
|
+
orderBy: options.oldOrderByFromNewOrderBy(orderBy)
|
|
116
|
+
});
|
|
117
|
+
const mapped = original.items.flatMap((itemEntry) => options.itemMapper(
|
|
118
|
+
itemEntry,
|
|
119
|
+
filter,
|
|
120
|
+
orderBy
|
|
121
|
+
));
|
|
122
|
+
return {
|
|
123
|
+
items: mapped,
|
|
124
|
+
isFirst: original.isFirst,
|
|
125
|
+
isLast: original.isLast,
|
|
126
|
+
cursor: options.newCursorFromOldCursor(original.cursor)
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return new FlatMapPaginatedList();
|
|
131
|
+
}
|
|
132
|
+
map(options) {
|
|
133
|
+
return this.flatMap({
|
|
134
|
+
itemMapper: (itemEntry, filter, orderBy) => {
|
|
135
|
+
return [{ item: options.itemMapper(itemEntry.item), itemCursor: itemEntry.itemCursor }];
|
|
136
|
+
},
|
|
137
|
+
compare: (orderBy, a, b) => this.compare(options.oldOrderByFromNewOrderBy(orderBy), options.oldItemFromNewItem(a), options.oldItemFromNewItem(b)),
|
|
138
|
+
newCursorFromOldCursor: (cursor) => cursor,
|
|
139
|
+
oldCursorFromNewCursor: (cursor) => cursor,
|
|
140
|
+
oldFilterFromNewFilter: (filter) => options.oldFilterFromNewFilter(filter),
|
|
141
|
+
oldOrderByFromNewOrderBy: (orderBy) => options.oldOrderByFromNewOrderBy(orderBy),
|
|
142
|
+
estimateItemsToFetch: (options2) => options2.limit
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
filter(options) {
|
|
146
|
+
return this.flatMap({
|
|
147
|
+
itemMapper: (itemEntry, filter, orderBy) => options.filter(itemEntry.item, filter) ? [itemEntry] : [],
|
|
148
|
+
compare: (orderBy, a, b) => this.compare(orderBy, a, b),
|
|
149
|
+
newCursorFromOldCursor: (cursor) => cursor,
|
|
150
|
+
oldCursorFromNewCursor: (cursor) => cursor,
|
|
151
|
+
oldFilterFromNewFilter: (filter) => options.oldFilterFromNewFilter(filter),
|
|
152
|
+
oldOrderByFromNewOrderBy: (orderBy) => orderBy,
|
|
153
|
+
estimateItemsToFetch: (o) => options.estimateItemsToFetch(o)
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
addFilter(options) {
|
|
157
|
+
return this.filter({
|
|
158
|
+
filter: (item, filter) => options.filter(item, filter),
|
|
159
|
+
oldFilterFromNewFilter: (filter) => filter,
|
|
160
|
+
estimateItemsToFetch: (o) => options.estimateItemsToFetch(o)
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
static merge(...lists) {
|
|
164
|
+
class MergePaginatedList extends _PaginatedList {
|
|
165
|
+
_getFirstCursor() {
|
|
166
|
+
return JSON.stringify(lists.map((list) => list.getFirstCursor()));
|
|
167
|
+
}
|
|
168
|
+
_getLastCursor() {
|
|
169
|
+
return JSON.stringify(lists.map((list) => list.getLastCursor()));
|
|
170
|
+
}
|
|
171
|
+
_compare(orderBy, a, b) {
|
|
172
|
+
const listsResults = lists.map((list) => list.compare(orderBy, a, b));
|
|
173
|
+
if (!listsResults.every((result) => result === listsResults[0])) {
|
|
174
|
+
throw new import_errors.StackAssertionError("Lists have different compare results; make sure that they use the same compare function", { lists, listsResults });
|
|
175
|
+
}
|
|
176
|
+
return listsResults[0];
|
|
177
|
+
}
|
|
178
|
+
async _nextOrPrev(type, { limit, filter, orderBy, cursor }) {
|
|
179
|
+
const cursors = JSON.parse(cursor);
|
|
180
|
+
const fetchedLists = await Promise.all(lists.map(async (list, i) => {
|
|
181
|
+
return await list.nextOrPrev(type, {
|
|
182
|
+
limit,
|
|
183
|
+
filter,
|
|
184
|
+
orderBy,
|
|
185
|
+
cursor: cursors[i],
|
|
186
|
+
limitPrecision: "at-least"
|
|
187
|
+
});
|
|
188
|
+
}));
|
|
189
|
+
const combinedItems = fetchedLists.flatMap((list, i) => list.items.map((itemEntry) => ({ itemEntry, listIndex: i })));
|
|
190
|
+
const sortedItems = [...combinedItems].sort((a, b) => this._compare(orderBy, a.itemEntry.item, b.itemEntry.item));
|
|
191
|
+
const lastCursorForEachList = sortedItems.reduce((acc, item) => {
|
|
192
|
+
acc[item.listIndex] = item.itemEntry.itemCursor;
|
|
193
|
+
return acc;
|
|
194
|
+
}, (0, import_arrays.range)(lists.length).map((i) => cursors[i]));
|
|
195
|
+
return {
|
|
196
|
+
items: sortedItems.map((item) => item.itemEntry),
|
|
197
|
+
isFirst: sortedItems.every((item) => item.listIndex === 0),
|
|
198
|
+
isLast: sortedItems.every((item) => item.listIndex === lists.length - 1),
|
|
199
|
+
cursor: JSON.stringify(lastCursorForEachList)
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return new MergePaginatedList();
|
|
204
|
+
}
|
|
205
|
+
static empty() {
|
|
206
|
+
class EmptyPaginatedList extends _PaginatedList {
|
|
207
|
+
_getFirstCursor() {
|
|
208
|
+
return "first";
|
|
209
|
+
}
|
|
210
|
+
_getLastCursor() {
|
|
211
|
+
return "last";
|
|
212
|
+
}
|
|
213
|
+
_compare(orderBy, a, b) {
|
|
214
|
+
return 0;
|
|
215
|
+
}
|
|
216
|
+
async _nextOrPrev(type, options) {
|
|
217
|
+
return { items: [], isFirst: true, isLast: true, cursor: "first" };
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return new EmptyPaginatedList();
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
var ArrayPaginatedList = class extends PaginatedList {
|
|
224
|
+
constructor(array) {
|
|
225
|
+
super();
|
|
226
|
+
this.array = array;
|
|
227
|
+
}
|
|
228
|
+
_getFirstCursor() {
|
|
229
|
+
return "0";
|
|
230
|
+
}
|
|
231
|
+
_getLastCursor() {
|
|
232
|
+
return `${this.array.length - 1}`;
|
|
233
|
+
}
|
|
234
|
+
_compare(orderBy, a, b) {
|
|
235
|
+
return orderBy(a, b);
|
|
236
|
+
}
|
|
237
|
+
async _nextOrPrev(type, options) {
|
|
238
|
+
const filteredArray = this.array.filter(options.filter);
|
|
239
|
+
const sortedArray = [...filteredArray].sort((a, b) => this._compare(options.orderBy, a, b));
|
|
240
|
+
const itemEntriesArray = sortedArray.map((item, index) => ({ item, itemCursor: `${index}` }));
|
|
241
|
+
const oldCursor = Number(options.cursor);
|
|
242
|
+
const newCursor = Math.max(0, Math.min(this.array.length - 1, oldCursor + (type === "next" ? 1 : -1) * options.limit));
|
|
243
|
+
return {
|
|
244
|
+
items: itemEntriesArray.slice(Math.min(oldCursor, newCursor), Math.max(oldCursor, newCursor)),
|
|
245
|
+
isFirst: oldCursor === 0 || newCursor === 0,
|
|
246
|
+
isLast: oldCursor === this.array.length - 1 || newCursor === this.array.length - 1,
|
|
247
|
+
cursor: `${newCursor}`
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
252
|
+
0 && (module.exports = {
|
|
253
|
+
ArrayPaginatedList,
|
|
254
|
+
PaginatedList
|
|
255
|
+
});
|
|
256
|
+
//# sourceMappingURL=paginated-lists.js.map
|