Skip to content

Commit 189a6f8

Browse files
authored
Merge branch 'trunk' into feat/upgrade-mongodb
2 parents 87fea30 + 924e7f1 commit 189a6f8

File tree

30 files changed

+1562
-8
lines changed

30 files changed

+1562
-8
lines changed

.changeset/lazy-zoos-listen.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
"@reactioncommerce/api-core": minor
3+
"@reactioncommerce/api-plugin-accounts": minor
4+
"@reactioncommerce/api-plugin-orders": minor
5+
"@reactioncommerce/api-plugin-products": minor
6+
"@reactioncommerce/api-utils": minor
7+
---
8+
9+
Filter feature. This new feature provides a common function that can be used in a new query endpoint to get filtered results from any collection.

packages/api-core/src/graphql/schema.graphql

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,100 @@ enum MassUnit {
3434
oz
3535
}
3636

37+
"Relational Operator Types used in filtering inside a single condition"
38+
enum RelationalOperatorTypes{
39+
"Begins With used with String types to filter based on the beginning of the string"
40+
beginsWith
41+
42+
"Ends With used with String types to filter based on the end of the string"
43+
endsWith
44+
45+
"Equal to"
46+
eq
47+
48+
"Greater Than"
49+
gt
50+
51+
"Greater Than or Equal"
52+
gte
53+
54+
"In used with Array types to filter based on the array containing the value"
55+
in
56+
57+
"Less Than"
58+
lt
59+
60+
"Less Than or Equal"
61+
lte
62+
63+
"Not Equal to"
64+
ne
65+
66+
"Not In used with Array types to filter based on the array not containing the value"
67+
nin
68+
69+
"Regex used with String types to filter based on the regex pattern"
70+
regex
71+
}
72+
73+
"Single Condition for filter, use exactly one of the optional input value type"
74+
input SingleConditionInput {
75+
"Value to filter if it is Boolean input"
76+
booleanValue: Boolean
77+
78+
"Flag to set if the regex is case insensitive"
79+
caseSensitive: Boolean
80+
81+
"Value to filter if it is Date input"
82+
dateValue: DateTime
83+
84+
"Value to filter if it is Float Array input"
85+
floatArrayValue: [Float]
86+
87+
"Value to filter if it is Float input"
88+
floatValue: Float
89+
90+
"Value to filter if it is Integer Array input"
91+
integerArrayValue: [Int]
92+
93+
"Value to filter if it is Integer input"
94+
integerValue: Int
95+
96+
"Field name"
97+
key: String!
98+
99+
"Logical NOT operator to negate the condition"
100+
logicalNot: Boolean
101+
102+
"Relational Operator to join the key and value"
103+
relationalOperator: RelationalOperatorTypes!
104+
105+
"Value to filter if it is String Array input"
106+
stringArrayValue: [String]
107+
108+
"Value to filter if it is String input"
109+
stringValue: String
110+
}
111+
112+
"Filter with One level of conditions (use either 'any' or 'all' not both)"
113+
input ConditionsArray {
114+
"Array of single-conditions"
115+
all: [SingleConditionInput]
116+
117+
"Array of single-conditions"
118+
any: [SingleConditionInput]
119+
}
120+
121+
"Filter with nested conditions of input (use either 'any' or 'all' not both)"
122+
input FilterConditionsInput {
123+
"Array holding Nested conditions (use either 'any' or 'all' not both)"
124+
all: [ConditionsArray]
125+
126+
"Array holding Nested conditions (use either 'any' or 'all' not both)"
127+
any: [ConditionsArray]
128+
}
129+
130+
37131
"A list of URLs for various sizes of an image"
38132
type ImageSizes {
39133
"Use this URL to get a large resolution file for this image"

packages/api-plugin-accounts/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
},
2727
"sideEffects": false,
2828
"dependencies": {
29-
"@reactioncommerce/api-utils": "^1.16.9",
29+
"@reactioncommerce/api-utils": "~1.17.1",
3030
"@reactioncommerce/db-version-check": "^1.0.0",
3131
"@reactioncommerce/logger": "^1.1.3",
3232
"@reactioncommerce/random": "^1.0.2",
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import generateFilterQuery from "@reactioncommerce/api-utils/generateFilterQuery.js";
2+
3+
/**
4+
* @name filterAccounts
5+
* @method
6+
* @memberof GraphQL/Accounts
7+
* @summary Query the Accounts collection for a list of customers/accounts
8+
* @param {Object} context - an object containing the per-request state
9+
* @param {Object} conditions - object containing the filter conditions
10+
* @param {String} shopId - shopID to filter by
11+
* @returns {Promise<Object>} Accounts object Promise
12+
*/
13+
export default async function filterAccounts(context, conditions, shopId) {
14+
const { collections: { Accounts } } = context;
15+
16+
if (!shopId) {
17+
throw new Error("shopId is required");
18+
}
19+
await context.validatePermissions("reaction:legacy:accounts", "read", { shopId });
20+
21+
const { filterQuery } = generateFilterQuery(context, "Account", conditions, shopId);
22+
23+
return Accounts.find(filterQuery);
24+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import generateFilterQuery from "@reactioncommerce/api-utils/generateFilterQuery.js";
2+
3+
/**
4+
* @name filterCustomers
5+
* @method
6+
* @memberof GraphQL/Customers
7+
* @summary Query the Accounts collection for a list of customers/accounts
8+
* @param {Object} context - an object containing the per-request state
9+
* @param {Object} conditions - object containing the filter conditions
10+
* @param {String} shopId - shopID to filter by
11+
* @returns {Promise<Object>} Accounts object Promise
12+
*/
13+
export default async function filterCustomers(context, conditions, shopId) {
14+
const { collections: { Accounts } } = context;
15+
16+
if (!shopId) {
17+
throw new Error("shopId is required");
18+
}
19+
await context.validatePermissions("reaction:legacy:accounts", "read", { shopId });
20+
21+
const { filterQuery } = generateFilterQuery(context, "Account", conditions, shopId);
22+
23+
filterQuery.groups = { $in: [null, []] }; // filter out non-customer accounts
24+
return Accounts.find(filterQuery);
25+
}

packages/api-plugin-accounts/src/queries/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@ import groupsByAccount from "./groupsByAccount.js";
77
import groupsById from "./groupsById.js";
88
import invitations from "./invitations.js";
99
import userAccount from "./userAccount.js";
10+
import filterAccounts from "./filterAccounts.js";
11+
import filterCustomers from "./filterCustomers.js";
1012

1113
export default {
14+
filterAccounts,
15+
filterCustomers,
1216
accountByUserId,
1317
accounts,
1418
customers,
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import getPaginatedResponse from "@reactioncommerce/api-utils/graphql/getPaginatedResponse.js";
2+
import wasFieldRequested from "@reactioncommerce/api-utils/graphql/wasFieldRequested.js";
3+
4+
/**
5+
* @name Query/accounts
6+
* @method
7+
* @memberof Accounts/Query
8+
* @summary Query for a list of accounts
9+
* @param {Object} _ - unused
10+
* @param {Object} args - an object of all arguments that were sent by the client
11+
* @param {String} args.shopId - id of shop to query
12+
* @param {Object} args.conditions - object containing the filter conditions
13+
* @param {Object} context - an object containing the per-request state
14+
* @param {Object} info Info about the GraphQL request
15+
* @returns {Promise<Object>} Accounts
16+
*/
17+
export default async function filterAccounts(_, args, context, info) {
18+
const {
19+
shopId,
20+
conditions,
21+
...connectionArgs
22+
} = args;
23+
24+
const query = await context.queries.filterAccounts(context, conditions, shopId);
25+
26+
return getPaginatedResponse(query, connectionArgs, {
27+
includeHasNextPage: wasFieldRequested("pageInfo.hasNextPage", info),
28+
includeHasPreviousPage: wasFieldRequested("pageInfo.hasPreviousPage", info),
29+
includeTotalCount: wasFieldRequested("totalCount", info)
30+
});
31+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import getPaginatedResponse from "@reactioncommerce/api-utils/graphql/getPaginatedResponse.js";
2+
import wasFieldRequested from "@reactioncommerce/api-utils/graphql/wasFieldRequested.js";
3+
4+
/**
5+
* @name Query/accounts
6+
* @method
7+
* @memberof Customers/Query
8+
* @summary Query for a list of customers
9+
* @param {Object} _ - unused
10+
* @param {Object} args - an object of all arguments that were sent by the client
11+
* @param {String} args.shopId - id of shop to query
12+
* @param {Object} args.conditions - object containing the filter conditions
13+
* @param {Object} context - an object containing the per-request state
14+
* @param {Object} info Info about the GraphQL request
15+
* @returns {Promise<Object>} Accounts
16+
*/
17+
export default async function filterCustomers(_, args, context, info) {
18+
const {
19+
shopId,
20+
conditions,
21+
...connectionArgs
22+
} = args;
23+
24+
const query = await context.queries.filterCustomers(context, conditions, shopId);
25+
26+
return getPaginatedResponse(query, connectionArgs, {
27+
includeHasNextPage: wasFieldRequested("pageInfo.hasNextPage", info),
28+
includeHasPreviousPage: wasFieldRequested("pageInfo.hasPreviousPage", info),
29+
includeTotalCount: wasFieldRequested("totalCount", info)
30+
});
31+
}

packages/api-plugin-accounts/src/resolvers/Query/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@ import group from "./group.js";
55
import groups from "./groups.js";
66
import invitations from "./invitations.js";
77
import viewer from "./viewer.js";
8+
import filterAccounts from "./filterAccounts.js";
9+
import filterCustomers from "./filterCustomers.js";
810

911
export default {
12+
filterAccounts,
13+
filterCustomers,
1014
account,
1115
accounts,
1216
customers,

packages/api-plugin-accounts/src/schemas/account.graphql

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,66 @@ extend type Query {
496496
id: ID!
497497
): Account
498498

499+
"Query to get a filtered list of Accounts"
500+
filterAccounts(
501+
"Shop ID"
502+
shopId: ID!,
503+
504+
"Input Conditions for fliter (use either 'any' or 'all' not both)"
505+
conditions: FilterConditionsInput,
506+
507+
"Return only results that come after this cursor. Use this with `first` to specify the number of results to return."
508+
after: ConnectionCursor,
509+
510+
"Return only results that come before this cursor. Use this with `last` to specify the number of results to return."
511+
before: ConnectionCursor,
512+
513+
"Return at most this many results. This parameter may be used with either `after` or `offset` parameters."
514+
first: ConnectionLimitInt,
515+
516+
"Return at most this many results. This parameter may be used with the `before` parameter."
517+
last: ConnectionLimitInt,
518+
519+
"Return only results that come after the Nth result. This parameter may be used with the `first` parameter."
520+
offset: Int
521+
522+
"Return results sorted in this order"
523+
sortOrder: SortOrder = desc,
524+
525+
"By default, accounts are sorted by createdAt. Set this to sort by one of the other allowed fields"
526+
sortBy: AccountSortByField = createdAt
527+
): AccountConnection
528+
529+
"Query to get a filtered list of Customers"
530+
filterCustomers(
531+
"Shop ID"
532+
shopId: ID!,
533+
534+
"Input Conditions for fliter (use either 'any' or 'all' not both)"
535+
conditions: FilterConditionsInput,
536+
537+
"Return only results that come after this cursor. Use this with `first` to specify the number of results to return."
538+
after: ConnectionCursor,
539+
540+
"Return only results that come before this cursor. Use this with `last` to specify the number of results to return."
541+
before: ConnectionCursor,
542+
543+
"Return at most this many results. This parameter may be used with either `after` or `offset` parameters."
544+
first: ConnectionLimitInt,
545+
546+
"Return at most this many results. This parameter may be used with the `before` parameter."
547+
last: ConnectionLimitInt,
548+
549+
"Return only results that come after the Nth result. This parameter may be used with the `first` parameter."
550+
offset: Int
551+
552+
"Return results sorted in this order"
553+
sortOrder: SortOrder = desc,
554+
555+
"By default, customers are sorted by createdAt. Set this to sort by one of the other allowed fields"
556+
sortBy: AccountSortByField = createdAt
557+
): AccountConnection
558+
499559
"Returns accounts optionally filtered by account groups"
500560
accounts(
501561
"Return only accounts in any of these groups"

0 commit comments

Comments
 (0)