eth-graph-query 1.1.1 → 1.1.3

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,15 @@
1
- import { ElementType, GraphParams, Metadata, OptionKeys, OptionsKey, QueryJson, WhereOptions } from './type.js';
1
+ import {
2
+ ElementType,
3
+ GraphObject,
4
+ GraphParams,
5
+ InlineFragmentType,
6
+ Metadata,
7
+ OptionKeys,
8
+ QueryJson,
9
+ WhereOptions,
10
+ } from './type.js';
2
11
 
3
12
  export class QueryBuilder {
4
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
5
- private static isWhereOptions(data: any) {
6
- const keys = Object.keys(data);
7
- if (keys.length == 0) return true;
8
- for (const key of keys) {
9
- if (!OptionKeys.includes(key)) return false;
10
- }
11
- return true;
12
- }
13
-
14
13
  /**
15
14
  * Create a query string from a query with json format.
16
15
  * @param {QueryJson} query the json format query
@@ -23,18 +22,28 @@ export class QueryBuilder {
23
22
  if (Array.isArray(query[key])) {
24
23
  const queryArray = query[key] as Array<string>;
25
24
  whereList.push(`${key}: [${queryArray.map((item) => `"${item}"`).join(', ')}]`);
26
- } else if (this.isWhereOptions(query[key])) {
27
- const realJson: QueryJson = {};
28
- const options = query[key] as WhereOptions;
25
+ } else if (typeof query[key] == 'object') {
26
+ const normalJson: QueryJson = {};
27
+ const operatorJson: QueryJson = {};
28
+ const options = query[key] as { [key: string]: QueryJson | WhereOptions };
29
29
  for (const option in options) {
30
- const value = options[option as OptionsKey];
31
- if (value) realJson[`${key}_${option}`] = value;
30
+ const value = options[option];
31
+ if (option.length == 1) normalJson[option] = value;
32
+ else {
33
+ if (option[0] == '$') {
34
+ const realOperator = option.slice(1);
35
+ if (OptionKeys.includes(realOperator))
36
+ operatorJson[`${key}_${realOperator}`] = value;
37
+ } else normalJson[option] = value;
38
+ }
32
39
  }
33
- whereList.push(`${this.buildJsonQuery(realJson as QueryJson)}`);
34
- } else if (typeof query[key] == 'object')
35
- whereList.push(`${key}: {${this.buildJsonQuery(query[key] as QueryJson)}}`);
36
- else if (typeof query[key] == 'string') whereList.push(`${key}: "${query[key]}"`);
37
- else whereList.push(`${key}: ${query[key]}`);
40
+ if (Object.keys(normalJson).length > 0)
41
+ whereList.push(`${key}: {${this.buildJsonQuery(normalJson as QueryJson)}}`);
42
+ if (Object.keys(operatorJson).length > 0)
43
+ whereList.push(this.buildJsonQuery(operatorJson as QueryJson));
44
+ } else if (typeof query[key] == 'string') {
45
+ whereList.push(`${key}: "${query[key]}"`);
46
+ } else whereList.push(`${key}: ${query[key]}`);
38
47
  }
39
48
  }
40
49
  return whereList.join(', ');
@@ -68,7 +77,8 @@ export class QueryBuilder {
68
77
  if (metadata.blockQuery) {
69
78
  if (metadata.blockQuery.hash) blockQuery.push(`hash: "${metadata.blockQuery.hash}"`);
70
79
  if (metadata.blockQuery.number) blockQuery.push(`number: ${metadata.blockQuery.number}`);
71
- if (metadata.blockQuery.number_gte) blockQuery.push(`number_gte: ${metadata.blockQuery.number_gte}`);
80
+ if (metadata.blockQuery.number_gte)
81
+ blockQuery.push(`number_gte: ${metadata.blockQuery.number_gte}`);
72
82
  }
73
83
  const sBlockQuery = blockQuery.join(', ');
74
84
  if (sBlockQuery.length > 0) result += `(block: {${sBlockQuery}})`;
@@ -92,45 +102,80 @@ export class QueryBuilder {
92
102
  return result.length > 0 ? `_meta${result}` : '';
93
103
  }
94
104
 
105
+ private static _buildInlineFragment(fragment: InlineFragmentType): string {
106
+ let elements = ['id'];
107
+ if (fragment.params?.elements) elements = this.buildElements(fragment.params.elements);
108
+ return `... on ${fragment.collection}{${elements.join(' ')}}`;
109
+ }
110
+
111
+ /**
112
+ * Given a instance of Array<{@link InlineFragmentType}>, returns the string represent the inline fragments you want to query
113
+ * @param {Array<InlineFragmentType>} fragments The instance represent the inline fragments you want to query
114
+ * @returns The string represent the inline fragments you want to query
115
+ */
116
+ static buildInlineFragments(fragments: Array<InlineFragmentType>): string {
117
+ const result = [];
118
+ for (const fragment of fragments) {
119
+ result.push(this._buildInlineFragment(fragment));
120
+ }
121
+ return result.join(' ');
122
+ }
123
+
95
124
  /**
96
125
  * Given json data, returns the string query. This function only can create a string query for a particular collection.
97
- * @param {{ collection: string; params?: GraphParams }} data An data for create query, contains two elements:
126
+ * @param {GraphObject} data An data for create query, contains two elements:
98
127
  * 1. collection: string - collection name
99
128
  * 2. params: GraphParams | undefined - If it is defined, it create a query to the collection
100
129
  * @param {Metadata | undefined} metadata If it is defined, the query can get metadata that you defined
101
130
  * @returns The string query
102
131
  */
103
- static buildQuery(data: { collection: string; params?: GraphParams }, metadata?: Metadata): string {
132
+ static buildQuery(data: GraphObject, metadata?: Metadata): string {
104
133
  const collection = data.collection;
105
134
  const params = data.params;
106
135
  const filters: Array<string> = [];
136
+ // build id
107
137
  if (params?.id != undefined) filters.push(`id: ${params.id}`);
138
+ // build order
108
139
  if (params?.orderBy) filters.push(`orderBy: ${params.orderBy}`);
140
+ // build order direction
109
141
  if (params?.orderDirection) filters.push(`orderDirection: ${params.orderDirection}`);
142
+ //build first
110
143
  if (params?.first != undefined) {
111
144
  if (params.first < 0) params.first = 0;
112
145
  else if (params.first > 1000) params.first = 1000;
113
146
  filters.push(`first: ${params.first}`);
114
147
  }
148
+ // build skip
115
149
  if (params?.skip != undefined) {
116
150
  if (params.skip < 0) params.skip = 0;
117
151
  else if (params.skip > 5000) params.skip = 5000;
118
152
  filters.push(`skip: ${params.skip}`);
119
153
  }
154
+ // build where
120
155
  if (params?.where) {
121
156
  const sWhere = this.buildJsonQuery(params.where);
122
157
  if (sWhere.length > 0) filters.push(`where: {${sWhere}}`);
123
158
  }
159
+ // build block
124
160
  if (params?.block) {
125
161
  const sBlock = this.buildJsonQuery(params.block);
126
162
  if (sBlock.length > 0) filters.push(`block: {${sBlock}}`);
127
163
  }
128
164
  const filterString = filters.join(', ');
165
+ // build elements
129
166
  let elements: Array<string> = ['id'];
130
- if (params?.elements) if (params.elements.length > 0) elements = this.buildElements(params.elements);
167
+ if (params?.elements)
168
+ if (params.elements.length > 0) elements = this.buildElements(params.elements);
169
+ // build inline fragments
170
+ let inlineFragments = '';
171
+ if (params?.inlineFragments)
172
+ if (params.inlineFragments.length > 0)
173
+ inlineFragments = this.buildInlineFragments(params.inlineFragments);
131
174
  let finalQuery = '';
132
- if (filterString.length > 0) finalQuery = `${collection}(${filterString}) {${elements.join(' ')}}`;
133
- else finalQuery = `${collection} {${elements.join(' ')}}`;
175
+ const sElements =
176
+ inlineFragments.length > 0 ? `${elements.join(' ')} ${inlineFragments}` : elements.join(' ');
177
+ if (filterString.length > 0) finalQuery = `${collection}(${filterString}) {${sElements}}`;
178
+ else finalQuery = `${collection} {${sElements}}`;
134
179
  if (metadata) {
135
180
  const sMetadata = this.buildMetadata(metadata);
136
181
  if (sMetadata.length > 0) return `${sMetadata} ${finalQuery}`;
@@ -141,13 +186,14 @@ export class QueryBuilder {
141
186
 
142
187
  /**
143
188
  * Given a array contain many json data, return a query string represent a query to all collections that is in a array.
144
- * @param {Array<{ collection: string; params?: GraphParams }>} data An array contain data to query to many collections
189
+ * @param {Array<GraphObject>} data An array contain data to query to many collections
145
190
  * @param {Metadata | undefined} metadata If it is defined, the query can get metadata that you defined
146
191
  * @returns The query string
147
192
  */
148
- static mergeQuery(data: Array<{ collection: string; params?: GraphParams }>, metadata?: Metadata): string {
193
+ static mergeQuery(data: Array<GraphObject>, metadata?: Metadata): string {
149
194
  const queries: Array<string> = [];
150
- for (const item of data) queries.push(this.buildQuery({ collection: item.collection, params: item.params }));
195
+ for (const item of data)
196
+ queries.push(this.buildQuery({ collection: item.collection, params: item.params }));
151
197
  const finalQuery = queries.join(' ');
152
198
  if (metadata) {
153
199
  const sMetadata = this.buildMetadata(metadata);
package/src/type.ts CHANGED
@@ -21,50 +21,30 @@ export const OptionKeys = [
21
21
  'in',
22
22
  'not_in',
23
23
  ];
24
- export type OptionsKey =
25
- | 'contains'
26
- | 'contains_nocase'
27
- | 'ends_with'
28
- | 'end_with_nocase'
29
- | 'starts_with'
30
- | 'starts_with_nocase'
31
- | 'not_contains'
32
- | 'not_contains_nocase'
33
- | 'not_ends_with'
34
- | 'not_ends_with_nocase'
35
- | 'not_starts_with'
36
- | 'not_starts_with_nocase'
37
- | 'gt'
38
- | 'gte'
39
- | 'lt'
40
- | 'lte'
41
- | 'not'
42
- | 'in'
43
- | 'not_in';
44
24
 
45
25
  export type TextWhereOptions = {
46
- contains?: BaseQueryType;
47
- contains_nocase?: BaseQueryType;
48
- ends_with?: BaseQueryType;
49
- end_with_nocase?: BaseQueryType;
50
- starts_with?: BaseQueryType;
51
- starts_with_nocase?: BaseQueryType;
52
- not_contains?: BaseQueryType;
53
- not_contains_nocase?: BaseQueryType;
54
- not_ends_with?: BaseQueryType;
55
- not_ends_with_nocase?: BaseQueryType;
56
- not_starts_with?: BaseQueryType;
57
- not_starts_with_nocase?: BaseQueryType;
26
+ $contains?: BaseQueryType;
27
+ $contains_nocase?: BaseQueryType;
28
+ $ends_with?: BaseQueryType;
29
+ $end_with_nocase?: BaseQueryType;
30
+ $starts_with?: BaseQueryType;
31
+ $starts_with_nocase?: BaseQueryType;
32
+ $not_contains?: BaseQueryType;
33
+ $not_contains_nocase?: BaseQueryType;
34
+ $not_ends_with?: BaseQueryType;
35
+ $not_ends_with_nocase?: BaseQueryType;
36
+ $not_starts_with?: BaseQueryType;
37
+ $not_starts_with_nocase?: BaseQueryType;
58
38
  };
59
39
 
60
40
  export type CommonWhereOptions = {
61
- gt?: BaseQueryType;
62
- gte?: BaseQueryType;
63
- lt?: BaseQueryType;
64
- lte?: BaseQueryType;
65
- not?: BaseQueryType;
66
- in?: BaseQueryType;
67
- not_in?: BaseQueryType;
41
+ $gt?: BaseQueryType;
42
+ $gte?: BaseQueryType;
43
+ $lt?: BaseQueryType;
44
+ $lte?: BaseQueryType;
45
+ $not?: BaseQueryType;
46
+ $in?: BaseQueryType;
47
+ $not_in?: BaseQueryType;
68
48
  };
69
49
 
70
50
  export type WhereOptions = TextWhereOptions & CommonWhereOptions;
@@ -77,10 +57,12 @@ export type Metadata = {
77
57
  blockQuery?: BlockQuery;
78
58
  };
79
59
 
80
- export type ElementType = string | { collection: string; params?: GraphParams };
60
+ export type ElementType = string | GraphObject;
61
+ export type InlineFragmentType = { collection: string; params?: Pick<GraphParams, 'elements'> };
81
62
 
82
63
  export interface GraphParams {
83
64
  elements?: Array<ElementType>;
65
+ inlineFragments?: Array<InlineFragmentType>;
84
66
  where?: QueryJson;
85
67
  id?: string;
86
68
  first?: number;
@@ -90,3 +72,8 @@ export interface GraphParams {
90
72
  subgraphError?: 'allow' | 'deny';
91
73
  block?: BlockQuery;
92
74
  }
75
+
76
+ export interface GraphObject {
77
+ collection: string;
78
+ params?: GraphParams;
79
+ }