@orion-js/paginated-mongodb 3.2.55 → 3.3.1

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.
@@ -1,16 +1,31 @@
1
- import { Collection, FindCursor } from '@orion-js/mongodb';
2
- export interface PaginatedResolverOpts<T = any> {
1
+ export interface PaginatedCursor {
2
+ count?: () => Promise<number> | number;
3
+ toArray: () => Promise<any[]>;
4
+ limit?: (newLimit: number) => void;
5
+ skip?: (newSkip: number) => void;
6
+ sort?: (newSort: {
7
+ [key: string]: 1 | -1;
8
+ }) => void;
9
+ }
10
+ export declare type PaginatedResolverGetCursorResultWithCount = {
11
+ count: () => Promise<number> | number;
12
+ cursor: PaginatedCursor;
13
+ };
14
+ export declare type PaginatedResolverGetCursorResult = PaginatedCursor | PaginatedResolverGetCursorResultWithCount;
15
+ export interface PaginatedResolverOpts {
3
16
  returns: any;
4
- collection?: Collection<T>;
5
- params?: object;
6
- getCursor: (params?: any, viewer?: any) => Promise<FindCursor<T>>;
17
+ getCursor: (params?: any, viewer?: any) => Promise<PaginatedResolverGetCursorResult>;
18
+ allowedSorts?: string[];
19
+ defaultSortBy?: string;
20
+ defaultSortType?: 'asc' | 'desc';
21
+ params?: any;
7
22
  modelName?: string;
8
23
  permissionsOptions?: any;
9
24
  }
10
- export default function paginatedResolver<T = any>({ returns, collection, params, getCursor, modelName, ...otherOptions }: PaginatedResolverOpts<T> & {
25
+ export default function paginatedResolver({ returns, params, allowedSorts, defaultSortBy, defaultSortType, getCursor, getCursorAndCount, modelName, ...otherOptions }: PaginatedResolverOpts & {
11
26
  [key: string]: any;
12
27
  }): import("@orion-js/resolvers").Resolver<(params: any, viewer: any) => Promise<{
13
- cursor: FindCursor<T>;
28
+ cursor: PaginatedCursor;
14
29
  params: any;
15
30
  viewer: any;
16
31
  options: {
@@ -8,22 +8,27 @@ const getModel_1 = __importDefault(require("./getModel"));
8
8
  const params_1 = __importDefault(require("./params"));
9
9
  const setOptions_1 = __importDefault(require("./setOptions"));
10
10
  const getArgs_1 = require("@orion-js/resolvers/lib/resolver/getArgs");
11
- function paginatedResolver({ returns, collection, params, getCursor, modelName, ...otherOptions }) {
12
- const getPaginatedCursor = async (...args) => {
13
- if (getCursor) {
14
- return await getCursor(...args);
11
+ function paginatedResolver({ returns, params, allowedSorts, defaultSortBy, defaultSortType, getCursor, getCursorAndCount, modelName, ...otherOptions }) {
12
+ const getCursorResult = async (...args) => {
13
+ const result = await getCursor(...args);
14
+ if (result.cursor) {
15
+ const resultWithCount = result;
16
+ return { cursor: resultWithCount.cursor, getCount: () => resultWithCount.count() };
17
+ }
18
+ else {
19
+ const resultWithoutCount = result;
20
+ return { cursor: resultWithoutCount, getCount: () => resultWithoutCount.count() };
15
21
  }
16
- return collection.find({});
17
22
  };
18
23
  return (0, resolvers_1.resolver)({
19
- params: (0, params_1.default)({ params }),
24
+ params: (0, params_1.default)({ params, allowedSorts, defaultSortBy, defaultSortType }),
20
25
  returns: (0, getModel_1.default)({ modelName, returns }),
21
26
  async resolve(...args) {
22
27
  const { params, viewer } = (0, getArgs_1.getArgs)(...args);
23
- const cursor = await getPaginatedCursor(...args);
28
+ const { cursor, getCount } = await getCursorResult(...args);
24
29
  /* counting the total number of elements of this cursor, so we make sure
25
30
  that it is going to be computed only once */
26
- const count = await cursor.count();
31
+ const count = await getCount();
27
32
  const options = (0, setOptions_1.default)(params, cursor);
28
33
  return {
29
34
  cursor,
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const models_1 = require("@orion-js/models");
16
+ const helpers_1 = require("@orion-js/helpers");
17
+ const _1 = __importDefault(require("."));
18
+ const typed_model_1 = require("@orion-js/typed-model");
19
+ const mongodb_1 = require("@orion-js/mongodb");
20
+ describe('Full example of paginated resolver', () => {
21
+ const createResolver = async () => {
22
+ let ItemSchema = class ItemSchema {
23
+ };
24
+ __decorate([
25
+ (0, typed_model_1.Prop)(),
26
+ __metadata("design:type", String)
27
+ ], ItemSchema.prototype, "name", void 0);
28
+ __decorate([
29
+ (0, typed_model_1.Prop)(),
30
+ __metadata("design:type", Number)
31
+ ], ItemSchema.prototype, "index", void 0);
32
+ ItemSchema = __decorate([
33
+ (0, typed_model_1.TypedSchema)()
34
+ ], ItemSchema);
35
+ const collection = (0, mongodb_1.createCollection)({
36
+ name: (0, helpers_1.generateId)(),
37
+ schema: ItemSchema
38
+ });
39
+ await collection.insertMany([
40
+ { name: `Number 1`, index: 1 },
41
+ { name: `Number 2`, index: 2 },
42
+ { name: `Number 3`, index: 3 },
43
+ { name: `Number 4`, index: 4 },
44
+ { name: `Number 5`, index: 5 },
45
+ { name: `Number 6`, index: 6 }
46
+ ]);
47
+ let Params = class Params {
48
+ };
49
+ __decorate([
50
+ (0, typed_model_1.Prop)({ optional: true }),
51
+ __metadata("design:type", String)
52
+ ], Params.prototype, "filter", void 0);
53
+ Params = __decorate([
54
+ (0, typed_model_1.TypedSchema)()
55
+ ], Params);
56
+ return (0, _1.default)({
57
+ returns: ItemSchema,
58
+ params: Params,
59
+ allowedSorts: ['index'],
60
+ async getCursor(params) {
61
+ const query = {};
62
+ if (params.filter) {
63
+ query.name = params.filter;
64
+ }
65
+ return collection.find(query);
66
+ }
67
+ });
68
+ };
69
+ it('should work passing custom params', async () => {
70
+ const resolver = await createResolver();
71
+ const result = (await resolver.resolve({
72
+ filter: `Number 1`
73
+ }, {}));
74
+ const items = await result.items();
75
+ const count = await result.totalCount();
76
+ expect(items.length).toBe(1);
77
+ expect(items[0].index).toBe(1);
78
+ expect(count).toBe(1);
79
+ });
80
+ it('should using sorts', async () => {
81
+ const resolver = await createResolver();
82
+ const result = (await resolver.resolve({
83
+ sortBy: 'index',
84
+ sortType: 'asc'
85
+ }, {}));
86
+ const items = await result.items();
87
+ const count = await result.totalCount();
88
+ expect(items.map(item => item.index)).toEqual([1, 2, 3, 4, 5, 6]);
89
+ expect(count).toBe(6);
90
+ });
91
+ });
92
+ describe('Cursors with count', () => {
93
+ const createResolver = async () => {
94
+ const cursor = {
95
+ count: () => 100,
96
+ toArray: async () => [{ hello: 'foo' }]
97
+ };
98
+ return (0, _1.default)({
99
+ returns: (0, models_1.createModel)({
100
+ name: 'Hello',
101
+ schema: {
102
+ hello: {
103
+ type: String
104
+ }
105
+ }
106
+ }),
107
+ async getCursor() {
108
+ return {
109
+ cursor: cursor,
110
+ count: () => 10
111
+ };
112
+ }
113
+ });
114
+ };
115
+ it('should not call cursor.count', async () => {
116
+ const resolver = await createResolver();
117
+ const result = (await resolver.resolve({}, {}));
118
+ const items = await result.items();
119
+ const count = await result.totalCount();
120
+ expect(items.length).toBe(1);
121
+ expect(count).toBe(10);
122
+ });
123
+ });
@@ -1,4 +1,5 @@
1
- declare const _default: ({ params }: {
2
- params: any;
3
- }) => any;
4
- export default _default;
1
+ import { Schema } from '@orion-js/schema';
2
+ import { PaginatedResolverOpts } from '.';
3
+ declare type OptionsKeys = 'params' | 'allowedSorts' | 'defaultSortBy' | 'defaultSortType';
4
+ export default function getParams(options: Pick<PaginatedResolverOpts, OptionsKeys>): Schema;
5
+ export {};
@@ -1,16 +1,52 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.default = ({ params }) => ({
4
- page: {
5
- type: 'integer',
6
- defaultValue: 1,
7
- min: 1
8
- },
9
- limit: {
10
- type: 'integer',
11
- defaultValue: 0,
12
- min: 0,
13
- max: 200
14
- },
15
- ...params
16
- });
3
+ const lodash_1 = require("lodash");
4
+ function getParams(options) {
5
+ const { params, allowedSorts, defaultSortBy, defaultSortType } = options;
6
+ const schema = {
7
+ page: {
8
+ type: 'integer',
9
+ defaultValue: 1,
10
+ min: 1
11
+ },
12
+ limit: {
13
+ type: 'integer',
14
+ defaultValue: 0,
15
+ min: 0,
16
+ max: 200
17
+ }
18
+ };
19
+ if (allowedSorts && allowedSorts.length) {
20
+ schema.sortBy = {
21
+ type: String,
22
+ allowedValues: allowedSorts,
23
+ optional: true
24
+ };
25
+ if (defaultSortBy) {
26
+ schema.sortBy.defaultValue = defaultSortBy;
27
+ }
28
+ schema.sortType = {
29
+ type: String,
30
+ allowedValues: ['asc', 'desc'],
31
+ optional: true
32
+ };
33
+ if (defaultSortType) {
34
+ schema.sortType.defaultValue = defaultSortType;
35
+ }
36
+ }
37
+ if (params) {
38
+ if (typeof params === 'function' && params.getModel && params.__schemaId) {
39
+ const modelSchema = params.getModel().getSchema();
40
+ Object.assign(schema, (0, lodash_1.omit)(modelSchema, '__model'));
41
+ }
42
+ else if (params.__isModel) {
43
+ const modelSchema = params.getSchema();
44
+ Object.assign(schema, (0, lodash_1.omit)(modelSchema, '__model'));
45
+ }
46
+ else {
47
+ Object.assign(schema, params);
48
+ }
49
+ }
50
+ return schema;
51
+ }
52
+ exports.default = getParams;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const models_1 = require("@orion-js/models");
16
+ const params_1 = __importDefault(require("./params"));
17
+ const typed_model_1 = require("@orion-js/typed-model");
18
+ describe('Get params', () => {
19
+ it('should return the params', () => {
20
+ const params = (0, params_1.default)({
21
+ params: { foo: 'bar' }
22
+ });
23
+ expect(params).toEqual({
24
+ page: {
25
+ type: 'integer',
26
+ defaultValue: 1,
27
+ min: 1
28
+ },
29
+ limit: {
30
+ type: 'integer',
31
+ defaultValue: 0,
32
+ min: 0,
33
+ max: 200
34
+ },
35
+ foo: 'bar'
36
+ });
37
+ });
38
+ it('should return the params with allowed sort', () => {
39
+ const params = (0, params_1.default)({
40
+ params: { foo: 'bar' },
41
+ allowedSorts: ['foo']
42
+ });
43
+ expect(params).toEqual({
44
+ page: {
45
+ type: 'integer',
46
+ defaultValue: 1,
47
+ min: 1
48
+ },
49
+ limit: {
50
+ type: 'integer',
51
+ defaultValue: 0,
52
+ min: 0,
53
+ max: 200
54
+ },
55
+ sortBy: {
56
+ type: String,
57
+ allowedValues: ['foo'],
58
+ optional: true
59
+ },
60
+ sortType: {
61
+ type: String,
62
+ allowedValues: ['asc', 'desc'],
63
+ optional: true
64
+ },
65
+ foo: 'bar'
66
+ });
67
+ });
68
+ it('should return the params correctly if we pass a model', () => {
69
+ const model = (0, models_1.createModel)({
70
+ name: 'Params',
71
+ schema: {
72
+ foo: {
73
+ type: 'string'
74
+ }
75
+ }
76
+ });
77
+ const params = (0, params_1.default)({
78
+ params: model,
79
+ allowedSorts: ['foo']
80
+ });
81
+ expect(params).toEqual({
82
+ page: {
83
+ type: 'integer',
84
+ defaultValue: 1,
85
+ min: 1
86
+ },
87
+ limit: {
88
+ type: 'integer',
89
+ defaultValue: 0,
90
+ min: 0,
91
+ max: 200
92
+ },
93
+ sortBy: {
94
+ type: String,
95
+ allowedValues: ['foo'],
96
+ optional: true
97
+ },
98
+ sortType: {
99
+ type: String,
100
+ allowedValues: ['asc', 'desc'],
101
+ optional: true
102
+ },
103
+ foo: {
104
+ type: 'string'
105
+ }
106
+ });
107
+ });
108
+ it('should return the params correctly if we pass a typed schema', () => {
109
+ let Schema = class Schema {
110
+ };
111
+ __decorate([
112
+ (0, typed_model_1.Prop)(),
113
+ __metadata("design:type", String)
114
+ ], Schema.prototype, "foo", void 0);
115
+ Schema = __decorate([
116
+ (0, typed_model_1.TypedSchema)()
117
+ ], Schema);
118
+ const params = (0, params_1.default)({
119
+ params: Schema,
120
+ allowedSorts: ['foo']
121
+ });
122
+ expect(params).toEqual({
123
+ page: {
124
+ type: 'integer',
125
+ defaultValue: 1,
126
+ min: 1
127
+ },
128
+ limit: {
129
+ type: 'integer',
130
+ defaultValue: 0,
131
+ min: 0,
132
+ max: 200
133
+ },
134
+ sortBy: {
135
+ type: String,
136
+ allowedValues: ['foo'],
137
+ optional: true
138
+ },
139
+ sortType: {
140
+ type: String,
141
+ allowedValues: ['asc', 'desc'],
142
+ optional: true
143
+ },
144
+ foo: {
145
+ type: String
146
+ }
147
+ });
148
+ });
149
+ });
@@ -1,7 +1,10 @@
1
- export default function ({ page, limit }: {
1
+ import { PaginatedCursor } from './index';
2
+ export default function ({ page, limit, sortBy, sortType }: {
2
3
  page: any;
3
4
  limit: any;
4
- }, cursor: any): {
5
+ sortBy: any;
6
+ sortType: any;
7
+ }, cursor: PaginatedCursor): {
5
8
  skip: number;
6
9
  limit: any;
7
10
  };
@@ -1,13 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- function default_1({ page, limit }, cursor) {
3
+ function default_1({ page, limit, sortBy, sortType }, cursor) {
4
4
  const skip = limit * (page - 1);
5
- if (limit) {
5
+ if (limit && cursor.limit) {
6
6
  cursor.limit(limit);
7
7
  }
8
- if (skip) {
8
+ if (skip && cursor.skip) {
9
9
  cursor.skip(skip);
10
10
  }
11
+ if (sortBy && sortType && cursor.sort) {
12
+ cursor.sort({
13
+ [`${sortBy}`]: sortType === 'asc' ? 1 : -1
14
+ });
15
+ }
11
16
  return {
12
17
  skip,
13
18
  limit
@@ -2,4 +2,4 @@ import { PaginatedResolverOpts } from '../paginatedResolver';
2
2
  export interface PagiantedQueryDescriptor extends Omit<PropertyDecorator, 'value'> {
3
3
  value?: PaginatedResolverOpts['getCursor'];
4
4
  }
5
- export declare function PaginatedQuery(options: Omit<PaginatedResolverOpts<any>, 'getCursor'>): (target: any, propertyKey: string, descriptor: PagiantedQueryDescriptor) => void;
5
+ export declare function PaginatedQuery(options: Omit<PaginatedResolverOpts, 'getCursor'>): (target: any, propertyKey: string, descriptor: PagiantedQueryDescriptor) => void;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const mongodb_1 = require("@orion-js/mongodb");
4
+ const url = `${global.__MONGO_URI__}jest`;
5
+ process.env.MONGO_URL = url;
6
+ beforeAll(async () => {
7
+ const connection = (0, mongodb_1.getMongoConnection)({ name: 'main' });
8
+ await connection.connectionPromise;
9
+ });
10
+ afterAll(async () => {
11
+ /**
12
+ * We need to wait on indexes promises to be resolved to close all the handlers
13
+ */
14
+ await Promise.all(mongodb_1.createIndexesPromises);
15
+ for (const connectionName in mongodb_1.connections) {
16
+ const connection = mongodb_1.connections[connectionName];
17
+ await connection.client.close();
18
+ }
19
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orion-js/paginated-mongodb",
3
- "version": "3.2.55",
3
+ "version": "3.3.1",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "files": [
@@ -9,7 +9,7 @@
9
9
  "author": "nicolaslopezj",
10
10
  "license": "MIT",
11
11
  "scripts": {
12
- "test": "exit 0",
12
+ "test": "jest",
13
13
  "prepare": "yarn run build",
14
14
  "clean": "rm -rf ./lib",
15
15
  "build": "yarn run clean && tsc",
@@ -20,7 +20,8 @@
20
20
  "@orion-js/models": "^3.2.53",
21
21
  "@orion-js/mongodb": "^3.2.55",
22
22
  "@orion-js/resolvers": "^3.2.53",
23
- "@orion-js/services": "^3.2.48"
23
+ "@orion-js/services": "^3.2.48",
24
+ "@orion-js/typed-model": "^3.2.53"
24
25
  },
25
26
  "devDependencies": {
26
27
  "@shelf/jest-mongodb": "^2.1.0",
@@ -33,5 +34,5 @@
33
34
  "publishConfig": {
34
35
  "access": "public"
35
36
  },
36
- "gitHead": "ce5164ec1e1f513042436572b0fbf0d4df0fd224"
37
+ "gitHead": "f47ed0366f06654d5353c188e91d69f92fd6d536"
37
38
  }