@lowerdeck/pagination 1.0.0 → 1.0.2

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 ADDED
@@ -0,0 +1,7 @@
1
+ # @lowerdeck/pagination
2
+
3
+ ## 1.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Add mongoose opts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lowerdeck/pagination",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -24,8 +24,9 @@
24
24
  "build": "microbundle"
25
25
  },
26
26
  "devDependencies": {
27
- "microbundle": "^0.15.1",
28
27
  "@lowerdeck/tsconfig": "^1.0.0",
28
+ "microbundle": "^0.15.1",
29
+ "mongoose": "^9.0.2",
29
30
  "typescript": "^5.9.3",
30
31
  "vitest": "^3.2.4"
31
32
  },
@@ -1,4 +1,5 @@
1
1
  import { ServiceError, badRequestError } from '@lowerdeck/error';
2
+ import type { QueryFilter, SortOrder } from 'mongoose';
2
3
  import { PaginatedList } from './types';
3
4
 
4
5
  export interface PaginatedProviderInput {
@@ -15,6 +16,12 @@ export interface PrismaPaginationOpts {
15
16
  skip: number;
16
17
  }
17
18
 
19
+ export interface MongoosePaginationOpts<T> {
20
+ filter: QueryFilter<T>;
21
+ sort: { _id: SortOrder };
22
+ limit: number;
23
+ }
24
+
18
25
  export type PaginatedProvider<T> = (
19
26
  input: PaginatedProviderInput
20
27
  ) => Promise<PaginatedList<T>>;
@@ -98,3 +105,65 @@ export let paginatedProviderPrisma =
98
105
  }
99
106
  };
100
107
  };
108
+
109
+ export let paginatedProviderMongoose =
110
+ <T extends { _id: string }>(
111
+ provider: (opts: MongoosePaginationOpts<T>) => Promise<T[] | null | undefined>
112
+ ): PaginatedProvider<T> =>
113
+ async (input: PaginatedProviderInput) => {
114
+ let { limit, after, before, order } = input;
115
+
116
+ if (after && before) {
117
+ throw new ServiceError(
118
+ badRequestError({
119
+ message: 'Cannot use both after and before cursors'
120
+ })
121
+ );
122
+ }
123
+
124
+ let filter: QueryFilter<T> = {};
125
+ let sort: { _id: SortOrder } = { _id: order === 'asc' ? 1 : -1 };
126
+ let cursorId = after ?? before;
127
+ let cursorType: 'after' | 'before' | 'none' = 'none';
128
+
129
+ if (after) {
130
+ filter._id = order === 'asc' ? { $gt: after } : { $lt: after };
131
+ cursorType = 'after';
132
+ } else if (before) {
133
+ filter._id = order === 'asc' ? { $lt: before } : { $gt: before };
134
+ sort._id = order === 'asc' ? -1 : 1;
135
+ cursorType = 'before';
136
+ }
137
+
138
+ let opts: MongoosePaginationOpts<T> = {
139
+ filter,
140
+ sort,
141
+ limit: limit + 1
142
+ };
143
+
144
+ let items = (await provider(opts)) ?? [];
145
+
146
+ if (cursorType === 'before') items = items.reverse();
147
+
148
+ let hasMore = items.length > limit;
149
+ let selectedItems = hasMore ? items.slice(0, limit) : items;
150
+
151
+ let hasItemsBefore = false;
152
+ let hasItemsAfter = false;
153
+
154
+ if (cursorType === 'after' || cursorType === 'none') {
155
+ hasItemsAfter = hasMore;
156
+ hasItemsBefore = !!after;
157
+ } else if (cursorType === 'before') {
158
+ hasItemsBefore = hasMore;
159
+ hasItemsAfter = !!before;
160
+ }
161
+
162
+ return {
163
+ items: selectedItems,
164
+ pagination: {
165
+ hasNextPage: hasItemsAfter,
166
+ hasPreviousPage: hasItemsBefore
167
+ }
168
+ };
169
+ };
package/src/paginator.ts CHANGED
@@ -3,6 +3,7 @@ import { Cursor } from './cursor';
3
3
  import {
4
4
  PaginatedProvider,
5
5
  PaginatedProviderInput,
6
+ paginatedProviderMongoose,
6
7
  paginatedProviderPrisma
7
8
  } from './paginatedProvider';
8
9
  import { PaginatedList } from './types';
@@ -22,6 +23,7 @@ export interface PaginatorOpts {
22
23
 
23
24
  export type Provider<T> = (providers: {
24
25
  prisma: typeof paginatedProviderPrisma;
26
+ mongoose: typeof paginatedProviderMongoose;
25
27
  }) => PaginatedProvider<T>;
26
28
 
27
29
  export class Paginator<T> {
@@ -113,7 +115,8 @@ export class Paginator<T> {
113
115
  }
114
116
 
115
117
  let provider = this.provider({
116
- prisma: paginatedProviderPrisma
118
+ prisma: paginatedProviderPrisma,
119
+ mongoose: paginatedProviderMongoose
117
120
  });
118
121
 
119
122
  return await provider(providerInput);
@@ -1,14 +0,0 @@
1
-
2
- $ microbundle
3
- No name was provided for external module '@lowerdeck/error' in output.globals – guessing 'error'
4
- No name was provided for external module '@lowerdeck/validation' in output.globals – guessing 'validation'
5
- No name was provided for external module '@lowerdeck/base62' in output.globals – guessing 'base62'
6
- Build "@lowerdeck/pagination" to dist:
7
- 1378 B: index.cjs.gz
8
- 1232 B: index.cjs.br
9
- 1289 B: index.module.js.gz
10
- 1159 B: index.module.js.br
11
- 1381 B: index.module.js.gz
12
- 1239 B: index.module.js.br
13
- 1444 B: index.umd.js.gz
14
- 1291 B: index.umd.js.br
@@ -1,35 +0,0 @@
1
-
2
- $ vitest run --passWithNoTests
3
- [?25l
4
-  RUN  v3.2.4 /Users/tobias/code/metorial/metorial-enterprise/oss/src/packages/shared/anonymize-ip
5
-
6
- [?2026h
7
-  ❯ src/anonymizeIp.test.ts [queued]
8
-
9
-  Test Files 0 passed (1)
10
-  Tests 0 passed (0)
11
-  Start at 10:23:25
12
-  Duration 101ms
13
- [?2026l ✓ src/anonymizeIp.test.ts (15 tests) 4ms
14
- ✓ anonymizeIP > anonymizes IPv4 with default options 1ms
15
- ✓ anonymizeIP > anonymizes IPv4 with keepGroups=1 0ms
16
- ✓ anonymizeIP > anonymizes IPv4 with keepGroups=3 0ms
17
- ✓ anonymizeIP > anonymizes IPv4 with custom maskChar 0ms
18
- ✓ anonymizeIP > throws error for invalid IPv4 keepGroups 1ms
19
- ✓ anonymizeIP > anonymizes IPv6 with default options 0ms
20
- ✓ anonymizeIP > anonymizes IPv6 with keepGroups=2 0ms
21
- ✓ anonymizeIP > anonymizes IPv6 with keepGroups=7 0ms
22
- ✓ anonymizeIP > anonymizes IPv6 with custom maskChar 0ms
23
- ✓ anonymizeIP > throws error for invalid IPv6 keepGroups 0ms
24
- ✓ anonymizeIP > anonymizes IPv6 compressed notation 0ms
25
- ✓ anonymizeIP > anonymizes IPv6 :: 0ms
26
- ✓ anonymizeIP > anonymizes IPv6 with embedded IPv4 0ms
27
- ✓ anonymizeIP > throws error for invalid IP address 0ms
28
- ✓ anonymizeIP > trims whitespace from IP 0ms
29
-
30
-  Test Files  1 passed (1)
31
-  Tests  15 passed (15)
32
-  Start at  10:23:25
33
-  Duration  230ms (transform 36ms, setup 0ms, collect 35ms, tests 4ms, environment 0ms, prepare 39ms)
34
-
35
- [?25h
@@ -1,10 +0,0 @@
1
- interface AnonymizationOptions {
2
- maskChar?: string;
3
- keepGroups?: {
4
- ipv4?: number;
5
- ipv6?: number;
6
- } | number;
7
- }
8
- export declare let anonymizeIP: (ip: string, options?: AnonymizationOptions) => string;
9
- export {};
10
- //# sourceMappingURL=anonymizeIp.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"anonymizeIp.d.ts","sourceRoot":"","sources":["../src/anonymizeIp.ts"],"names":[],"mappings":"AAQA,UAAU,oBAAoB;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EACP;QACE,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,GACD,MAAM,CAAC;CACZ;AAuHD,eAAO,IAAI,WAAW,GAAI,IAAI,MAAM,EAAE,UAAS,oBAAyB,WAwBvE,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=anonymizeIp.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"anonymizeIp.test.d.ts","sourceRoot":"","sources":["../src/anonymizeIp.test.ts"],"names":[],"mappings":""}
@@ -1,82 +0,0 @@
1
- import { ValidationType } from '@lowerdeck/validation';
2
- import * as Cookie from 'cookie';
3
- export type Method = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
4
- export interface ServiceRequest {
5
- query: URLSearchParams;
6
- headers: Headers;
7
- url: string;
8
- ip?: string;
9
- body: any;
10
- rawBody: any;
11
- requestId: string;
12
- getCookies: () => Record<string, string | undefined>;
13
- getCookie: (name: string) => string | undefined;
14
- setCookie: (name: string, value: string, opts?: Cookie.SerializeOptions) => void;
15
- sharedMiddlewareMemo: Map<string, Promise<any>>;
16
- beforeSend: (handler: () => Promise<any>) => void;
17
- appendHeaders: (headers: Record<string, string | string[]>) => void;
18
- }
19
- export type Simplify<T> = {
20
- [KeyType in keyof T]: T[KeyType];
21
- } & {};
22
- export type ExtendContext<C extends object, E> = E extends object ? Simplify<C & E> : C;
23
- export declare class Group<Context extends {
24
- [key: string]: any;
25
- } = {}> {
26
- private _middleware;
27
- constructor(_middleware?: Array<(ctx: Context & ServiceRequest) => Promise<any>>);
28
- use<T extends {
29
- [key: string]: any;
30
- } | undefined | void>(handler: (ctx: Context & ServiceRequest) => Promise<T>, opts?: {
31
- getSharedMemoKey?: (ctx: Context & ServiceRequest) => string;
32
- }): Group<Context & T extends infer T_1 ? { [KeyType in keyof T_1]: T_1[KeyType]; } : never>;
33
- createMiddleware<T extends {
34
- [key: string]: any;
35
- }, P = void>(handler: (ctx: Context & ServiceRequest, input: P) => Promise<T>, opts?: {
36
- getSharedMemoKey?: (ctx: Context & ServiceRequest, input: P) => string;
37
- }): (input: P) => (ctx: Context & ServiceRequest) => Promise<T>;
38
- handler(): Handler<unknown, unknown, Context>;
39
- controller<HandlersAndSubControllers extends {
40
- [key: string]: Handler<any, any, any> | Controller<any>;
41
- }>(handlers: HandlersAndSubControllers): Controller<HandlersAndSubControllers>;
42
- }
43
- export type Controller<HandlersAndSubControllers extends {
44
- [key: string]: Handler<any, any, any> | Controller<any>;
45
- }> = HandlersAndSubControllers;
46
- export type InferControllerType<T> = T extends Controller<infer U> ? U : never;
47
- export type InferClient<HandlersAndSubControllers extends {
48
- [key: string]: Handler<any, any, any> | Controller<any>;
49
- }> = {
50
- [K in keyof HandlersAndSubControllers]: HandlersAndSubControllers[K] extends Handler<infer I, infer O, infer C> ? ((input: I, opts?: {
51
- headers?: Record<string, string>;
52
- query?: Record<string, string>;
53
- }) => Promise<O>) & {
54
- getFull: (input: I, opts?: {
55
- headers?: Record<string, string>;
56
- query?: Record<string, string>;
57
- }) => Promise<{
58
- data: O;
59
- status: number;
60
- headers: Record<string, string>;
61
- }>;
62
- } : HandlersAndSubControllers[K] extends Controller<infer U> ? InferClient<U> : never;
63
- };
64
- export declare class Handler<Input, Output, Context extends {
65
- [key: string]: any;
66
- } = {}> {
67
- private _middleware;
68
- private _handler;
69
- private _validation;
70
- constructor(_middleware?: Array<(ctx: Context & ServiceRequest) => Promise<any>>);
71
- do<HandlerOutput>(handler: (ctx: Context & Omit<ServiceRequest, 'body'> & {
72
- input: Input;
73
- }) => Promise<HandlerOutput>): Handler<Input, HandlerOutput, Context>;
74
- use<T extends {
75
- [key: string]: any;
76
- } = {}>(handler: (ctx: Context & ServiceRequest) => Promise<T | undefined | void>): Handler<Input, Output, ExtendContext<Context, T>>;
77
- input<HandlerInput>(validation: ValidationType<HandlerInput>): Handler<HandlerInput, Output, Context>;
78
- run(req: ServiceRequest, initialContext: any): Promise<{
79
- response: Output;
80
- }>;
81
- }
82
- //# sourceMappingURL=controller.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../src/controller.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=controller.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"controller.test.d.ts","sourceRoot":"","sources":["../src/controller.test.ts"],"names":[],"mappings":""}
package/dist/cursor.d.ts DELETED
@@ -1,9 +0,0 @@
1
- export declare class Cursor {
2
- readonly id: string;
3
- readonly type: 'after' | 'before';
4
- private constructor();
5
- static fromString(str: string): Cursor;
6
- static fromId(id: string, type: 'after' | 'before'): Cursor;
7
- toString(): string;
8
- }
9
- //# sourceMappingURL=cursor.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../src/cursor.ts"],"names":[],"mappings":"AAKA,qBAAa,MAAM;aAEC,EAAE,EAAE,MAAM;aACV,IAAI,EAAE,OAAO,GAAG,QAAQ;IAF1C,OAAO;IAKP,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM;IAiC7B,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,QAAQ;IAIlD,QAAQ;CAGT"}
@@ -1,2 +0,0 @@
1
- export declare let parseForwardedFor: (xForwardedForHeader?: string | null | undefined) => string | undefined;
2
- //# sourceMappingURL=extractIp.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"extractIp.d.ts","sourceRoot":"","sources":["../src/extractIp.ts"],"names":[],"mappings":"AAAA,eAAO,IAAI,iBAAiB,GAAI,sBAAsB,MAAM,GAAG,IAAI,GAAG,SAAS,uBAQ9E,CAAC"}
package/dist/index.cjs DELETED
@@ -1,2 +0,0 @@
1
- var r=require("@lowerdeck/error"),e=require("@lowerdeck/validation"),t=require("@lowerdeck/base62"),i=function(e){return function(t){try{var i=t.limit,o=t.after,n=t.before,a=t.order;if(o&&n)throw new r.ServiceError(r.badRequestError({message:"Cannot use both after and before cursors"}));var s={orderBy:[{id:a}],take:i+2,skip:0},u=null!=o?o:n,l="none";return o?(s.cursor={id:o},l="after"):n&&(s.cursor={id:n},s.take=-s.take,s.skip=0,l="before"),Promise.resolve(e(s)).then(function(r){var e=r,t=u?null==e?void 0:e.find(function(r){return r.id==u}):void 0,o=t?null==e?void 0:e.indexOf(t):void 0,n="number"==typeof o?[].concat(e.slice(0,o),e.slice(o+1)):e,a=null==n?void 0:n.slice(0,i);"before"==l&&n.length>i&&(a=null==n?void 0:n.slice(1,i+1));var s=!1,c=!1;return"after"==l||"none"==l?(n.length>a.length&&(c=!0),t&&(s=!0)):"before"==l&&(n.length>a.length&&(s=!0),t&&(c=!0)),{items:a,pagination:{hasNextPage:c,hasPreviousPage:s}}})}catch(r){return Promise.reject(r)}}},o="cur_",n=/*#__PURE__*/function(){function e(r,e){this.id=void 0,this.type=void 0,this.id=r,this.type=e}return e.fromString=function(i){if(!i.startsWith(o))throw new r.ServiceError(r.badRequestError({message:"Invalid cursor format",hint:'Cursor must start with "cur_"'}));try{var n=t.base62.decode(i.slice(4)),a=JSON.parse(n.toString()),s=a[0],u=a[1];if("after"!==s&&"before"!==s)throw new Error("Invalid cursor type");if("string"!=typeof u)throw new Error("Invalid cursor id");return new e(u,s)}catch(e){throw new r.ServiceError(r.badRequestError({message:"Invalid cursor format",hint:"Please provide a valid cursor from another page."}))}},e.fromId=function(r,t){return new e(r,t)},e.prototype.toString=function(){return o+t.base62.encode(JSON.stringify([this.type,this.id]))},e}();exports.Paginator=/*#__PURE__*/function(){function r(r,e){void 0===e&&(e={}),this.provider=void 0,this.opts=void 0,this.provider=r,this.opts=e}return r.create=function(e,t){return void 0===t&&(t={}),new r(e,t)},r.validate=function(r){return e.v.intersection([e.v.object({limit:e.v.optional(e.v.number({modifiers:[e.v.minValue(1),e.v.maxValue(100)]})),after:e.v.optional(e.v.string()),before:e.v.optional(e.v.string()),cursor:e.v.optional(e.v.string()),order:e.v.optional(e.v.enumOf(["asc","desc"]))}),null!=r?r:e.v.object({})])},r.present=function(r,e){return function(t){return{run:function(){try{return Promise.resolve(Promise.all(r.items.map(function(r){var i;return null==(i=e(r))||null==(i=i(t))?void 0:i.run({})}))).then(function(e){return{__typename:"list",items:e.filter(Boolean),pagination:{has_more_after:r.pagination.hasNextPage,has_more_before:r.pagination.hasPreviousPage}}})}catch(r){return Promise.reject(r)}}}}},r.presentLight=function(r,e){try{return Promise.resolve(Promise.all(r.items.map(function(r){return e(r)}))).then(function(e){return{__typename:"list",items:e.filter(Boolean),pagination:{has_more_after:r.pagination.hasNextPage,has_more_before:r.pagination.hasPreviousPage}}})}catch(r){return Promise.reject(r)}},r.prototype.run=function(r){try{var e,t,o,a,s=this,u=Number(r.limit);isNaN(u)&&(u=20);var l={limit:Math.max(Math.min(null!=(e=null!=u?u:s.opts.defaultLimit)?e:20,null!=(t=s.opts.defaultLimit)?t:100),1),order:null!=(o=null!=(a=r.order)?a:s.opts.defaultOrder)?o:"asc"};if(r.after)l.after=r.after;else if(r.before)l.before=r.before;else if(r.cursor){var c=n.fromString(r.cursor);l[c.type]=c.id}var f=s.provider({prisma:i});return Promise.resolve(f(l))}catch(r){return Promise.reject(r)}},r}(),exports.paginatedProviderPrisma=i;
2
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/paginatedProvider.ts","../src/cursor.ts","../src/paginator.ts"],"sourcesContent":["import { ServiceError, badRequestError } from '@lowerdeck/error';\nimport { PaginatedList } from './types';\n\nexport interface PaginatedProviderInput {\n limit: number;\n after?: string;\n before?: string;\n order: 'asc' | 'desc';\n}\n\nexport interface PrismaPaginationOpts {\n orderBy: [{ id: 'asc' | 'desc' }];\n cursor?: { id: string };\n take: number;\n skip: number;\n}\n\nexport type PaginatedProvider<T> = (\n input: PaginatedProviderInput\n) => Promise<PaginatedList<T>>;\n\nexport let paginatedProviderPrisma =\n <T extends { id: string }>(\n provider: (opts: PrismaPaginationOpts) => Promise<T[] | null | undefined>\n ): PaginatedProvider<T> =>\n async (input: PaginatedProviderInput) => {\n let { limit, after, before, order } = input;\n\n if (after && before) {\n throw new ServiceError(\n badRequestError({\n message: 'Cannot use both after and before cursors'\n })\n );\n }\n\n let opts: PrismaPaginationOpts = {\n orderBy: [{ id: order }],\n take: limit + 2,\n skip: 0\n };\n\n let cursorId = after ?? before;\n let cursorType: 'after' | 'before' | 'none' = 'none';\n\n if (after) {\n opts.cursor = { id: after };\n cursorType = 'after';\n } else if (before) {\n opts.cursor = { id: before };\n opts.take = -opts.take!;\n opts.skip = 0;\n cursorType = 'before';\n }\n\n let items = (await provider(opts)) ?? [];\n\n let orderedItems = items; /* items?.sort((a, b) => {\n if (order == 'asc') {\n return a.id.localeCompare(b.id);\n } else {\n return b.id.localeCompare(a.id);\n }\n });*/\n\n let cursorItem = cursorId ? orderedItems?.find(item => item.id == cursorId) : undefined;\n let cursorItemIndex = cursorItem ? orderedItems?.indexOf(cursorItem) : undefined;\n let orderedItemsWithoutCursor =\n typeof cursorItemIndex == 'number'\n ? [\n ...orderedItems.slice(0, cursorItemIndex),\n ...orderedItems.slice(cursorItemIndex + 1)\n ]\n : orderedItems;\n\n let selectedItems = orderedItemsWithoutCursor?.slice(0, limit);\n\n if (cursorType == 'before' && orderedItemsWithoutCursor.length > limit) {\n selectedItems = orderedItemsWithoutCursor?.slice(1, limit + 1);\n }\n\n let hasItemsBefore = false;\n let hasItemsAfter = false;\n\n if (cursorType == 'after' || cursorType == 'none') {\n if (orderedItemsWithoutCursor.length > selectedItems.length) hasItemsAfter = true;\n if (cursorItem) hasItemsBefore = true;\n } else if (cursorType == 'before') {\n if (orderedItemsWithoutCursor.length > selectedItems.length) hasItemsBefore = true;\n if (cursorItem) hasItemsAfter = true;\n }\n\n return {\n items: selectedItems,\n pagination: {\n hasNextPage: hasItemsAfter,\n hasPreviousPage: hasItemsBefore\n }\n };\n };\n","import { base62 } from '@lowerdeck/base62';\nimport { badRequestError, ServiceError } from '@lowerdeck/error';\n\nlet PREFIX = 'cur_';\n\nexport class Cursor {\n private constructor(\n public readonly id: string,\n public readonly type: 'after' | 'before'\n ) {}\n\n static fromString(str: string) {\n if (!str.startsWith(PREFIX)) {\n throw new ServiceError(\n badRequestError({\n message: 'Invalid cursor format',\n hint: 'Cursor must start with \"cur_\"'\n })\n );\n }\n\n try {\n let decoded = base62.decode(str.slice(PREFIX.length));\n let [type, id] = JSON.parse(decoded.toString());\n\n if (type !== 'after' && type !== 'before') {\n throw new Error('Invalid cursor type');\n }\n\n if (typeof id !== 'string') {\n throw new Error('Invalid cursor id');\n }\n\n return new Cursor(id, type);\n } catch (e) {\n throw new ServiceError(\n badRequestError({\n message: 'Invalid cursor format',\n hint: 'Please provide a valid cursor from another page.'\n })\n );\n }\n }\n\n static fromId(id: string, type: 'after' | 'before') {\n return new Cursor(id, type);\n }\n\n toString() {\n return PREFIX + base62.encode(JSON.stringify([this.type, this.id]));\n }\n}\n","import { v, ValidationType } from '@lowerdeck/validation';\nimport { Cursor } from './cursor';\nimport {\n PaginatedProvider,\n PaginatedProviderInput,\n paginatedProviderPrisma\n} from './paginatedProvider';\nimport { PaginatedList } from './types';\n\nexport interface PaginatorInput {\n limit?: number | string;\n after?: string;\n before?: string;\n cursor?: string;\n order?: 'asc' | 'desc';\n}\n\nexport interface PaginatorOpts {\n defaultLimit?: number;\n defaultOrder?: 'asc' | 'desc';\n}\n\nexport type Provider<T> = (providers: {\n prisma: typeof paginatedProviderPrisma;\n}) => PaginatedProvider<T>;\n\nexport class Paginator<T> {\n private constructor(\n private provider: Provider<T>,\n private opts: PaginatorOpts = {}\n ) {}\n\n static create<T>(provider: Provider<T>, opts: PaginatorOpts = {}) {\n return new Paginator(provider, opts);\n }\n\n static validate<Inner extends object>(inner?: ValidationType<Inner>) {\n return v.intersection([\n v.object({\n limit: v.optional(\n v.number({\n modifiers: [v.minValue(1), v.maxValue(100)]\n })\n ),\n after: v.optional(v.string()),\n before: v.optional(v.string()),\n cursor: v.optional(v.string()),\n order: v.optional(v.enumOf(['asc', 'desc']))\n }),\n inner ?? v.object({})\n ]) as ValidationType<\n Inner & {\n limit?: number;\n after?: string;\n before?: string;\n cursor?: string;\n order?: 'asc' | 'desc';\n }\n >;\n }\n\n static present<T, R>(\n list: PaginatedList<T>,\n presenter: (item: T) => (context: any) => { run: (d: any) => R } | undefined\n ) {\n return (context: any) => ({\n run: async () => ({\n __typename: `list`,\n items: (\n await Promise.all(list.items.map(item => presenter(item)?.(context)?.run({})))\n ).filter(Boolean),\n pagination: {\n has_more_after: list.pagination.hasNextPage,\n has_more_before: list.pagination.hasPreviousPage\n }\n })\n });\n }\n\n static async presentLight<T, R>(\n list: PaginatedList<T>,\n presenter: (item: T) => R | Promise<R>\n ) {\n return {\n __typename: `list`,\n items: (await Promise.all(list.items.map(item => presenter(item)))).filter(Boolean),\n pagination: {\n has_more_after: list.pagination.hasNextPage,\n has_more_before: list.pagination.hasPreviousPage\n }\n };\n }\n\n async run(input: PaginatorInput): Promise<PaginatedList<T>> {\n let numberLimit = Number(input.limit);\n if (isNaN(numberLimit)) numberLimit = 20;\n\n let providerInput: PaginatedProviderInput = {\n limit: Math.max(\n Math.min(numberLimit ?? this.opts.defaultLimit ?? 20, this.opts.defaultLimit ?? 100),\n 1\n ),\n order: input.order ?? this.opts.defaultOrder ?? 'asc'\n };\n\n if (input.after) {\n providerInput.after = input.after;\n } else if (input.before) {\n providerInput.before = input.before;\n } else if (input.cursor) {\n let cursor = Cursor.fromString(input.cursor);\n providerInput[cursor.type] = cursor.id;\n }\n\n let provider = this.provider({\n prisma: paginatedProviderPrisma\n });\n\n return await provider(providerInput);\n }\n}\n"],"names":["paginatedProviderPrisma","provider","input","limit","after","before","order","ServiceError","badRequestError","message","opts","orderBy","id","take","skip","cursorId","cursorType","cursor","Promise","resolve","then","items","orderedItems","cursorItem","find","item","undefined","cursorItemIndex","indexOf","orderedItemsWithoutCursor","concat","slice","selectedItems","length","hasItemsBefore","hasItemsAfter","pagination","hasNextPage","hasPreviousPage","e","reject","PREFIX","Cursor","type","this","fromString","str","startsWith","hint","decoded","base62","decode","_JSON$parse","JSON","parse","toString","Error","fromId","prototype","encode","stringify","Paginator","create","validate","inner","v","intersection","object","optional","number","modifiers","minValue","maxValue","string","enumOf","present","list","presenter","context","run","all","map","_presenter","_Promise$all","__typename","filter","Boolean","has_more_after","has_more_before","presentLight","_Promise$all2","_ref","_this$opts$defaultLim","_ref2","_input$order","_this","numberLimit","Number","isNaN","providerInput","Math","max","min","defaultLimit","defaultOrder","prisma"],"mappings":"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"}
package/dist/index.d.ts DELETED
@@ -1,4 +0,0 @@
1
- export * from './paginatedProvider';
2
- export * from './paginator';
3
- export * from './types';
4
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC"}
@@ -1,2 +0,0 @@
1
- let e=e=>!!/^(\d{1,3}\.){3}\d{1,3}$/.test(e)&&e.split(".").every(e=>{let r=parseInt(e,10);return r>=0&&r<=255}),r=e=>{if(e.includes("::")){let r=e.split("::");if(2!==r.length)return!1;if((r[0]?r[0].split(":").length:0)+(r[1]?r[1].split(":").length:0)>7)return!1}return/^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}$/.test(e)||"::"===e},t=(e,r={})=>{let{keepGroups:t=2,maskChar:s="x"}=r,n=e.split(".");if(t<1||t>3)throw new Error("keepGroups for IPv4 must be between 1 and 3");return n.map((e,r)=>r<t?e:s.repeat(e.length)).join(".")},s=(e,r,t)=>{let s=e;if(e.includes("::")){let r=e.split("::"),t=r[0]||"",n=r[1]||"",p=t?t.split(":"):[],l=n?n.split(":"):[],i=Array(8-p.length-l.length).fill("0");s=[...p,...i,...l].join(":")}return s.split(":").map((e,s)=>s<r?e:t.repeat(Math.max(1,e.length))).join(":")},n=(n,p={})=>{if(!n||"string"!=typeof n)throw new Error("IP address must be a non-empty string");let l=n.trim();var i,u;if(e(l))return t(l,{keepGroups:"number"==typeof p.keepGroups?p.keepGroups:null==(i=p.keepGroups)?void 0:i.ipv4,maskChar:p.maskChar}).replace("000","0");if((t=>{if(t.includes(".")){let s=t.split(":");if(e(s[s.length-1])){let e=t.substring(0,t.lastIndexOf(":")+1)+"0";return r(e)}}return r(t)})(l))return((r,n={})=>{let{keepGroups:p=4,maskChar:l="x"}=n;if(p<1||p>7)throw new Error("keepGroups for IPv6 must be between 1 and 7");if(r.includes(".")){let n=r.lastIndexOf(":"),i=r.substring(0,n+1),u=r.substring(n+1);if(e(u)){let e=t(u,{keepGroups:2,maskChar:l}),r=s(i+"0",p,l);return r.substring(0,r.lastIndexOf(":")+1)+e}}return s(r,p,l)})(l,{keepGroups:"number"==typeof p.keepGroups?p.keepGroups:null==(u=p.keepGroups)?void 0:u.ipv6,maskChar:p.maskChar});throw new Error("Invalid IP address format")};export{n as anonymizeIP};
2
- //# sourceMappingURL=index.modern.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.modern.js","sources":["../src/anonymizeIp.ts"],"sourcesContent":["interface AnonymizationOptionsSingle {\n // For IPv4: number of octets to keep (1-3, default: 2)\n // For IPv6: number of groups to keep (1-7, default: 4)\n keepGroups?: number;\n // Character to use for masking (default: 'x')\n maskChar?: string;\n}\n\ninterface AnonymizationOptions {\n maskChar?: string;\n keepGroups?:\n | {\n ipv4?: number;\n ipv6?: number;\n }\n | number;\n}\n\nlet isIPv4 = (ip: string) => {\n let ipv4Regex = /^(\\d{1,3}\\.){3}\\d{1,3}$/;\n if (!ipv4Regex.test(ip)) return false;\n\n return ip.split('.').every(octet => {\n let num = parseInt(octet, 10);\n return num >= 0 && num <= 255;\n });\n};\n\nlet isIPv6 = (ip: string) => {\n // Handle IPv6 with embedded IPv4 (e.g., ::ffff:192.0.2.1)\n if (ip.includes('.')) {\n let parts = ip.split(':');\n let lastPart = parts[parts.length - 1];\n if (isIPv4(lastPart)) {\n // Remove the IPv4 part and validate the IPv6 part\n let ipv6Part = ip.substring(0, ip.lastIndexOf(':') + 1) + '0';\n return isIPv6Simple(ipv6Part);\n }\n }\n\n return isIPv6Simple(ip);\n};\n\nlet isIPv6Simple = (ip: string) => {\n let ipv6Regex = /^([0-9a-fA-F]{0,4}:){1,7}[0-9a-fA-F]{0,4}$/;\n\n if (ip.includes('::')) {\n let parts = ip.split('::');\n if (parts.length !== 2) return false;\n\n let leftGroups = parts[0] ? parts[0].split(':').length : 0;\n let rightGroups = parts[1] ? parts[1].split(':').length : 0;\n\n // Total groups should not exceed 8\n if (leftGroups + rightGroups > 7) return false;\n }\n\n return ipv6Regex.test(ip) || ip === '::';\n};\n\nlet anonymizeIPv4 = (ip: string, options: AnonymizationOptionsSingle = {}) => {\n let { keepGroups = 2, maskChar = 'x' } = options;\n let octets = ip.split('.');\n\n if (keepGroups < 1 || keepGroups > 3) {\n throw new Error('keepGroups for IPv4 must be between 1 and 3');\n }\n\n let maskedOctets = octets.map((octet, index) => {\n if (index < keepGroups) {\n return octet;\n }\n return maskChar.repeat(octet.length);\n });\n\n return maskedOctets.join('.');\n};\n\nlet anonymizeIPv6 = (ip: string, options: AnonymizationOptionsSingle = {}) => {\n let { keepGroups = 4, maskChar = 'x' } = options;\n\n if (keepGroups < 1 || keepGroups > 7) {\n throw new Error('keepGroups for IPv6 must be between 1 and 7');\n }\n\n // Handle IPv6 with embedded IPv4\n if (ip.includes('.')) {\n let lastColonIndex = ip.lastIndexOf(':');\n let ipv6Part = ip.substring(0, lastColonIndex + 1);\n let ipv4Part = ip.substring(lastColonIndex + 1);\n\n if (isIPv4(ipv4Part)) {\n let anonymizedIPv4 = anonymizeIPv4(ipv4Part, { keepGroups: 2, maskChar });\n let anonymizedIPv6Part = anonymizeIPv6Simple(ipv6Part + '0', keepGroups, maskChar);\n return (\n anonymizedIPv6Part.substring(0, anonymizedIPv6Part.lastIndexOf(':') + 1) +\n anonymizedIPv4\n );\n }\n }\n\n return anonymizeIPv6Simple(ip, keepGroups, maskChar);\n};\n\nlet anonymizeIPv6Simple = (ip: string, keepGroups: number, maskChar: string) => {\n // Expand compressed notation for easier processing\n let expanded = ip;\n\n if (ip.includes('::')) {\n let parts = ip.split('::');\n let leftPart = parts[0] || '';\n let rightPart = parts[1] || '';\n\n let leftGroups = leftPart ? leftPart.split(':') : [];\n let rightGroups = rightPart ? rightPart.split(':') : [];\n\n let missingGroups = 8 - leftGroups.length - rightGroups.length;\n let zeroGroups = Array(missingGroups).fill('0');\n\n let allGroups = [...leftGroups, ...zeroGroups, ...rightGroups];\n expanded = allGroups.join(':');\n }\n\n let groups = expanded.split(':');\n\n let maskedGroups = groups.map((group, index) => {\n if (index < keepGroups) {\n return group;\n }\n return maskChar.repeat(Math.max(1, group.length));\n });\n\n return maskedGroups.join(':');\n};\n\nexport let anonymizeIP = (ip: string, options: AnonymizationOptions = {}) => {\n if (!ip || typeof ip !== 'string') {\n throw new Error('IP address must be a non-empty string');\n }\n\n let trimmedIP = ip.trim();\n\n if (isIPv4(trimmedIP)) {\n return anonymizeIPv4(trimmedIP, {\n keepGroups:\n typeof options.keepGroups === 'number' ? options.keepGroups : options.keepGroups?.ipv4,\n maskChar: options.maskChar\n }).replace('000', '0'); // Ensure no triple zeros in IPv4\n }\n\n if (isIPv6(trimmedIP)) {\n return anonymizeIPv6(trimmedIP, {\n keepGroups:\n typeof options.keepGroups === 'number' ? options.keepGroups : options.keepGroups?.ipv6,\n maskChar: options.maskChar\n });\n }\n\n throw new Error('Invalid IP address format');\n};\n"],"names":["isIPv4","ip","test","split","every","octet","num","parseInt","isIPv6Simple","includes","parts","length","anonymizeIPv4","options","keepGroups","maskChar","octets","Error","map","index","repeat","join","anonymizeIPv6Simple","expanded","leftPart","rightPart","leftGroups","rightGroups","zeroGroups","Array","fill","group","Math","max","anonymizeIP","trimmedIP","trim","_options$keepGroups","_options$keepGroups2","ipv4","replace","ipv6Part","substring","lastIndexOf","isIPv6","anonymizeIPv6","lastColonIndex","ipv4Part","anonymizedIPv4","anonymizedIPv6Part","ipv6"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import{ServiceError as r,badRequestError as e}from"@lowerdeck/error";import{v as t}from"@lowerdeck/validation";import{base62 as i}from"@lowerdeck/base62";var n=function(t){return function(i){try{var n=i.limit,o=i.after,a=i.before,s=i.order;if(o&&a)throw new r(e({message:"Cannot use both after and before cursors"}));var u={orderBy:[{id:s}],take:n+2,skip:0},l=null!=o?o:a,f="none";return o?(u.cursor={id:o},f="after"):a&&(u.cursor={id:a},u.take=-u.take,u.skip=0,f="before"),Promise.resolve(t(u)).then(function(r){var e=r,t=l?null==e?void 0:e.find(function(r){return r.id==l}):void 0,i=t?null==e?void 0:e.indexOf(t):void 0,o="number"==typeof i?[].concat(e.slice(0,i),e.slice(i+1)):e,a=null==o?void 0:o.slice(0,n);"before"==f&&o.length>n&&(a=null==o?void 0:o.slice(1,n+1));var s=!1,u=!1;return"after"==f||"none"==f?(o.length>a.length&&(u=!0),t&&(s=!0)):"before"==f&&(o.length>a.length&&(s=!0),t&&(u=!0)),{items:a,pagination:{hasNextPage:u,hasPreviousPage:s}}})}catch(r){return Promise.reject(r)}}},o="cur_",a=/*#__PURE__*/function(){function t(r,e){this.id=void 0,this.type=void 0,this.id=r,this.type=e}return t.fromString=function(n){if(!n.startsWith(o))throw new r(e({message:"Invalid cursor format",hint:'Cursor must start with "cur_"'}));try{var a=i.decode(n.slice(4)),s=JSON.parse(a.toString()),u=s[0],l=s[1];if("after"!==u&&"before"!==u)throw new Error("Invalid cursor type");if("string"!=typeof l)throw new Error("Invalid cursor id");return new t(l,u)}catch(t){throw new r(e({message:"Invalid cursor format",hint:"Please provide a valid cursor from another page."}))}},t.fromId=function(r,e){return new t(r,e)},t.prototype.toString=function(){return o+i.encode(JSON.stringify([this.type,this.id]))},t}(),s=/*#__PURE__*/function(){function r(r,e){void 0===e&&(e={}),this.provider=void 0,this.opts=void 0,this.provider=r,this.opts=e}return r.create=function(e,t){return void 0===t&&(t={}),new r(e,t)},r.validate=function(r){return t.intersection([t.object({limit:t.optional(t.number({modifiers:[t.minValue(1),t.maxValue(100)]})),after:t.optional(t.string()),before:t.optional(t.string()),cursor:t.optional(t.string()),order:t.optional(t.enumOf(["asc","desc"]))}),null!=r?r:t.object({})])},r.present=function(r,e){return function(t){return{run:function(){try{return Promise.resolve(Promise.all(r.items.map(function(r){var i;return null==(i=e(r))||null==(i=i(t))?void 0:i.run({})}))).then(function(e){return{__typename:"list",items:e.filter(Boolean),pagination:{has_more_after:r.pagination.hasNextPage,has_more_before:r.pagination.hasPreviousPage}}})}catch(r){return Promise.reject(r)}}}}},r.presentLight=function(r,e){try{return Promise.resolve(Promise.all(r.items.map(function(r){return e(r)}))).then(function(e){return{__typename:"list",items:e.filter(Boolean),pagination:{has_more_after:r.pagination.hasNextPage,has_more_before:r.pagination.hasPreviousPage}}})}catch(r){return Promise.reject(r)}},r.prototype.run=function(r){try{var e,t,i,o,s=this,u=Number(r.limit);isNaN(u)&&(u=20);var l={limit:Math.max(Math.min(null!=(e=null!=u?u:s.opts.defaultLimit)?e:20,null!=(t=s.opts.defaultLimit)?t:100),1),order:null!=(i=null!=(o=r.order)?o:s.opts.defaultOrder)?i:"asc"};if(r.after)l.after=r.after;else if(r.before)l.before=r.before;else if(r.cursor){var f=a.fromString(r.cursor);l[f.type]=f.id}var c=s.provider({prisma:n});return Promise.resolve(c(l))}catch(r){return Promise.reject(r)}},r}();export{s as Paginator,n as paginatedProviderPrisma};
2
- //# sourceMappingURL=index.module.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.module.js","sources":["../src/paginatedProvider.ts","../src/cursor.ts","../src/paginator.ts"],"sourcesContent":["import { ServiceError, badRequestError } from '@lowerdeck/error';\nimport { PaginatedList } from './types';\n\nexport interface PaginatedProviderInput {\n limit: number;\n after?: string;\n before?: string;\n order: 'asc' | 'desc';\n}\n\nexport interface PrismaPaginationOpts {\n orderBy: [{ id: 'asc' | 'desc' }];\n cursor?: { id: string };\n take: number;\n skip: number;\n}\n\nexport type PaginatedProvider<T> = (\n input: PaginatedProviderInput\n) => Promise<PaginatedList<T>>;\n\nexport let paginatedProviderPrisma =\n <T extends { id: string }>(\n provider: (opts: PrismaPaginationOpts) => Promise<T[] | null | undefined>\n ): PaginatedProvider<T> =>\n async (input: PaginatedProviderInput) => {\n let { limit, after, before, order } = input;\n\n if (after && before) {\n throw new ServiceError(\n badRequestError({\n message: 'Cannot use both after and before cursors'\n })\n );\n }\n\n let opts: PrismaPaginationOpts = {\n orderBy: [{ id: order }],\n take: limit + 2,\n skip: 0\n };\n\n let cursorId = after ?? before;\n let cursorType: 'after' | 'before' | 'none' = 'none';\n\n if (after) {\n opts.cursor = { id: after };\n cursorType = 'after';\n } else if (before) {\n opts.cursor = { id: before };\n opts.take = -opts.take!;\n opts.skip = 0;\n cursorType = 'before';\n }\n\n let items = (await provider(opts)) ?? [];\n\n let orderedItems = items; /* items?.sort((a, b) => {\n if (order == 'asc') {\n return a.id.localeCompare(b.id);\n } else {\n return b.id.localeCompare(a.id);\n }\n });*/\n\n let cursorItem = cursorId ? orderedItems?.find(item => item.id == cursorId) : undefined;\n let cursorItemIndex = cursorItem ? orderedItems?.indexOf(cursorItem) : undefined;\n let orderedItemsWithoutCursor =\n typeof cursorItemIndex == 'number'\n ? [\n ...orderedItems.slice(0, cursorItemIndex),\n ...orderedItems.slice(cursorItemIndex + 1)\n ]\n : orderedItems;\n\n let selectedItems = orderedItemsWithoutCursor?.slice(0, limit);\n\n if (cursorType == 'before' && orderedItemsWithoutCursor.length > limit) {\n selectedItems = orderedItemsWithoutCursor?.slice(1, limit + 1);\n }\n\n let hasItemsBefore = false;\n let hasItemsAfter = false;\n\n if (cursorType == 'after' || cursorType == 'none') {\n if (orderedItemsWithoutCursor.length > selectedItems.length) hasItemsAfter = true;\n if (cursorItem) hasItemsBefore = true;\n } else if (cursorType == 'before') {\n if (orderedItemsWithoutCursor.length > selectedItems.length) hasItemsBefore = true;\n if (cursorItem) hasItemsAfter = true;\n }\n\n return {\n items: selectedItems,\n pagination: {\n hasNextPage: hasItemsAfter,\n hasPreviousPage: hasItemsBefore\n }\n };\n };\n","import { base62 } from '@lowerdeck/base62';\nimport { badRequestError, ServiceError } from '@lowerdeck/error';\n\nlet PREFIX = 'cur_';\n\nexport class Cursor {\n private constructor(\n public readonly id: string,\n public readonly type: 'after' | 'before'\n ) {}\n\n static fromString(str: string) {\n if (!str.startsWith(PREFIX)) {\n throw new ServiceError(\n badRequestError({\n message: 'Invalid cursor format',\n hint: 'Cursor must start with \"cur_\"'\n })\n );\n }\n\n try {\n let decoded = base62.decode(str.slice(PREFIX.length));\n let [type, id] = JSON.parse(decoded.toString());\n\n if (type !== 'after' && type !== 'before') {\n throw new Error('Invalid cursor type');\n }\n\n if (typeof id !== 'string') {\n throw new Error('Invalid cursor id');\n }\n\n return new Cursor(id, type);\n } catch (e) {\n throw new ServiceError(\n badRequestError({\n message: 'Invalid cursor format',\n hint: 'Please provide a valid cursor from another page.'\n })\n );\n }\n }\n\n static fromId(id: string, type: 'after' | 'before') {\n return new Cursor(id, type);\n }\n\n toString() {\n return PREFIX + base62.encode(JSON.stringify([this.type, this.id]));\n }\n}\n","import { v, ValidationType } from '@lowerdeck/validation';\nimport { Cursor } from './cursor';\nimport {\n PaginatedProvider,\n PaginatedProviderInput,\n paginatedProviderPrisma\n} from './paginatedProvider';\nimport { PaginatedList } from './types';\n\nexport interface PaginatorInput {\n limit?: number | string;\n after?: string;\n before?: string;\n cursor?: string;\n order?: 'asc' | 'desc';\n}\n\nexport interface PaginatorOpts {\n defaultLimit?: number;\n defaultOrder?: 'asc' | 'desc';\n}\n\nexport type Provider<T> = (providers: {\n prisma: typeof paginatedProviderPrisma;\n}) => PaginatedProvider<T>;\n\nexport class Paginator<T> {\n private constructor(\n private provider: Provider<T>,\n private opts: PaginatorOpts = {}\n ) {}\n\n static create<T>(provider: Provider<T>, opts: PaginatorOpts = {}) {\n return new Paginator(provider, opts);\n }\n\n static validate<Inner extends object>(inner?: ValidationType<Inner>) {\n return v.intersection([\n v.object({\n limit: v.optional(\n v.number({\n modifiers: [v.minValue(1), v.maxValue(100)]\n })\n ),\n after: v.optional(v.string()),\n before: v.optional(v.string()),\n cursor: v.optional(v.string()),\n order: v.optional(v.enumOf(['asc', 'desc']))\n }),\n inner ?? v.object({})\n ]) as ValidationType<\n Inner & {\n limit?: number;\n after?: string;\n before?: string;\n cursor?: string;\n order?: 'asc' | 'desc';\n }\n >;\n }\n\n static present<T, R>(\n list: PaginatedList<T>,\n presenter: (item: T) => (context: any) => { run: (d: any) => R } | undefined\n ) {\n return (context: any) => ({\n run: async () => ({\n __typename: `list`,\n items: (\n await Promise.all(list.items.map(item => presenter(item)?.(context)?.run({})))\n ).filter(Boolean),\n pagination: {\n has_more_after: list.pagination.hasNextPage,\n has_more_before: list.pagination.hasPreviousPage\n }\n })\n });\n }\n\n static async presentLight<T, R>(\n list: PaginatedList<T>,\n presenter: (item: T) => R | Promise<R>\n ) {\n return {\n __typename: `list`,\n items: (await Promise.all(list.items.map(item => presenter(item)))).filter(Boolean),\n pagination: {\n has_more_after: list.pagination.hasNextPage,\n has_more_before: list.pagination.hasPreviousPage\n }\n };\n }\n\n async run(input: PaginatorInput): Promise<PaginatedList<T>> {\n let numberLimit = Number(input.limit);\n if (isNaN(numberLimit)) numberLimit = 20;\n\n let providerInput: PaginatedProviderInput = {\n limit: Math.max(\n Math.min(numberLimit ?? this.opts.defaultLimit ?? 20, this.opts.defaultLimit ?? 100),\n 1\n ),\n order: input.order ?? this.opts.defaultOrder ?? 'asc'\n };\n\n if (input.after) {\n providerInput.after = input.after;\n } else if (input.before) {\n providerInput.before = input.before;\n } else if (input.cursor) {\n let cursor = Cursor.fromString(input.cursor);\n providerInput[cursor.type] = cursor.id;\n }\n\n let provider = this.provider({\n prisma: paginatedProviderPrisma\n });\n\n return await provider(providerInput);\n }\n}\n"],"names":["paginatedProviderPrisma","provider","input","limit","after","before","order","ServiceError","badRequestError","message","opts","orderBy","id","take","skip","cursorId","cursorType","cursor","Promise","resolve","then","items","orderedItems","cursorItem","find","item","undefined","cursorItemIndex","indexOf","orderedItemsWithoutCursor","concat","slice","selectedItems","length","hasItemsBefore","hasItemsAfter","pagination","hasNextPage","hasPreviousPage","e","reject","PREFIX","Cursor","type","this","fromString","str","startsWith","hint","decoded","base62","decode","_JSON$parse","JSON","parse","toString","Error","fromId","prototype","encode","stringify","Paginator","create","validate","inner","v","intersection","object","optional","number","modifiers","minValue","maxValue","string","enumOf","present","list","presenter","context","run","all","map","_presenter","_Promise$all","__typename","filter","Boolean","has_more_after","has_more_before","presentLight","_Promise$all2","_ref","_this$opts$defaultLim","_ref2","_input$order","_this","numberLimit","Number","isNaN","providerInput","Math","max","min","defaultLimit","defaultOrder","prisma"],"mappings":"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"}
package/dist/index.umd.js DELETED
@@ -1,2 +0,0 @@
1
- !function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("@lowerdeck/error"),require("@lowerdeck/validation"),require("@lowerdeck/base62")):"function"==typeof define&&define.amd?define(["exports","@lowerdeck/error","@lowerdeck/validation","@lowerdeck/base62"],r):r((e||self).pagination={},e.error,e.validation,e.base62)}(this,function(e,r,t,i){var o=function(e){return function(t){try{var i=t.limit,o=t.after,n=t.before,a=t.order;if(o&&n)throw new r.ServiceError(r.badRequestError({message:"Cannot use both after and before cursors"}));var s={orderBy:[{id:a}],take:i+2,skip:0},u=null!=o?o:n,l="none";return o?(s.cursor={id:o},l="after"):n&&(s.cursor={id:n},s.take=-s.take,s.skip=0,l="before"),Promise.resolve(e(s)).then(function(e){var r=e,t=u?null==r?void 0:r.find(function(e){return e.id==u}):void 0,o=t?null==r?void 0:r.indexOf(t):void 0,n="number"==typeof o?[].concat(r.slice(0,o),r.slice(o+1)):r,a=null==n?void 0:n.slice(0,i);"before"==l&&n.length>i&&(a=null==n?void 0:n.slice(1,i+1));var s=!1,f=!1;return"after"==l||"none"==l?(n.length>a.length&&(f=!0),t&&(s=!0)):"before"==l&&(n.length>a.length&&(s=!0),t&&(f=!0)),{items:a,pagination:{hasNextPage:f,hasPreviousPage:s}}})}catch(e){return Promise.reject(e)}}},n="cur_",a=/*#__PURE__*/function(){function e(e,r){this.id=void 0,this.type=void 0,this.id=e,this.type=r}return e.fromString=function(t){if(!t.startsWith(n))throw new r.ServiceError(r.badRequestError({message:"Invalid cursor format",hint:'Cursor must start with "cur_"'}));try{var o=i.base62.decode(t.slice(4)),a=JSON.parse(o.toString()),s=a[0],u=a[1];if("after"!==s&&"before"!==s)throw new Error("Invalid cursor type");if("string"!=typeof u)throw new Error("Invalid cursor id");return new e(u,s)}catch(e){throw new r.ServiceError(r.badRequestError({message:"Invalid cursor format",hint:"Please provide a valid cursor from another page."}))}},e.fromId=function(r,t){return new e(r,t)},e.prototype.toString=function(){return n+i.base62.encode(JSON.stringify([this.type,this.id]))},e}();e.Paginator=/*#__PURE__*/function(){function e(e,r){void 0===r&&(r={}),this.provider=void 0,this.opts=void 0,this.provider=e,this.opts=r}return e.create=function(r,t){return void 0===t&&(t={}),new e(r,t)},e.validate=function(e){return t.v.intersection([t.v.object({limit:t.v.optional(t.v.number({modifiers:[t.v.minValue(1),t.v.maxValue(100)]})),after:t.v.optional(t.v.string()),before:t.v.optional(t.v.string()),cursor:t.v.optional(t.v.string()),order:t.v.optional(t.v.enumOf(["asc","desc"]))}),null!=e?e:t.v.object({})])},e.present=function(e,r){return function(t){return{run:function(){try{return Promise.resolve(Promise.all(e.items.map(function(e){var i;return null==(i=r(e))||null==(i=i(t))?void 0:i.run({})}))).then(function(r){return{__typename:"list",items:r.filter(Boolean),pagination:{has_more_after:e.pagination.hasNextPage,has_more_before:e.pagination.hasPreviousPage}}})}catch(e){return Promise.reject(e)}}}}},e.presentLight=function(e,r){try{return Promise.resolve(Promise.all(e.items.map(function(e){return r(e)}))).then(function(r){return{__typename:"list",items:r.filter(Boolean),pagination:{has_more_after:e.pagination.hasNextPage,has_more_before:e.pagination.hasPreviousPage}}})}catch(e){return Promise.reject(e)}},e.prototype.run=function(e){try{var r,t,i,n,s=this,u=Number(e.limit);isNaN(u)&&(u=20);var l={limit:Math.max(Math.min(null!=(r=null!=u?u:s.opts.defaultLimit)?r:20,null!=(t=s.opts.defaultLimit)?t:100),1),order:null!=(i=null!=(n=e.order)?n:s.opts.defaultOrder)?i:"asc"};if(e.after)l.after=e.after;else if(e.before)l.before=e.before;else if(e.cursor){var f=a.fromString(e.cursor);l[f.type]=f.id}var c=s.provider({prisma:o});return Promise.resolve(c(l))}catch(e){return Promise.reject(e)}},e}(),e.paginatedProviderPrisma=o});
2
- //# sourceMappingURL=index.umd.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.umd.js","sources":["../src/paginatedProvider.ts","../src/cursor.ts","../src/paginator.ts"],"sourcesContent":["import { ServiceError, badRequestError } from '@lowerdeck/error';\nimport { PaginatedList } from './types';\n\nexport interface PaginatedProviderInput {\n limit: number;\n after?: string;\n before?: string;\n order: 'asc' | 'desc';\n}\n\nexport interface PrismaPaginationOpts {\n orderBy: [{ id: 'asc' | 'desc' }];\n cursor?: { id: string };\n take: number;\n skip: number;\n}\n\nexport type PaginatedProvider<T> = (\n input: PaginatedProviderInput\n) => Promise<PaginatedList<T>>;\n\nexport let paginatedProviderPrisma =\n <T extends { id: string }>(\n provider: (opts: PrismaPaginationOpts) => Promise<T[] | null | undefined>\n ): PaginatedProvider<T> =>\n async (input: PaginatedProviderInput) => {\n let { limit, after, before, order } = input;\n\n if (after && before) {\n throw new ServiceError(\n badRequestError({\n message: 'Cannot use both after and before cursors'\n })\n );\n }\n\n let opts: PrismaPaginationOpts = {\n orderBy: [{ id: order }],\n take: limit + 2,\n skip: 0\n };\n\n let cursorId = after ?? before;\n let cursorType: 'after' | 'before' | 'none' = 'none';\n\n if (after) {\n opts.cursor = { id: after };\n cursorType = 'after';\n } else if (before) {\n opts.cursor = { id: before };\n opts.take = -opts.take!;\n opts.skip = 0;\n cursorType = 'before';\n }\n\n let items = (await provider(opts)) ?? [];\n\n let orderedItems = items; /* items?.sort((a, b) => {\n if (order == 'asc') {\n return a.id.localeCompare(b.id);\n } else {\n return b.id.localeCompare(a.id);\n }\n });*/\n\n let cursorItem = cursorId ? orderedItems?.find(item => item.id == cursorId) : undefined;\n let cursorItemIndex = cursorItem ? orderedItems?.indexOf(cursorItem) : undefined;\n let orderedItemsWithoutCursor =\n typeof cursorItemIndex == 'number'\n ? [\n ...orderedItems.slice(0, cursorItemIndex),\n ...orderedItems.slice(cursorItemIndex + 1)\n ]\n : orderedItems;\n\n let selectedItems = orderedItemsWithoutCursor?.slice(0, limit);\n\n if (cursorType == 'before' && orderedItemsWithoutCursor.length > limit) {\n selectedItems = orderedItemsWithoutCursor?.slice(1, limit + 1);\n }\n\n let hasItemsBefore = false;\n let hasItemsAfter = false;\n\n if (cursorType == 'after' || cursorType == 'none') {\n if (orderedItemsWithoutCursor.length > selectedItems.length) hasItemsAfter = true;\n if (cursorItem) hasItemsBefore = true;\n } else if (cursorType == 'before') {\n if (orderedItemsWithoutCursor.length > selectedItems.length) hasItemsBefore = true;\n if (cursorItem) hasItemsAfter = true;\n }\n\n return {\n items: selectedItems,\n pagination: {\n hasNextPage: hasItemsAfter,\n hasPreviousPage: hasItemsBefore\n }\n };\n };\n","import { base62 } from '@lowerdeck/base62';\nimport { badRequestError, ServiceError } from '@lowerdeck/error';\n\nlet PREFIX = 'cur_';\n\nexport class Cursor {\n private constructor(\n public readonly id: string,\n public readonly type: 'after' | 'before'\n ) {}\n\n static fromString(str: string) {\n if (!str.startsWith(PREFIX)) {\n throw new ServiceError(\n badRequestError({\n message: 'Invalid cursor format',\n hint: 'Cursor must start with \"cur_\"'\n })\n );\n }\n\n try {\n let decoded = base62.decode(str.slice(PREFIX.length));\n let [type, id] = JSON.parse(decoded.toString());\n\n if (type !== 'after' && type !== 'before') {\n throw new Error('Invalid cursor type');\n }\n\n if (typeof id !== 'string') {\n throw new Error('Invalid cursor id');\n }\n\n return new Cursor(id, type);\n } catch (e) {\n throw new ServiceError(\n badRequestError({\n message: 'Invalid cursor format',\n hint: 'Please provide a valid cursor from another page.'\n })\n );\n }\n }\n\n static fromId(id: string, type: 'after' | 'before') {\n return new Cursor(id, type);\n }\n\n toString() {\n return PREFIX + base62.encode(JSON.stringify([this.type, this.id]));\n }\n}\n","import { v, ValidationType } from '@lowerdeck/validation';\nimport { Cursor } from './cursor';\nimport {\n PaginatedProvider,\n PaginatedProviderInput,\n paginatedProviderPrisma\n} from './paginatedProvider';\nimport { PaginatedList } from './types';\n\nexport interface PaginatorInput {\n limit?: number | string;\n after?: string;\n before?: string;\n cursor?: string;\n order?: 'asc' | 'desc';\n}\n\nexport interface PaginatorOpts {\n defaultLimit?: number;\n defaultOrder?: 'asc' | 'desc';\n}\n\nexport type Provider<T> = (providers: {\n prisma: typeof paginatedProviderPrisma;\n}) => PaginatedProvider<T>;\n\nexport class Paginator<T> {\n private constructor(\n private provider: Provider<T>,\n private opts: PaginatorOpts = {}\n ) {}\n\n static create<T>(provider: Provider<T>, opts: PaginatorOpts = {}) {\n return new Paginator(provider, opts);\n }\n\n static validate<Inner extends object>(inner?: ValidationType<Inner>) {\n return v.intersection([\n v.object({\n limit: v.optional(\n v.number({\n modifiers: [v.minValue(1), v.maxValue(100)]\n })\n ),\n after: v.optional(v.string()),\n before: v.optional(v.string()),\n cursor: v.optional(v.string()),\n order: v.optional(v.enumOf(['asc', 'desc']))\n }),\n inner ?? v.object({})\n ]) as ValidationType<\n Inner & {\n limit?: number;\n after?: string;\n before?: string;\n cursor?: string;\n order?: 'asc' | 'desc';\n }\n >;\n }\n\n static present<T, R>(\n list: PaginatedList<T>,\n presenter: (item: T) => (context: any) => { run: (d: any) => R } | undefined\n ) {\n return (context: any) => ({\n run: async () => ({\n __typename: `list`,\n items: (\n await Promise.all(list.items.map(item => presenter(item)?.(context)?.run({})))\n ).filter(Boolean),\n pagination: {\n has_more_after: list.pagination.hasNextPage,\n has_more_before: list.pagination.hasPreviousPage\n }\n })\n });\n }\n\n static async presentLight<T, R>(\n list: PaginatedList<T>,\n presenter: (item: T) => R | Promise<R>\n ) {\n return {\n __typename: `list`,\n items: (await Promise.all(list.items.map(item => presenter(item)))).filter(Boolean),\n pagination: {\n has_more_after: list.pagination.hasNextPage,\n has_more_before: list.pagination.hasPreviousPage\n }\n };\n }\n\n async run(input: PaginatorInput): Promise<PaginatedList<T>> {\n let numberLimit = Number(input.limit);\n if (isNaN(numberLimit)) numberLimit = 20;\n\n let providerInput: PaginatedProviderInput = {\n limit: Math.max(\n Math.min(numberLimit ?? this.opts.defaultLimit ?? 20, this.opts.defaultLimit ?? 100),\n 1\n ),\n order: input.order ?? this.opts.defaultOrder ?? 'asc'\n };\n\n if (input.after) {\n providerInput.after = input.after;\n } else if (input.before) {\n providerInput.before = input.before;\n } else if (input.cursor) {\n let cursor = Cursor.fromString(input.cursor);\n providerInput[cursor.type] = cursor.id;\n }\n\n let provider = this.provider({\n prisma: paginatedProviderPrisma\n });\n\n return await provider(providerInput);\n }\n}\n"],"names":["paginatedProviderPrisma","provider","input","limit","after","before","order","ServiceError","badRequestError","message","opts","orderBy","id","take","skip","cursorId","cursorType","cursor","Promise","resolve","then","items","orderedItems","cursorItem","find","item","undefined","cursorItemIndex","indexOf","orderedItemsWithoutCursor","concat","slice","selectedItems","length","hasItemsBefore","hasItemsAfter","pagination","hasNextPage","hasPreviousPage","e","reject","PREFIX","Cursor","type","this","fromString","str","startsWith","hint","decoded","base62","decode","_JSON$parse","JSON","parse","toString","Error","fromId","prototype","encode","stringify","Paginator","create","validate","inner","v","intersection","object","optional","number","modifiers","minValue","maxValue","string","enumOf","present","list","presenter","context","run","all","map","_presenter","_Promise$all","__typename","filter","Boolean","has_more_after","has_more_before","presentLight","_Promise$all2","_ref","_this$opts$defaultLim","_ref2","_input$order","_this","numberLimit","Number","isNaN","providerInput","Math","max","min","defaultLimit","defaultOrder","prisma"],"mappings":"iaAqBWA,IAAAA,EACT,SACEC,mBAEKC,GAA6B,IAClC,IAAMC,EAAgCD,EAAhCC,MAAOC,EAAyBF,EAAzBE,MAAOC,EAAkBH,EAAlBG,OAAQC,EAAUJ,EAAVI,MAE5B,GAAIF,GAASC,EACX,UAAUE,EAAAA,aACRC,EAAeA,gBAAC,CACdC,QAAS,8CAKf,IAAIC,EAA6B,CAC/BC,QAAS,CAAC,CAAEC,GAAIN,IAChBO,KAAMV,EAAQ,EACdW,KAAM,GAGJC,EAAWX,MAAAA,EAAAA,EAASC,EACpBW,EAA0C,OAU7C,OARGZ,GACFM,EAAKO,OAAS,CAAEL,GAAIR,GACpBY,EAAa,SACJX,IACTK,EAAKO,OAAS,CAAEL,GAAIP,GACpBK,EAAKG,MAAQH,EAAKG,KAClBH,EAAKI,KAAO,EACZE,EAAa,UACdE,QAAAC,QAEkBlB,EAASS,IAAKU,KAA7BC,SAAAA,GAEJ,IAAIC,EAAeD,EAQfE,EAAaR,EAAuB,MAAZO,OAAY,EAAZA,EAAcE,KAAK,SAAAC,GAAI,OAAIA,EAAKb,IAAMG,CAAQ,QAAIW,EAC1EC,EAAkBJ,EAAyB,MAAZD,OAAY,EAAZA,EAAcM,QAAQL,QAAcG,EACnEG,EACwB,iBAAnBF,KAA2BG,OAEzBR,EAAaS,MAAM,EAAGJ,GACtBL,EAAaS,MAAMJ,EAAkB,IAE1CL,EAEFU,QAAgBH,SAAAA,EAA2BE,MAAM,EAAG5B,GAEtC,UAAda,GAA0Ba,EAA0BI,OAAS9B,IAC/D6B,QAAgBH,SAAAA,EAA2BE,MAAM,EAAG5B,EAAQ,IAG9D,IAAI+B,GAAiB,EACjBC,GAAgB,EAUpB,MARkB,SAAdnB,GAAuC,QAAdA,GACvBa,EAA0BI,OAASD,EAAcC,SAAQE,GAAgB,GACzEZ,IAAYW,GAAiB,IACV,UAAdlB,IACLa,EAA0BI,OAASD,EAAcC,SAAQC,GAAiB,GAC1EX,IAAYY,GAAgB,IAG3B,CACLd,MAAOW,EACPI,WAAY,CACVC,YAAaF,EACbG,gBAAiBJ,GAEnB,EACJ,CAAC,MAAAK,UAAArB,QAAAsB,OAAAD,EAAA,CAAA,CAAA,EChGCE,EAAS,OAEAC,eACX,WAAA,SAAAA,EACkB9B,EACA+B,GAAwBC,KADxBhC,QAAA,EAAAgC,KACAD,UAAA,EADAC,KAAEhC,GAAFA,EACAgC,KAAID,KAAJA,CACf,QAACD,EAEGG,WAAP,SAAkBC,GAChB,IAAKA,EAAIC,WAAWN,GAClB,MAAM,IAAIlC,EAAAA,aACRC,EAAAA,gBAAgB,CACdC,QAAS,wBACTuC,KAAM,mCAKZ,IACE,IAAIC,EAAUC,EAAMA,OAACC,OAAOL,EAAIf,MAAMU,IACtCW,EAAiBC,KAAKC,MAAML,EAAQM,YAA/BZ,EAAIS,EAAA,GAAExC,EAAEwC,EAAA,GAEb,GAAa,UAATT,GAA6B,WAATA,EACtB,MAAU,IAAAa,MAAM,uBAGlB,GAAkB,iBAAP5C,EACT,MAAU,IAAA4C,MAAM,qBAGlB,OAAO,IAAId,EAAO9B,EAAI+B,EACxB,CAAE,MAAOJ,GACP,MAAM,IAAIhC,EAAYA,aACpBC,EAAeA,gBAAC,CACdC,QAAS,wBACTuC,KAAM,qDAGZ,CACF,EAACN,EAEMe,OAAP,SAAc7C,EAAY+B,GACxB,OAAW,IAAAD,EAAO9B,EAAI+B,EACxB,EAACD,EAAAgB,UAEDH,SAAA,WACE,OAAOd,EAASS,EAAAA,OAAOS,OAAON,KAAKO,UAAU,CAAChB,KAAKD,KAAMC,KAAKhC,KAChE,EAAC8B,CAAA,CA5CD,4BCqBA,WAAA,SAAAmB,EACU5D,EACAS,QAAA,IAAAA,IAAAA,EAAsB,IAAEkC,KADxB3C,cAAA,EAAA2C,KACAlC,UADA,EAAAkC,KAAQ3C,SAARA,EACA2C,KAAIlC,KAAJA,CACP,QAACmD,EAEGC,OAAP,SAAiB7D,EAAuBS,GACtC,YADsCA,IAAAA,IAAAA,EAAsB,CAAA,OACjDmD,EAAU5D,EAAUS,EACjC,EAACmD,EAEME,SAAP,SAAsCC,GACpC,OAAOC,IAAEC,aAAa,CACpBD,IAAEE,OAAO,CACPhE,MAAO8D,EAACA,EAACG,SACPH,IAAEI,OAAO,CACPC,UAAW,CAACL,EAAAA,EAAEM,SAAS,GAAIN,EAACA,EAACO,SAAS,SAG1CpE,MAAO6D,IAAEG,SAASH,EAAAA,EAAEQ,UACpBpE,OAAQ4D,EAACA,EAACG,SAASH,IAAEQ,UACrBxD,OAAQgD,EAAAA,EAAEG,SAASH,EAACA,EAACQ,UACrBnE,MAAO2D,EAACA,EAACG,SAASH,EAAAA,EAAES,OAAO,CAAC,MAAO,YAEhC,MAALV,EAAAA,EAASC,EAACA,EAACE,OAAO,CAAA,IAUtB,EAACN,EAEMc,QAAP,SACEC,EACAC,GAEA,gBAAQC,GAAY,MAAM,CACxBC,eAAG,IAAA,OAAA7D,QAAAC,QAGOD,QAAQ8D,IAAIJ,EAAKvD,MAAM4D,IAAI,SAAAxD,GAAI,IAAAyD,EAAA,OAAmBA,OAAnBA,EAAIL,EAAUpD,KAAVyD,OAAeA,EAAfA,EAAkBJ,SAAlBI,EAAAA,EAA4BH,IAAI,GAAG,KAAE3D,cAAA+D,GAAA,MAHhE,CAChBC,WADC,OAED/D,MAAO8D,EAELE,OAAOC,SACTlD,WAAY,CACVmD,eAAgBX,EAAKxC,WAAWC,YAChCmD,gBAAiBZ,EAAKxC,WAAWE,iBAEpC,EAAA,CAAA,MAAAC,GAAA,OAAArB,QAAAsB,OAAAD,EACF,CAAA,EAAA,CACH,EAACsB,EAEY4B,aAAY,SACvBb,EACAC,GAAsC,IAAA,OAAA3D,QAAAC,QAItBD,QAAQ8D,IAAIJ,EAAKvD,MAAM4D,IAAI,SAAAxD,GAAQ,OAAAoD,EAAUpD,EAAK,KAAEL,KAAAsE,SAAAA,GAFpE,MAAO,CACLN,WAHoC,OAIpC/D,MAAOqE,EAA6DL,OAAOC,SAC3ElD,WAAY,CACVmD,eAAgBX,EAAKxC,WAAWC,YAChCmD,gBAAiBZ,EAAKxC,WAAWE,iBAEnC,EACJ,CAAC,MAAAC,GAAA,OAAArB,QAAAsB,OAAAD,KAAAsB,EAAAH,UAEKqB,aAAI7E,OAAqByF,IAAAA,EAAAC,EAAAC,EAAAC,EAAAC,EAMDnD,KALxBoD,EAAcC,OAAO/F,EAAMC,OAC3B+F,MAAMF,KAAcA,EAAc,IAEtC,IAAIG,EAAwC,CAC1ChG,MAAOiG,KAAKC,IACVD,KAAKE,IAAyC,OAAtCX,EAAY,MAAXK,EAAAA,EAAeD,EAAKrF,KAAK6F,cAAYZ,EAAI,GAA0B,OAAxBC,EAAEG,EAAKrF,KAAK6F,cAAYX,EAAI,KAChF,GAEFtF,aAAKuF,EAAa,OAAbC,EAAE5F,EAAMI,OAAKwF,EAAIC,EAAKrF,KAAK8F,cAAYX,EAAI,OAGlD,GAAI3F,EAAME,MACR+F,EAAc/F,MAAQF,EAAME,WACnBF,GAAAA,EAAMG,OACf8F,EAAc9F,OAASH,EAAMG,YACpBH,GAAAA,EAAMe,OAAQ,CACvB,IAAIA,EAASyB,EAAOG,WAAW3C,EAAMe,QACrCkF,EAAclF,EAAO0B,MAAQ1B,EAAOL,EACtC,CAEA,IAAIX,EAAW8F,EAAK9F,SAAS,CAC3BwG,OAAQzG,IACP,OAAAkB,QAAAC,QAEUlB,EAASkG,GACxB,CAAC,MAAA5D,GAAA,OAAArB,QAAAsB,OAAAD,KAAAsB,CAAA,CA5FD"}
@@ -1,22 +0,0 @@
1
- import { PaginatedList } from './types';
2
- export interface PaginatedProviderInput {
3
- limit: number;
4
- after?: string;
5
- before?: string;
6
- order: 'asc' | 'desc';
7
- }
8
- export interface PrismaPaginationOpts {
9
- orderBy: [{
10
- id: 'asc' | 'desc';
11
- }];
12
- cursor?: {
13
- id: string;
14
- };
15
- take: number;
16
- skip: number;
17
- }
18
- export type PaginatedProvider<T> = (input: PaginatedProviderInput) => Promise<PaginatedList<T>>;
19
- export declare let paginatedProviderPrisma: <T extends {
20
- id: string;
21
- }>(provider: (opts: PrismaPaginationOpts) => Promise<T[] | null | undefined>) => PaginatedProvider<T>;
22
- //# sourceMappingURL=paginatedProvider.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"paginatedProvider.d.ts","sourceRoot":"","sources":["../src/paginatedProvider.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAExC,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,CAAC;QAAE,EAAE,EAAE,KAAK,GAAG,MAAM,CAAA;KAAE,CAAC,CAAC;IAClC,MAAM,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,iBAAiB,CAAC,CAAC,IAAI,CACjC,KAAK,EAAE,sBAAsB,KAC1B,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AAE/B,eAAO,IAAI,uBAAuB,GAC/B,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACvB,UAAU,CAAC,IAAI,EAAE,oBAAoB,KAAK,OAAO,CAAC,CAAC,EAAE,GAAG,IAAI,GAAG,SAAS,CAAC,KACxE,iBAAiB,CAAC,CAAC,CA2ErB,CAAC"}
@@ -1,52 +0,0 @@
1
- import { ValidationType } from '@lowerdeck/validation';
2
- import { PaginatedProvider, paginatedProviderPrisma } from './paginatedProvider';
3
- import { PaginatedList } from './types';
4
- export interface PaginatorInput {
5
- limit?: number | string;
6
- after?: string;
7
- before?: string;
8
- cursor?: string;
9
- order?: 'asc' | 'desc';
10
- }
11
- export interface PaginatorOpts {
12
- defaultLimit?: number;
13
- defaultOrder?: 'asc' | 'desc';
14
- }
15
- export type Provider<T> = (providers: {
16
- prisma: typeof paginatedProviderPrisma;
17
- }) => PaginatedProvider<T>;
18
- export declare class Paginator<T> {
19
- private provider;
20
- private opts;
21
- private constructor();
22
- static create<T>(provider: Provider<T>, opts?: PaginatorOpts): Paginator<T>;
23
- static validate<Inner extends object>(inner?: ValidationType<Inner>): ValidationType<Inner & {
24
- limit?: number;
25
- after?: string;
26
- before?: string;
27
- cursor?: string;
28
- order?: "asc" | "desc";
29
- }>;
30
- static present<T, R>(list: PaginatedList<T>, presenter: (item: T) => (context: any) => {
31
- run: (d: any) => R;
32
- } | undefined): (context: any) => {
33
- run: () => Promise<{
34
- __typename: string;
35
- items: (Awaited<R> | undefined)[];
36
- pagination: {
37
- has_more_after: boolean;
38
- has_more_before: boolean;
39
- };
40
- }>;
41
- };
42
- static presentLight<T, R>(list: PaginatedList<T>, presenter: (item: T) => R | Promise<R>): Promise<{
43
- __typename: string;
44
- items: (Awaited<R> | Awaited<R>)[];
45
- pagination: {
46
- has_more_after: boolean;
47
- has_more_before: boolean;
48
- };
49
- }>;
50
- run(input: PaginatorInput): Promise<PaginatedList<T>>;
51
- }
52
- //# sourceMappingURL=paginator.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"paginator.d.ts","sourceRoot":"","sources":["../src/paginator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE1D,OAAO,EACL,iBAAiB,EAEjB,uBAAuB,EACxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAExC,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;CAC/B;AAED,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,CAAC,SAAS,EAAE;IACpC,MAAM,EAAE,OAAO,uBAAuB,CAAC;CACxC,KAAK,iBAAiB,CAAC,CAAC,CAAC,CAAC;AAE3B,qBAAa,SAAS,CAAC,CAAC;IAEpB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,IAAI;IAFd,OAAO;IAKP,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,GAAE,aAAkB;IAIhE,MAAM,CAAC,QAAQ,CAAC,KAAK,SAAS,MAAM,EAAE,KAAK,CAAC,EAAE,cAAc,CAAC,KAAK,CAAC,GAc3D,cAAc,CAClB,KAAK,GAAG;QACN,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;KACxB,CACF;IAGH,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,EACjB,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,EACtB,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,KAAK;QAAE,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,CAAA;KAAE,GAAG,SAAS,IAEpE,SAAS,GAAG;;;;;;;;;;WAcT,YAAY,CAAC,CAAC,EAAE,CAAC,EAC5B,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,EACtB,SAAS,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;;;;;;;;IAYlC,GAAG,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;CA2B5D"}
package/dist/rpcMux.d.ts DELETED
@@ -1,30 +0,0 @@
1
- import { ServiceRequest } from './controller';
2
- export declare let rpcMux: (opts: {
3
- path: string;
4
- cors?: {
5
- headers?: string[];
6
- } & ({
7
- domains: string[];
8
- } | {
9
- check: (origin: string) => boolean;
10
- });
11
- }, rpcs: {
12
- handlerNames: string[];
13
- runMany: (req: ServiceRequest, body: {
14
- requestId: string;
15
- calls: {
16
- id: string;
17
- name: string;
18
- payload: any;
19
- }[];
20
- }) => Promise<{
21
- status: number;
22
- body: {
23
- calls: any[];
24
- };
25
- }>;
26
- }[]) => {
27
- path: string;
28
- fetch: (req: any) => Promise<any>;
29
- };
30
- //# sourceMappingURL=rpcMux.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"rpcMux.d.ts","sourceRoot":"","sources":["../src/rpcMux.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAe9C,eAAO,IAAI,MAAM,GACf,MAAM;IACJ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE;QACL,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;KACpB,GAAG,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG;QAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAA;KAAE,CAAC,CAAC;CACtE,EACD,MAAM;IACJ,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,EAAE,CACP,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE;QACJ,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE;YACL,EAAE,EAAE,MAAM,CAAC;YACX,IAAI,EAAE,MAAM,CAAC;YACb,OAAO,EAAE,GAAG,CAAC;SACd,EAAE,CAAC;KACL,KACE,OAAO,CAAC;QACX,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE;YACJ,KAAK,EAAE,GAAG,EAAE,CAAC;SACd,CAAC;KACH,CAAC,CAAC;CACJ,EAAE;;iBASkB,GAAG,KAAG,OAAO,CAAC,GAAG,CAAC;CAgPxC,CAAC"}
package/dist/server.d.ts DELETED
@@ -1,34 +0,0 @@
1
- import { Controller, ServiceRequest } from './controller';
2
- export declare let createServer: (opts: {
3
- onError?: (opts: {
4
- request: ServiceRequest;
5
- error: any;
6
- reqId: string;
7
- callId: string;
8
- callName: string;
9
- }) => void;
10
- onRequest?: (opts: {
11
- reqId: string;
12
- callId: string;
13
- callName: string;
14
- request: ServiceRequest;
15
- response: {
16
- status: number;
17
- body: any;
18
- };
19
- }) => void;
20
- }) => (controller: Controller<any>) => {
21
- handlerNames: string[];
22
- runMany: (req: ServiceRequest, body: {
23
- calls: {
24
- id: string;
25
- name: string;
26
- payload: any;
27
- }[];
28
- requestId: string;
29
- }) => Promise<{
30
- status: number;
31
- body: any;
32
- }>;
33
- };
34
- //# sourceMappingURL=server.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAW,cAAc,EAAE,MAAM,cAAc,CAAC;AAInE,eAAO,IAAI,YAAY,GACpB,MAAM;IACL,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE;QACf,OAAO,EAAE,cAAc,CAAC;QACxB,KAAK,EAAE,GAAG,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;KAClB,KAAK,IAAI,CAAC;IACX,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,cAAc,CAAC;QACxB,QAAQ,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,GAAG,CAAA;SAAE,CAAC;KACzC,KAAK,IAAI,CAAC;CACZ,MACA,YAAY,UAAU,CAAC,GAAG,CAAC;;mBA4FnB,cAAc,QACb;QACJ,KAAK,EAAE;YACL,EAAE,EAAE,MAAM,CAAC;YACX,IAAI,EAAE,MAAM,CAAC;YACb,OAAO,EAAE,GAAG,CAAC;SACd,EAAE,CAAC;QACJ,SAAS,EAAE,MAAM,CAAC;KACnB,KACA,OAAO,CAAC;QACT,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,GAAG,CAAC;KACX,CAAC;CA4EH,CAAC"}
package/dist/types.d.ts DELETED
@@ -1,8 +0,0 @@
1
- export interface PaginatedList<T> {
2
- items: T[];
3
- pagination: {
4
- hasNextPage: boolean;
5
- hasPreviousPage: boolean;
6
- };
7
- }
8
- //# sourceMappingURL=types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,UAAU,EAAE;QACV,WAAW,EAAE,OAAO,CAAC;QACrB,eAAe,EAAE,OAAO,CAAC;KAC1B,CAAC;CACH"}