@zengenti/contensis-react-base 3.0.0-beta.76 → 3.0.0-beta.79
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/cjs/contensis-react-base.js +531 -319
- package/cjs/contensis-react-base.js.map +1 -1
- package/cjs/forms.js +49 -21
- package/cjs/forms.js.map +1 -1
- package/cjs/setCachingHeaders-ee619bdf.js +12 -0
- package/cjs/setCachingHeaders-ee619bdf.js.map +1 -0
- package/cjs/util.js +199 -42
- package/cjs/util.js.map +1 -1
- package/esm/contensis-react-base.js +532 -320
- package/esm/contensis-react-base.js.map +1 -1
- package/esm/forms.js +49 -21
- package/esm/forms.js.map +1 -1
- package/esm/setCachingHeaders-d49060e1.js +10 -0
- package/esm/setCachingHeaders-d49060e1.js.map +1 -0
- package/esm/util.js +196 -41
- package/esm/util.js.map +1 -1
- package/models/app/pages/VersionInfo/components/VersionInfo.d.ts +1 -1
- package/models/redux/sagas/navigation.d.ts +1 -1
- package/models/server/features/linkdepth-api/LinkDepthSearchService.d.ts +24 -0
- package/models/server/features/linkdepth-api/QueryLevelResults.d.ts +50 -0
- package/models/server/features/linkdepth-api/search.d.ts +31 -0
- package/models/server/features/linkdepth-api/util.d.ts +11 -0
- package/models/user/hocs/withLogin.d.ts +2 -2
- package/models/user/hocs/withRegistration.d.ts +2 -2
- package/package.json +1 -1
- package/cjs/VersionInfo-4c9dfa6a.js +0 -181
- package/cjs/VersionInfo-4c9dfa6a.js.map +0 -1
- package/esm/VersionInfo-f5403b09.js +0 -172
- package/esm/VersionInfo-f5403b09.js.map +0 -1
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as cachedSearch, h as history, d as deliveryApi, p as pickProject, r as rootSaga } from './App-af0670fa.js';
|
|
2
|
+
export { A as ReactApp } from './App-af0670fa.js';
|
|
3
|
+
import { Query as Query$1 } from 'contensis-delivery-api';
|
|
2
4
|
import React from 'react';
|
|
3
5
|
import { Provider } from 'react-redux';
|
|
4
6
|
import { d as defaultExpressions, c as contentTypeIdExpression, f as filterExpressions, t as termExpressions, o as orderByExpression, a as customWhereExpressions } from './sagas-1f2b2aa0.js';
|
|
@@ -8,9 +10,8 @@ import 'deepmerge';
|
|
|
8
10
|
import 'query-string';
|
|
9
11
|
import 'immer';
|
|
10
12
|
import 'deep-equal';
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
export { A as ReactApp } from './App-af0670fa.js';
|
|
13
|
+
import { Op, Query } from 'contensis-core-api';
|
|
14
|
+
import { s as setCachingHeaders } from './setCachingHeaders-d49060e1.js';
|
|
14
15
|
import 'isomorphic-fetch';
|
|
15
16
|
import express from 'express';
|
|
16
17
|
import httpProxy from 'http-proxy';
|
|
@@ -31,11 +32,10 @@ import { CookiesProvider } from 'react-cookie';
|
|
|
31
32
|
import { c as createStore, s as setVersionStatus, a as setVersion } from './version-c7268214.js';
|
|
32
33
|
import { s as setCurrentProject } from './actions-fcfc8704.js';
|
|
33
34
|
import { s as selectSurrogateKeys, a as selectRouteEntry, b as selectCurrentProject, g as getImmutableOrJS } from './selectors-337be432.js';
|
|
34
|
-
import '
|
|
35
|
+
import 'history';
|
|
35
36
|
import '@redux-saga/core/effects';
|
|
36
|
-
import '
|
|
37
|
+
import 'loglevel';
|
|
37
38
|
import './version-6dd7b2cd.js';
|
|
38
|
-
import 'history';
|
|
39
39
|
import './login-ca2dc2f7.js';
|
|
40
40
|
import './reducers-8e5d6232.js';
|
|
41
41
|
import './ToJs-affd73f1.js';
|
|
@@ -48,254 +48,43 @@ import 'redux-thunk';
|
|
|
48
48
|
import 'redux-saga';
|
|
49
49
|
import 'redux-injectors';
|
|
50
50
|
|
|
51
|
-
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
52
|
-
|
|
53
51
|
/**
|
|
54
|
-
*
|
|
55
|
-
* The api supports a GET request and specified filters are supplied as query-string parameters.
|
|
56
|
-
* The response should be a normal Delivery API response.
|
|
57
|
-
* @param app Express app instance
|
|
58
|
-
* @param middlewareConfig Middleware configuration that represents the content types we want to search within, any filters that are required and any linkFields we wish to search within to derive a set of search results from the entries that contain the linkFields. Each key inside of linkFields represents another "linkDepth" of entries and we can specify all the same contentTypeId, filters, and linkFields of their own. There is no currently no limit on how deep these linkFields can go
|
|
59
|
-
* @returns Returns nothing if uri, contentTypeId or linkFields is not set in middlewareConfig
|
|
52
|
+
* Util class holds our search results helper boilerplate methods
|
|
60
53
|
*/
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
} = middlewareConfig;
|
|
67
|
-
if (!contentTypeId || !linkFields || !uri) return;
|
|
68
|
-
app.get(uri, makeLinkDepthMiddleware(middlewareConfig));
|
|
69
|
-
};
|
|
70
|
-
/** Create a content type hierarchy from supplied config and produces
|
|
71
|
-
* a RequestHandler function to serve our Express middleware */
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const makeLinkDepthMiddleware = ({
|
|
75
|
-
contentTypeId,
|
|
76
|
-
filters,
|
|
77
|
-
sharedFilters,
|
|
78
|
-
linkFields
|
|
79
|
-
}) => {
|
|
80
|
-
try {
|
|
81
|
-
// Recursive function to flatten and index a provided nested config
|
|
82
|
-
const returnFieldIdKeys = (obj, level = 1) => {
|
|
83
|
-
var _Object$entries$map;
|
|
84
|
-
|
|
85
|
-
if (!obj) return {};
|
|
86
|
-
const mappedConfig = Object.entries(obj).map(([k, v]) => ({
|
|
87
|
-
contentTypeIds: Array.isArray(v.contentTypeId) ? v.contentTypeId : [v.contentTypeId || k],
|
|
88
|
-
fieldId: k,
|
|
89
|
-
filters: v.filters,
|
|
90
|
-
sharedFilters: v.sharedFilters
|
|
91
|
-
}));
|
|
92
|
-
const inner = (_Object$entries$map = Object.entries(obj).map(([k, v]) => returnFieldIdKeys(v.linkFields, level + 1))) === null || _Object$entries$map === void 0 ? void 0 : _Object$entries$map[0];
|
|
93
|
-
return {
|
|
94
|
-
[level]: mappedConfig,
|
|
95
|
-
...inner
|
|
96
|
-
};
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
const others = returnFieldIdKeys(linkFields); // Level 0 is read from the top-level of config
|
|
100
|
-
|
|
101
|
-
const contentTypeHierarchy = {
|
|
102
|
-
0: [{
|
|
103
|
-
contentTypeIds: Array.isArray(contentTypeId) ? contentTypeId : [contentTypeId],
|
|
104
|
-
filters,
|
|
105
|
-
sharedFilters
|
|
106
|
-
}],
|
|
107
|
-
...others
|
|
108
|
-
}; // The runtime express request handler
|
|
109
|
-
|
|
110
|
-
const linkDepthMiddleware = async (req, res) => {
|
|
111
|
-
try {
|
|
112
|
-
// Short cache duration copied from canterbury project
|
|
113
|
-
setCachingHeaders(res, {
|
|
114
|
-
cacheControl: 'private',
|
|
115
|
-
surrogateControl: '10'
|
|
116
|
-
}); // Run our queries and provide a final result
|
|
117
|
-
// our params are sourced from the query-string
|
|
118
|
-
|
|
119
|
-
const result = await searchEventsTopDown(contentTypeHierarchy, req.query); // const result = await searchLinkDepthEntries(
|
|
120
|
-
// contentTypeHierarchy,
|
|
121
|
-
// req.query
|
|
122
|
-
// );
|
|
54
|
+
class Util {
|
|
55
|
+
static GetIds(entries, fieldId) {
|
|
56
|
+
if (fieldId) {
|
|
57
|
+
return entries === null || entries === void 0 ? void 0 : entries.map(e => {
|
|
58
|
+
var _e$fieldId, _e$fieldId2, _e$fieldId2$sys;
|
|
123
59
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
// This is a runtime error encountered when processing a given request
|
|
127
|
-
console.error(error);
|
|
128
|
-
res.statusCode = 500;
|
|
129
|
-
res.json(error);
|
|
130
|
-
}
|
|
131
|
-
};
|
|
60
|
+
return Array.isArray(e === null || e === void 0 ? void 0 : e[fieldId]) ? e === null || e === void 0 ? void 0 : (_e$fieldId = e[fieldId]) === null || _e$fieldId === void 0 ? void 0 : _e$fieldId.map(f => {
|
|
61
|
+
var _f$sys;
|
|
132
62
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
console.error(error);
|
|
63
|
+
return f === null || f === void 0 ? void 0 : (_f$sys = f.sys) === null || _f$sys === void 0 ? void 0 : _f$sys.id;
|
|
64
|
+
}) : (e === null || e === void 0 ? void 0 : (_e$fieldId2 = e[fieldId]) === null || _e$fieldId2 === void 0 ? void 0 : (_e$fieldId2$sys = _e$fieldId2.sys) === null || _e$fieldId2$sys === void 0 ? void 0 : _e$fieldId2$sys.id) || '';
|
|
65
|
+
}).flat();
|
|
66
|
+
}
|
|
138
67
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
res.json(JSON.stringify(error));
|
|
142
|
-
};
|
|
68
|
+
return entries === null || entries === void 0 ? void 0 : entries.map(e => {
|
|
69
|
+
var _e$sys;
|
|
143
70
|
|
|
144
|
-
|
|
71
|
+
return (e === null || e === void 0 ? void 0 : (_e$sys = e.sys) === null || _e$sys === void 0 ? void 0 : _e$sys.id) || '';
|
|
72
|
+
});
|
|
145
73
|
}
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
const getVarsFromConfig = (config, params) => {
|
|
149
|
-
// Build variables from query config to use in our Delivery API Query
|
|
150
|
-
const contentTypeIds = config.map(c => c.contentTypeIds).flat(); // Filters are the filters we are looking to include with the Query at this level
|
|
151
|
-
|
|
152
|
-
let filters = {}; // Shared filters are filters that share the same querystring key and are valid in multiple levels
|
|
153
|
-
|
|
154
|
-
let sharedFilters = {};
|
|
155
|
-
config.forEach(c => {
|
|
156
|
-
filters = { ...filters,
|
|
157
|
-
...c.filters
|
|
158
|
-
};
|
|
159
|
-
sharedFilters = { ...sharedFilters,
|
|
160
|
-
...c.sharedFilters
|
|
161
|
-
};
|
|
162
|
-
}); // FieldIds are the field name(s) in the parent/current entry that the
|
|
163
|
-
// entries are linked to, used to surface the next level based on id
|
|
164
|
-
// retrieved at the previous level
|
|
165
|
-
|
|
166
|
-
const fieldIds = config.map(c => c.fieldId).flat();
|
|
167
|
-
const queryFilters = makeFilterExpressions(filters, params);
|
|
168
|
-
const sharedQueryFilters = makeFilterExpressions(sharedFilters, params);
|
|
169
|
-
return {
|
|
170
|
-
contentTypeIds,
|
|
171
|
-
fieldIds,
|
|
172
|
-
filters,
|
|
173
|
-
queryFilters,
|
|
174
|
-
sharedFilters,
|
|
175
|
-
sharedQueryFilters
|
|
176
|
-
};
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
const makeDerivedIdsFilterExpression = (level, resultsAtLevel, ownIds = false, useFieldIds = false) => {
|
|
180
|
-
const previouslyDerivedIdsFilter = [];
|
|
181
|
-
const [prevFieldId, entries] = resultsAtLevel[level];
|
|
182
|
-
const prevKey = prevFieldId;
|
|
183
|
-
const prevResultIds = Util.GetIds(entries, useFieldIds ? prevFieldId : undefined);
|
|
184
|
-
if (prevKey && (prevResultIds === null || prevResultIds === void 0 ? void 0 : prevResultIds.length) > 0) previouslyDerivedIdsFilter.push({
|
|
185
|
-
key: ownIds ? 'sys.id' : `${prevFieldId}.sys.id`,
|
|
186
|
-
values: prevResultIds,
|
|
187
|
-
fieldOperator: 'in'
|
|
188
|
-
});else previouslyDerivedIdsFilter.push({
|
|
189
|
-
key: 'dud',
|
|
190
|
-
values: ['1'],
|
|
191
|
-
fieldOperator: 'in'
|
|
192
|
-
});
|
|
193
|
-
return previouslyDerivedIdsFilter;
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
const searchEventsTopDown = async (contentTypeHierarchy, params) => {
|
|
197
|
-
// Determine linkDepth for the final query by how many levels are in
|
|
198
|
-
// the contentTypeHierarchy object
|
|
199
|
-
const linkDepth = Object.keys(contentTypeHierarchy).length - 1 || 0; // Pre-size our results array to the size of our hierarchy
|
|
200
|
-
|
|
201
|
-
const resultsAtLevel = Object.values(contentTypeHierarchy).map((v, i, a) => {
|
|
202
|
-
const fieldId = i === 0 ? a[i + 1][0] : v[0];
|
|
203
|
-
return [fieldId.fieldId, []];
|
|
204
|
-
}); // [fieldId, results][]
|
|
205
|
-
|
|
206
|
-
for (const [level, levelConfig] of Object.entries(contentTypeHierarchy)) {
|
|
207
|
-
// LinkDepth level / current index
|
|
208
|
-
const currentLevel = Number(level); // Build variables from query config to use in our Delivery API Query
|
|
209
74
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
queryFilters,
|
|
214
|
-
sharedQueryFilters
|
|
215
|
-
} = getVarsFromConfig(levelConfig, params); // We won't have fetched any derived results to
|
|
216
|
-
// include as a field filter with the very first query
|
|
217
|
-
|
|
218
|
-
let previouslyDerivedIdsFilter = [];
|
|
75
|
+
static GetItems(result) {
|
|
76
|
+
return this.GetResults(result) ? result.items : [];
|
|
77
|
+
}
|
|
219
78
|
|
|
220
|
-
|
|
221
|
-
|
|
79
|
+
static GetResults(result) {
|
|
80
|
+
if (result !== null && result !== void 0 && result.items) {
|
|
81
|
+
return result;
|
|
82
|
+
} else {
|
|
83
|
+
return null;
|
|
222
84
|
}
|
|
85
|
+
}
|
|
223
86
|
|
|
224
|
-
|
|
225
|
-
contentTypeIds,
|
|
226
|
-
filters: queryFilters,
|
|
227
|
-
idFilters: previouslyDerivedIdsFilter,
|
|
228
|
-
sharedFilters: sharedQueryFilters,
|
|
229
|
-
versionStatus: params.versionStatus || 'published'
|
|
230
|
-
}); // These are all sub-queries, we only want ids returned in these to include
|
|
231
|
-
// them to filter by in our next level(s) queries, along with any other filters
|
|
232
|
-
// configured and found at this level
|
|
233
|
-
|
|
234
|
-
query.fields = currentLevel === 0 ? [] : ['sys.id']; // Scalability limitation for today
|
|
235
|
-
|
|
236
|
-
query.pageSize = 2000;
|
|
237
|
-
const levelQueryResult = await cachedSearch.searchUsingPost(query, 0);
|
|
238
|
-
resultsAtLevel[currentLevel][1] = Util.GetItems(levelQueryResult);
|
|
239
|
-
} // Build and run our final query containing all results
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
const {
|
|
243
|
-
contentTypeIds,
|
|
244
|
-
queryFilters,
|
|
245
|
-
sharedQueryFilters
|
|
246
|
-
} = getVarsFromConfig(Object.values(contentTypeHierarchy)[0], params);
|
|
247
|
-
const previouslyDerivedIdsFilter = makeDerivedIdsFilterExpression(1, resultsAtLevel);
|
|
248
|
-
const query = finalQuery({
|
|
249
|
-
contentTypeIds,
|
|
250
|
-
filters: queryFilters,
|
|
251
|
-
idFilters: previouslyDerivedIdsFilter,
|
|
252
|
-
sharedFilters: sharedQueryFilters,
|
|
253
|
-
versionStatus: params.versionStatus || 'published'
|
|
254
|
-
}, Object.entries(contentTypeHierarchy).filter(([k]) => k !== '0').map(([level, levelConfig]) => {
|
|
255
|
-
// LinkDepth level / current index
|
|
256
|
-
const currentLevel = Number(level); // Build variables from query config to use in our Delivery API Query
|
|
257
|
-
|
|
258
|
-
const {
|
|
259
|
-
contentTypeIds,
|
|
260
|
-
queryFilters,
|
|
261
|
-
sharedQueryFilters
|
|
262
|
-
} = getVarsFromConfig(levelConfig, params);
|
|
263
|
-
const previousIdsFilter = makeDerivedIdsFilterExpression(currentLevel, resultsAtLevel, true);
|
|
264
|
-
return {
|
|
265
|
-
contentTypeIds,
|
|
266
|
-
filters: queryFilters,
|
|
267
|
-
idFilters: previousIdsFilter,
|
|
268
|
-
sharedFilters: sharedQueryFilters,
|
|
269
|
-
versionStatus: params.versionStatus || 'published'
|
|
270
|
-
};
|
|
271
|
-
})); // This is the final query to be run and response returned to the caller
|
|
272
|
-
// Only this bit cares about linkDepth, fields and pagination parameters
|
|
273
|
-
|
|
274
|
-
query.fields = JSON.parse(params.fields || '[]');
|
|
275
|
-
query.pageSize = params.pageSize;
|
|
276
|
-
query.pageIndex = params.pageIndex;
|
|
277
|
-
query.orderBy = params.orderBy; // console.log(JSON.stringify(query.toJSON()));
|
|
278
|
-
|
|
279
|
-
const finalQueryResult = await cachedSearch.searchUsingPost(query, linkDepth);
|
|
280
|
-
const entriesWithResolvedParents = await resolveParentEntries(contentTypeIds, Array.from(new Set(resultsAtLevel[1][1].map(e => e.sys.contentTypeId || ''))), resultsAtLevel[0][0], Util.GetItems(finalQueryResult), params);
|
|
281
|
-
return { ...finalQueryResult,
|
|
282
|
-
items: entriesWithResolvedParents
|
|
283
|
-
};
|
|
284
|
-
};
|
|
285
|
-
|
|
286
|
-
const resolveParentEntries = async (parentContentTypeIds, replaceContentTypeIds, parentFieldId, results, params) => {
|
|
287
|
-
// Build variables from query config to use in our Delivery API Query
|
|
288
|
-
const previousIdsFilter = makeDerivedIdsFilterExpression(0, [[parentFieldId, results]]);
|
|
289
|
-
const query = searchQuery({
|
|
290
|
-
contentTypeIds: parentContentTypeIds,
|
|
291
|
-
idFilters: previousIdsFilter
|
|
292
|
-
});
|
|
293
|
-
query.fields = JSON.parse(params.fields || '[]');
|
|
294
|
-
console.log(JSON.stringify(query.toJSON()));
|
|
295
|
-
const parentResults = await cachedSearch.search(query, 0);
|
|
296
|
-
return mergeResults(results, Util.GetItems(parentResults), replaceContentTypeIds, parentFieldId);
|
|
297
|
-
};
|
|
298
|
-
|
|
87
|
+
}
|
|
299
88
|
const mergeResults = (results, parentResults, replaceContentTypeIds, linkFieldId) => results.map(r => {
|
|
300
89
|
if (replaceContentTypeIds.some(c => c === r.sys.contentTypeId)) {
|
|
301
90
|
const resolvedParent = parentResults === null || parentResults === void 0 ? void 0 : parentResults.find(e => {
|
|
@@ -319,30 +108,32 @@ const mergeResults = (results, parentResults, replaceContentTypeIds, linkFieldId
|
|
|
319
108
|
return r;
|
|
320
109
|
}).filter(r => r);
|
|
321
110
|
|
|
322
|
-
|
|
111
|
+
/* eslint-disable no-console */
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Builds our complete Delivery API Query object from a set of provided arguments
|
|
115
|
+
* @param queryParams
|
|
116
|
+
* @returns Delivery API Query
|
|
117
|
+
*/
|
|
118
|
+
const searchQuery = ({
|
|
323
119
|
assetTypes,
|
|
324
120
|
contentTypeIds,
|
|
121
|
+
customWhere,
|
|
325
122
|
fields,
|
|
326
123
|
filters,
|
|
327
|
-
idFilters,
|
|
328
|
-
sharedFilters,
|
|
124
|
+
idFilters = [],
|
|
125
|
+
sharedFilters = [],
|
|
329
126
|
pageSize,
|
|
330
|
-
pageIndex,
|
|
127
|
+
pageIndex = 0,
|
|
331
128
|
orderBy,
|
|
332
129
|
searchTerm,
|
|
333
130
|
versionStatus = 'published',
|
|
334
131
|
webpageTemplates,
|
|
335
132
|
weightedSearchFields
|
|
336
|
-
}
|
|
337
|
-
const expressions$1 = [...defaultExpressions(versionStatus),
|
|
338
|
-
// ...sharedFilters.map(sf =>
|
|
339
|
-
// Op.not(exp.fieldExpression(sf.key, true, 'exists')[0])
|
|
340
|
-
// ),
|
|
341
|
-
// ...exp.filterExpressions(idFilters)
|
|
342
|
-
// )
|
|
343
|
-
)), ...children.map(child => Op.and(...contentTypeIdExpression(child.contentTypeIds, child.webpageTemplates, child.assetTypes), ...filterExpressions(child.sharedFilters), ...filterExpressions(child.idFilters)))), ...termExpressions(searchTerm, weightedSearchFields)];
|
|
133
|
+
}) => {
|
|
134
|
+
const expressions$1 = [...defaultExpressions(versionStatus), ...contentTypeIdExpression(contentTypeIds, webpageTemplates, assetTypes), ...customWhereExpressions(customWhere), ...filterExpressions(filters), ...filterExpressions(idFilters), ...((sharedFilters === null || sharedFilters === void 0 ? void 0 : sharedFilters.length) > 0 ? [Op.or(...filterExpressions(sharedFilters, true))] : []), ...termExpressions(searchTerm || '', weightedSearchFields || [])];
|
|
344
135
|
const query = new Query(...expressions$1);
|
|
345
|
-
query.orderBy = orderByExpression(orderBy);
|
|
136
|
+
query.orderBy = orderByExpression(orderBy || []);
|
|
346
137
|
|
|
347
138
|
if (fields && fields.length > 0) {
|
|
348
139
|
query.fields = fields;
|
|
@@ -354,38 +145,12 @@ const finalQuery = ({
|
|
|
354
145
|
query.pageSize = pageSize;
|
|
355
146
|
return query;
|
|
356
147
|
};
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
* @param f filters configuration from any level
|
|
362
|
-
* @param params request.query object from Express middleware
|
|
363
|
-
* @returns FilterExpression[] we can use to use with searchQuery function
|
|
364
|
-
*/
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
const makeFilterExpressions = (f, params) => Object.entries(f).map(([paramKey, filterConfig]) => {
|
|
368
|
-
var _params$paramKey;
|
|
369
|
-
|
|
370
|
-
const filterValues = (_params$paramKey = params[paramKey]) === null || _params$paramKey === void 0 ? void 0 : _params$paramKey.split(',');
|
|
371
|
-
return typeof filterValues !== 'undefined' ? {
|
|
372
|
-
key: typeof filterConfig === 'object' ? filterConfig.fieldId : filterConfig,
|
|
373
|
-
values: filterValues,
|
|
374
|
-
fieldOperator: typeof filterConfig === 'object' ? filterConfig.fieldOperator : 'equalTo',
|
|
375
|
-
logicOperator: typeof filterConfig === 'object' ? filterConfig.logicOperator : 'or'
|
|
376
|
-
} : null;
|
|
377
|
-
}).filter(o => o);
|
|
378
|
-
/**
|
|
379
|
-
* Builds our complete Delivery API Query object from a set of provided arguments
|
|
380
|
-
* @param queryParams
|
|
381
|
-
* @returns Delivery API Query
|
|
382
|
-
*/
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
const searchQuery = ({
|
|
148
|
+
const appendSearchQueryFilters = (query, idFilters) => {
|
|
149
|
+
query.where.addRange(filterExpressions(idFilters));
|
|
150
|
+
};
|
|
151
|
+
const finalQuery = ({
|
|
386
152
|
assetTypes,
|
|
387
153
|
contentTypeIds,
|
|
388
|
-
customWhere,
|
|
389
154
|
fields,
|
|
390
155
|
filters,
|
|
391
156
|
idFilters,
|
|
@@ -397,10 +162,16 @@ const searchQuery = ({
|
|
|
397
162
|
versionStatus = 'published',
|
|
398
163
|
webpageTemplates,
|
|
399
164
|
weightedSearchFields
|
|
400
|
-
}) => {
|
|
401
|
-
const expressions$1 = [...defaultExpressions(versionStatus), ...contentTypeIdExpression(contentTypeIds, webpageTemplates, assetTypes), ...
|
|
165
|
+
}, children) => {
|
|
166
|
+
const expressions$1 = [...defaultExpressions(versionStatus), Op.or(Op.and(...contentTypeIdExpression(contentTypeIds, webpageTemplates, assetTypes), ...filterExpressions(filters), ...filterExpressions(idFilters || []), ...(sharedFilters !== null && sharedFilters !== void 0 && sharedFilters.length ? [Op.or(...filterExpressions(sharedFilters || []) // Op.and(
|
|
167
|
+
// ...sharedFilters.map(sf =>
|
|
168
|
+
// Op.not(exp.fieldExpression(sf.key, true, 'exists')[0])
|
|
169
|
+
// ),
|
|
170
|
+
// ...exp.filterExpressions(idFilters)
|
|
171
|
+
// )
|
|
172
|
+
)] : [])), ...children.map(child => Op.and(...contentTypeIdExpression(child.contentTypeIds, child.webpageTemplates, child.assetTypes), ...filterExpressions(child.sharedFilters || []), ...filterExpressions(child.idFilters || [])))), ...termExpressions(searchTerm || '', weightedSearchFields || [])];
|
|
402
173
|
const query = new Query(...expressions$1);
|
|
403
|
-
query.orderBy = orderByExpression(orderBy);
|
|
174
|
+
query.orderBy = orderByExpression(orderBy || []);
|
|
404
175
|
|
|
405
176
|
if (fields && fields.length > 0) {
|
|
406
177
|
query.fields = fields;
|
|
@@ -408,50 +179,489 @@ const searchQuery = ({
|
|
|
408
179
|
// (query as any).includeDeleted = true;
|
|
409
180
|
|
|
410
181
|
|
|
411
|
-
query.pageIndex = pageIndex;
|
|
182
|
+
query.pageIndex = pageIndex || 0;
|
|
412
183
|
query.pageSize = pageSize;
|
|
413
184
|
return query;
|
|
414
185
|
};
|
|
415
186
|
/**
|
|
416
|
-
*
|
|
187
|
+
* Create a filter expression from a provided filters configuration object
|
|
188
|
+
* and populate them based on the presence of that key in params, filter
|
|
189
|
+
* out any filter keys that do not have a value set in params
|
|
190
|
+
* @param f filters configuration from any level
|
|
191
|
+
* @param params request.query object from Express middleware
|
|
192
|
+
* @returns FilterExpression[] we can use to use with searchQuery function
|
|
417
193
|
*/
|
|
418
194
|
|
|
195
|
+
const makeFilterExpressions = (f, params) => {
|
|
196
|
+
const expressions = [];
|
|
419
197
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
if (fieldId) {
|
|
423
|
-
return entries.map(e => {
|
|
424
|
-
var _e$fieldId, _e$fieldId2, _e$fieldId2$sys;
|
|
198
|
+
for (const [paramKey, filterConfig] of Object.entries(f)) {
|
|
199
|
+
var _params$paramKey;
|
|
425
200
|
|
|
426
|
-
|
|
427
|
-
|
|
201
|
+
const filterValues = (_params$paramKey = params[paramKey]) === null || _params$paramKey === void 0 ? void 0 : _params$paramKey.split(',');
|
|
202
|
+
if (typeof filterValues !== 'undefined') expressions.push({
|
|
203
|
+
key: typeof filterConfig === 'object' ? filterConfig.fieldId : filterConfig,
|
|
204
|
+
values: filterValues,
|
|
205
|
+
fieldOperator: typeof filterConfig === 'object' && filterConfig.fieldOperator ? filterConfig.fieldOperator : 'equalTo',
|
|
206
|
+
logicOperator: typeof filterConfig === 'object' && filterConfig.logicOperator ? filterConfig.logicOperator : 'or'
|
|
207
|
+
});
|
|
208
|
+
}
|
|
428
209
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
210
|
+
return expressions;
|
|
211
|
+
};
|
|
212
|
+
const makeDerivedIdsFilterExpression = (prevFieldId, entries, ownIds = false, alwaysApplyFilter = false) => {
|
|
213
|
+
const previouslyDerivedIdsFilter = [];
|
|
214
|
+
const prevResultIds = Util.GetIds(entries);
|
|
215
|
+
if (prevFieldId && (prevResultIds === null || prevResultIds === void 0 ? void 0 : prevResultIds.length) > 0) previouslyDerivedIdsFilter.push({
|
|
216
|
+
key: ownIds ? 'sys.id' : `${prevFieldId}.sys.id`,
|
|
217
|
+
values: prevResultIds,
|
|
218
|
+
fieldOperator: 'in',
|
|
219
|
+
logicOperator: 'or'
|
|
220
|
+
});else if (alwaysApplyFilter) previouslyDerivedIdsFilter.push({
|
|
221
|
+
key: 'intended-dud',
|
|
222
|
+
values: ['1'],
|
|
223
|
+
fieldOperator: 'in',
|
|
224
|
+
logicOperator: 'or'
|
|
225
|
+
});
|
|
226
|
+
return previouslyDerivedIdsFilter;
|
|
227
|
+
};
|
|
228
|
+
const resolveParentEntries = async (parentContentTypeIds, replaceContentTypeIds, parentFieldId, results, params, debug) => {
|
|
229
|
+
// Build variables from query config to use in our Delivery API Query
|
|
230
|
+
const previousIdsFilter = makeDerivedIdsFilterExpression(parentFieldId, results);
|
|
231
|
+
const query = searchQuery({
|
|
232
|
+
contentTypeIds: parentContentTypeIds,
|
|
233
|
+
idFilters: previousIdsFilter
|
|
234
|
+
});
|
|
235
|
+
query.fields = params.fields ? [...JSON.parse(params.fields), parentFieldId] : [];
|
|
236
|
+
if (debug) console.log(`\nResolve parent entries query: \n${JSON.stringify(query.toJSON()).substring(0, 1000)}`);
|
|
237
|
+
const parentResults = await cachedSearch.searchUsingPost(query, Number(params.linkDepth || 0), params.projectId);
|
|
238
|
+
return mergeResults(results, Util.GetItems(parentResults), replaceContentTypeIds, parentFieldId);
|
|
239
|
+
};
|
|
433
240
|
|
|
434
|
-
|
|
435
|
-
var _e$sys;
|
|
241
|
+
/* eslint-disable no-console */
|
|
436
242
|
|
|
437
|
-
|
|
243
|
+
class QueryLevelResults {
|
|
244
|
+
constructor({
|
|
245
|
+
level: _level,
|
|
246
|
+
contentTypeIds,
|
|
247
|
+
linkFields,
|
|
248
|
+
filters,
|
|
249
|
+
sharedFilters,
|
|
250
|
+
returnEntries,
|
|
251
|
+
resolveFirstParent,
|
|
252
|
+
params: _params = {},
|
|
253
|
+
parent: _parent,
|
|
254
|
+
debug = false
|
|
255
|
+
}) {
|
|
256
|
+
this.level = void 0;
|
|
257
|
+
this.contentTypeIds = void 0;
|
|
258
|
+
this.linkFieldIds = void 0;
|
|
259
|
+
this.linkFields = void 0;
|
|
260
|
+
this.filters = void 0;
|
|
261
|
+
this.sharedFilters = void 0;
|
|
262
|
+
this.returnEntries = void 0;
|
|
263
|
+
this.resolveFirstParent = void 0;
|
|
264
|
+
this.validatedLinks = [];
|
|
265
|
+
this.parent = void 0;
|
|
266
|
+
this.children = [];
|
|
267
|
+
this.runFirstQuery = void 0;
|
|
268
|
+
this.runFinalQuery = void 0;
|
|
269
|
+
this.params = {};
|
|
270
|
+
this.debug = void 0;
|
|
271
|
+
this.firstQuery = new Query$1();
|
|
272
|
+
this.firstResults = {};
|
|
273
|
+
this.finalQuery = new Query$1();
|
|
274
|
+
this.finalResults = {};
|
|
275
|
+
|
|
276
|
+
this.AddChild = ({
|
|
277
|
+
child
|
|
278
|
+
}) => {
|
|
279
|
+
this.children.push(child);
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
this.RunFirstQuery = async () => {
|
|
283
|
+
const {
|
|
284
|
+
firstQuery: query,
|
|
285
|
+
params,
|
|
286
|
+
parent,
|
|
287
|
+
runFirstQuery
|
|
288
|
+
} = this;
|
|
289
|
+
|
|
290
|
+
if (parent !== null && parent !== void 0 && parent.validatedLinks.length) {
|
|
291
|
+
// add any idFilters derived from parent query results
|
|
292
|
+
appendSearchQueryFilters(query, makeFilterExpressions(Object.fromEntries(parent.validatedLinks.map(vl => [vl.linkFieldId, {
|
|
293
|
+
fieldId: `sys.id`
|
|
294
|
+
}])), Object.fromEntries(parent.validatedLinks.map(vl => [vl.linkFieldId, vl.entryIds.join(',') || `no ids from parent ${parent.level}`]))));
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (runFirstQuery) {
|
|
298
|
+
if (this.debug) console.log(`\nLevel ${this.level} - First query: \n${JSON.stringify(query.toJSON()).substring(0, 1000)}`);
|
|
299
|
+
this.firstResults = await cachedSearch.searchUsingPost(query, 0, params.projectId); // mapResultsToValidatedLinks
|
|
300
|
+
|
|
301
|
+
for (const linkFieldId of this.linkFieldIds) {
|
|
302
|
+
this.validatedLinks.push({
|
|
303
|
+
contentTypeId: this.linkFields[linkFieldId].contentTypeId || '',
|
|
304
|
+
linkFieldId,
|
|
305
|
+
entryIds: Util.GetIds(this.firstResults.items, linkFieldId)
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
this.RunFinalQuery = async () => {
|
|
312
|
+
const {
|
|
313
|
+
level,
|
|
314
|
+
children,
|
|
315
|
+
finalQuery: query,
|
|
316
|
+
params,
|
|
317
|
+
runFinalQuery
|
|
318
|
+
} = this;
|
|
319
|
+
|
|
320
|
+
if (!children.some(c => c.returnEntries)) {
|
|
321
|
+
const firstChild = children === null || children === void 0 ? void 0 : children[0]; // add any idFilters derived from child query results
|
|
322
|
+
|
|
323
|
+
if (firstChild) appendSearchQueryFilters(query, makeFilterExpressions(Object.fromEntries(firstChild.validatedLinks.map(vl => [vl.linkFieldId, {
|
|
324
|
+
fieldId: `${vl.linkFieldId}.sys.id`
|
|
325
|
+
}])), Object.fromEntries(firstChild.validatedLinks.map(vl => [vl.linkFieldId, vl.entryIds.join(',') || `no ids from child ${firstChild.level}`]))));
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (level === 0 && this.returnEntries) {
|
|
329
|
+
// This is the final query to be run and response returned to the caller
|
|
330
|
+
// Only this bit cares about linkDepth, fields and pagination parameters
|
|
331
|
+
query.fields = JSON.parse(params.fields || '[]');
|
|
332
|
+
query.pageSize = params.pageSize;
|
|
333
|
+
query.pageIndex = params.pageIndex; // query.orderBy = params.orderBy;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if (runFinalQuery) {
|
|
337
|
+
if (this.debug) console.log(`\nLevel ${this.level} - Final query: \n${JSON.stringify(query.toJSON()).substring(0, 1000)}`);
|
|
338
|
+
this.finalResults = await cachedSearch.searchUsingPost(query, Number(params.linkDepth) || 0, params.projectId);
|
|
339
|
+
if (this.parent) this.parent.runFinalQuery = true; // mapResultsToValidatedLinks
|
|
340
|
+
|
|
341
|
+
for (const linkFieldId of ((_this$parent = this.parent) === null || _this$parent === void 0 ? void 0 : _this$parent.linkFieldIds) || []) {
|
|
342
|
+
var _this$parent, _this$parent2;
|
|
343
|
+
|
|
344
|
+
this.validatedLinks.push({
|
|
345
|
+
contentTypeId: ((_this$parent2 = this.parent) === null || _this$parent2 === void 0 ? void 0 : _this$parent2.linkFields[linkFieldId].contentTypeId) || '',
|
|
346
|
+
linkFieldId,
|
|
347
|
+
entryIds: Util.GetIds(this.finalResults.items)
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
this.GetResultsEntries = () => {
|
|
354
|
+
var _finalResults$items;
|
|
355
|
+
|
|
356
|
+
const {
|
|
357
|
+
finalResults,
|
|
358
|
+
firstResults
|
|
359
|
+
} = this;
|
|
360
|
+
return finalResults !== null && finalResults !== void 0 && (_finalResults$items = finalResults.items) !== null && _finalResults$items !== void 0 && _finalResults$items.length ? finalResults.items : firstResults.items;
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
this.GetResults = () => {
|
|
364
|
+
const {
|
|
365
|
+
finalResults,
|
|
366
|
+
firstResults
|
|
367
|
+
} = this;
|
|
368
|
+
return typeof (finalResults === null || finalResults === void 0 ? void 0 : finalResults.totalCount) !== 'undefined' ? finalResults : firstResults;
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
this.level = _level;
|
|
372
|
+
this.contentTypeIds = contentTypeIds;
|
|
373
|
+
this.linkFields = linkFields;
|
|
374
|
+
this.linkFieldIds = Object.keys(linkFields).map(fId => fId);
|
|
375
|
+
this.filters = filters;
|
|
376
|
+
this.sharedFilters = sharedFilters;
|
|
377
|
+
this.returnEntries = typeof returnEntries === 'undefined' ? _level === 0 : returnEntries;
|
|
378
|
+
this.resolveFirstParent = resolveFirstParent || false;
|
|
379
|
+
this.params = _params;
|
|
380
|
+
this.parent = _parent;
|
|
381
|
+
this.debug = debug;
|
|
382
|
+
this.runFirstQuery = Object.keys(_params).some(p => Object.keys(filters).includes(p) || Object.keys(sharedFilters).includes(p));
|
|
383
|
+
this.runFinalQuery = Object.keys(_params).some(p => Object.keys(filters).includes(p) || Object.keys(sharedFilters).includes(p));
|
|
384
|
+
this.firstQuery = searchQuery({
|
|
385
|
+
contentTypeIds,
|
|
386
|
+
filters: makeFilterExpressions(filters, _params),
|
|
387
|
+
sharedFilters: makeFilterExpressions(sharedFilters, _params),
|
|
388
|
+
// idFilters: parent?.validatedLinks
|
|
389
|
+
// ? makeFilterExpressions(parent.validatedLinks, params)
|
|
390
|
+
// : [], // these dont exist yet
|
|
391
|
+
fields: ['sys.id', ...this.linkFieldIds],
|
|
392
|
+
pageSize: 2000,
|
|
393
|
+
searchTerm: _params.term,
|
|
394
|
+
versionStatus: _params.versionStatus
|
|
395
|
+
});
|
|
396
|
+
this.finalQuery = searchQuery({
|
|
397
|
+
contentTypeIds,
|
|
398
|
+
filters: makeFilterExpressions(filters, _params),
|
|
399
|
+
sharedFilters: makeFilterExpressions(sharedFilters, _params),
|
|
400
|
+
fields: JSON.parse(_params.fields || '[]'),
|
|
401
|
+
pageIndex: _level === 0 ? Number(_params.pageIndex) : 0,
|
|
402
|
+
pageSize: _level === 0 ? Number(_params.pageSize) : 2000,
|
|
403
|
+
searchTerm: _params.term,
|
|
404
|
+
versionStatus: _params.versionStatus
|
|
438
405
|
});
|
|
439
406
|
}
|
|
440
407
|
|
|
441
|
-
|
|
442
|
-
return this.GetResults(result) ? result.items : [];
|
|
443
|
-
}
|
|
408
|
+
}
|
|
444
409
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
}
|
|
410
|
+
/* eslint-disable no-console */
|
|
411
|
+
|
|
412
|
+
class LinkDepthSearchService {
|
|
413
|
+
constructor({
|
|
414
|
+
contentTypeId: _contentTypeId = '',
|
|
415
|
+
filters: _filters = {},
|
|
416
|
+
sharedFilters: _sharedFilters = {},
|
|
417
|
+
linkFields: _linkFields = {},
|
|
418
|
+
params: _params,
|
|
419
|
+
debug = false
|
|
420
|
+
}) {
|
|
421
|
+
this.contentTypeIds = void 0;
|
|
422
|
+
this.filters = void 0;
|
|
423
|
+
this.sharedFilters = void 0;
|
|
424
|
+
this.linkFields = void 0;
|
|
425
|
+
this.params = void 0;
|
|
426
|
+
this.debug = void 0;
|
|
427
|
+
this.queryLevels = void 0;
|
|
428
|
+
|
|
429
|
+
this.DoSearch = async () => {
|
|
430
|
+
// Run queries "top-down" through each level of `linkField`
|
|
431
|
+
for (const queryLevel of this.queryLevels) {
|
|
432
|
+
await queryLevel.RunFirstQuery();
|
|
433
|
+
} // Run queries "bottom-up" through each level of `linkField`
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
for (const queryLevel of [...this.queryLevels].reverse()) {
|
|
437
|
+
await queryLevel.RunFinalQuery();
|
|
438
|
+
} // Run a final query that will aggregate the results from all levels
|
|
439
|
+
// adding all levels to the query that have `returnEntries` set true
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
return await this.RunFinalQueries();
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
this.RunFinalQueries = async () => {
|
|
446
|
+
const finalQueryLevels = this.queryLevels.filter(ql => ql.level > 0 && ql.returnEntries || ql.level === 0 && ql.returnEntries !== false); // Decide if we need a further final query if any child level(s) have had `returnEntries` set to true
|
|
447
|
+
|
|
448
|
+
if (finalQueryLevels.length > 1 || finalQueryLevels.length === 1 && finalQueryLevels[0].level !== 0) {
|
|
449
|
+
var _params$orderBy;
|
|
450
|
+
|
|
451
|
+
// Build final query
|
|
452
|
+
const {
|
|
453
|
+
contentTypeIds,
|
|
454
|
+
filters,
|
|
455
|
+
sharedFilters,
|
|
456
|
+
params
|
|
457
|
+
} = this;
|
|
458
|
+
const derivedIds = finalQueryLevels[0].children.filter(ql => !ql.returnEntries).map(ql => ql.validatedLinks).flat() || [];
|
|
459
|
+
const derivedIdFilters = derivedIds.map(vl => makeFilterExpressions({
|
|
460
|
+
[vl.linkFieldId]: {
|
|
461
|
+
fieldId: `${vl.linkFieldId}.sys.id`
|
|
462
|
+
}
|
|
463
|
+
}, {
|
|
464
|
+
[vl.linkFieldId]: vl.entryIds.join(',') || 'no results for filter'
|
|
465
|
+
})).flat() || []; // This is the final query to be run and response returned to the caller
|
|
466
|
+
// Only this bit cares about linkDepth, fields and pagination parameters
|
|
467
|
+
|
|
468
|
+
const query = finalQuery({
|
|
469
|
+
contentTypeIds,
|
|
470
|
+
filters: makeFilterExpressions(filters, params),
|
|
471
|
+
sharedFilters: makeFilterExpressions(sharedFilters, params),
|
|
472
|
+
idFilters: derivedIdFilters,
|
|
473
|
+
fields: params.fields ? [...JSON.parse(params.fields), ...finalQueryLevels.map(l => {
|
|
474
|
+
var _l$parent;
|
|
475
|
+
|
|
476
|
+
return ((_l$parent = l.parent) === null || _l$parent === void 0 ? void 0 : _l$parent.linkFieldIds) || [];
|
|
477
|
+
}).flat()] : [],
|
|
478
|
+
orderBy: (_params$orderBy = params.orderBy) === null || _params$orderBy === void 0 ? void 0 : _params$orderBy.split(','),
|
|
479
|
+
pageIndex: Number(params.pageIndex) || 0,
|
|
480
|
+
pageSize: typeof Number(params.pageSize) === 'number' ? Number(params.pageSize) : 25,
|
|
481
|
+
searchTerm: params.term,
|
|
482
|
+
versionStatus: params.versionStatus
|
|
483
|
+
}, (finalQueryLevels === null || finalQueryLevels === void 0 ? void 0 : finalQueryLevels[0].children.filter(ql => ql.returnEntries).map(ql => {
|
|
484
|
+
var _ql$parent, _ql$parent2;
|
|
485
|
+
|
|
486
|
+
const entriesAtLevel = ql.GetResultsEntries() || ((_ql$parent = ql.parent) === null || _ql$parent === void 0 ? void 0 : _ql$parent.GetResultsEntries());
|
|
487
|
+
const previousIdsFilter = ql.returnEntries || !!ql.children.some(qc => qc.returnEntries) ? (_ql$parent2 = ql.parent) === null || _ql$parent2 === void 0 ? void 0 : _ql$parent2.linkFieldIds.map(fieldId => makeDerivedIdsFilterExpression(fieldId, entriesAtLevel, true, ql.runFinalQuery)).flat() : [];
|
|
488
|
+
return {
|
|
489
|
+
contentTypeIds: ql.contentTypeIds,
|
|
490
|
+
filters: makeFilterExpressions(ql.filters, params),
|
|
491
|
+
sharedFilters: makeFilterExpressions(ql.sharedFilters, params),
|
|
492
|
+
idFilters: previousIdsFilter
|
|
493
|
+
};
|
|
494
|
+
})) || []);
|
|
495
|
+
if (this.debug) console.log(`\nFinal query: ${derivedIds.reduce((accumulator, object) => accumulator + object.entryIds.length, 0)} derived ids \n${JSON.stringify(query.toJSON()).substring(0, 1000)}`);
|
|
496
|
+
const finalQueryResult = await cachedSearch.searchUsingPost(query, Number(params.linkDepth) || 0, params.projectId); // Resolve any parent entries
|
|
497
|
+
|
|
498
|
+
const resolveParentLevels = finalQueryLevels.filter(ql => ql.resolveFirstParent);
|
|
499
|
+
let entries = finalQueryResult.items;
|
|
500
|
+
|
|
501
|
+
for (const resolveParents of resolveParentLevels) {
|
|
502
|
+
var _resolveParents$paren, _resolveParents$paren2;
|
|
503
|
+
|
|
504
|
+
entries = await resolveParentEntries(((_resolveParents$paren = resolveParents.parent) === null || _resolveParents$paren === void 0 ? void 0 : _resolveParents$paren.contentTypeIds) || [], resolveParents.contentTypeIds, ((_resolveParents$paren2 = resolveParents.parent) === null || _resolveParents$paren2 === void 0 ? void 0 : _resolveParents$paren2.linkFieldIds[0]) || 'unknown', finalQueryResult.items, // or entries?
|
|
505
|
+
this.params, this.debug);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
return { ...finalQueryResult,
|
|
509
|
+
items: entries
|
|
510
|
+
};
|
|
511
|
+
} else {
|
|
512
|
+
var _this$queryLevels$fin;
|
|
513
|
+
|
|
514
|
+
if (this.debug) console.log(`\nNo further queries required\n`);
|
|
515
|
+
return (_this$queryLevels$fin = this.queryLevels.find(ql => ql.level === 0)) === null || _this$queryLevels$fin === void 0 ? void 0 : _this$queryLevels$fin.GetResults();
|
|
516
|
+
}
|
|
517
|
+
};
|
|
518
|
+
|
|
519
|
+
this.InitQueryLevels = () => {
|
|
520
|
+
const createChildQueryLevels = (linkFields, parentQueryLevel, level = 1) => {
|
|
521
|
+
return Object.entries(linkFields).map(([, {
|
|
522
|
+
contentTypeId = '',
|
|
523
|
+
filters = {},
|
|
524
|
+
linkFields = {},
|
|
525
|
+
resolveFirstParent,
|
|
526
|
+
returnEntries,
|
|
527
|
+
sharedFilters = {}
|
|
528
|
+
}]) => {
|
|
529
|
+
const thisLevel = new QueryLevelResults({
|
|
530
|
+
level,
|
|
531
|
+
contentTypeIds: Array.isArray(contentTypeId) ? contentTypeId : [contentTypeId],
|
|
532
|
+
filters: Object.fromEntries(Object.entries(filters).map(([fKey, fVal]) => [fKey, typeof fVal === 'string' ? {
|
|
533
|
+
fieldId: fVal
|
|
534
|
+
} : fVal])),
|
|
535
|
+
sharedFilters: Object.fromEntries(Object.entries(sharedFilters).map(([fKey, fVal]) => [fKey, typeof fVal === 'string' ? {
|
|
536
|
+
fieldId: fVal
|
|
537
|
+
} : fVal])),
|
|
538
|
+
linkFields,
|
|
539
|
+
parent: parentQueryLevel,
|
|
540
|
+
params,
|
|
541
|
+
resolveFirstParent,
|
|
542
|
+
returnEntries,
|
|
543
|
+
debug: this.debug
|
|
544
|
+
});
|
|
545
|
+
parentQueryLevel.AddChild({
|
|
546
|
+
child: thisLevel
|
|
547
|
+
});
|
|
548
|
+
return [thisLevel, ...createChildQueryLevels(linkFields, thisLevel, level + 1)];
|
|
549
|
+
}).flat();
|
|
550
|
+
};
|
|
551
|
+
|
|
552
|
+
const {
|
|
553
|
+
contentTypeIds,
|
|
554
|
+
filters,
|
|
555
|
+
sharedFilters,
|
|
556
|
+
linkFields,
|
|
557
|
+
params
|
|
558
|
+
} = this;
|
|
559
|
+
const firstLevel = new QueryLevelResults({
|
|
560
|
+
level: 0,
|
|
561
|
+
contentTypeIds,
|
|
562
|
+
filters: Object.fromEntries(Object.entries(filters).map(([fKey, fVal]) => [fKey, typeof fVal === 'string' ? {
|
|
563
|
+
fieldId: fVal
|
|
564
|
+
} : fVal])),
|
|
565
|
+
sharedFilters: Object.fromEntries(Object.entries(sharedFilters).map(([fKey, fVal]) => [fKey, typeof fVal === 'string' ? {
|
|
566
|
+
fieldId: fVal
|
|
567
|
+
} : fVal])),
|
|
568
|
+
linkFields,
|
|
569
|
+
params,
|
|
570
|
+
debug: this.debug
|
|
571
|
+
});
|
|
572
|
+
const queryLevels = [firstLevel, ...createChildQueryLevels(linkFields, firstLevel)]; // return queryLevels;
|
|
573
|
+
// If we are only returning entries from level 0
|
|
574
|
+
// we can skip running the first query and finalQuery will suffice
|
|
575
|
+
|
|
576
|
+
if (queryLevels.find(ql => ql.returnEntries && ql.level !== 0)) return queryLevels;else return queryLevels.map(ql => {
|
|
577
|
+
ql.runFirstQuery = false; // ql.runFinalQuery = false;
|
|
578
|
+
|
|
579
|
+
return ql;
|
|
580
|
+
});
|
|
581
|
+
};
|
|
582
|
+
|
|
583
|
+
this.contentTypeIds = Array.isArray(_contentTypeId) ? _contentTypeId : [_contentTypeId];
|
|
584
|
+
this.filters = _filters;
|
|
585
|
+
this.sharedFilters = _sharedFilters;
|
|
586
|
+
this.linkFields = _linkFields;
|
|
587
|
+
this.params = _params;
|
|
588
|
+
this.debug = debug;
|
|
589
|
+
this.queryLevels = this.InitQueryLevels();
|
|
451
590
|
}
|
|
452
591
|
|
|
453
592
|
}
|
|
454
593
|
|
|
594
|
+
/**
|
|
595
|
+
* Make a LinkDepth api at the uri specified in middlewareConfig.
|
|
596
|
+
* The api supports a GET request and specified filters are supplied as query-string parameters.
|
|
597
|
+
* The response should be a normal Delivery API response.
|
|
598
|
+
* @param app Express app instance
|
|
599
|
+
* @param middlewareConfig Middleware configuration that represents the content types we want to search within, any filters that are required and any linkFields we wish to search within to derive a set of search results from the entries that contain the linkFields. Each key inside of linkFields represents another "linkDepth" of entries and we can specify all the same contentTypeId, filters, and linkFields of their own. There is no currently no limit on how deep these linkFields can go
|
|
600
|
+
* @returns Returns nothing if uri, contentTypeId or linkFields is not set in middlewareConfig
|
|
601
|
+
*/
|
|
602
|
+
const makeLinkDepthApi = (app, middlewareConfig) => {
|
|
603
|
+
const {
|
|
604
|
+
uri,
|
|
605
|
+
contentTypeId,
|
|
606
|
+
linkFields
|
|
607
|
+
} = middlewareConfig;
|
|
608
|
+
if (!contentTypeId || !linkFields || !uri) return;
|
|
609
|
+
app.get(uri, makeLinkDepthMiddleware(middlewareConfig));
|
|
610
|
+
};
|
|
611
|
+
/** Create a content type hierarchy from supplied config and produces
|
|
612
|
+
* a RequestHandler function to serve our Express middleware */
|
|
613
|
+
|
|
614
|
+
|
|
615
|
+
const makeLinkDepthMiddleware = ({
|
|
616
|
+
contentTypeId,
|
|
617
|
+
filters = {},
|
|
618
|
+
sharedFilters = {},
|
|
619
|
+
linkFields,
|
|
620
|
+
debug
|
|
621
|
+
}) => {
|
|
622
|
+
try {
|
|
623
|
+
// The runtime express request handler
|
|
624
|
+
const linkDepthMiddleware = async (req, res) => {
|
|
625
|
+
try {
|
|
626
|
+
// Short cache duration copied from canterbury project
|
|
627
|
+
setCachingHeaders(res, {
|
|
628
|
+
cacheControl: 'private',
|
|
629
|
+
surrogateControl: '10'
|
|
630
|
+
}); // Gather all params from the request, we will use them at the right query levels later
|
|
631
|
+
|
|
632
|
+
const params = Object.fromEntries([...Object.entries(req.params), ...Object.entries(req.query)].map(([k, v]) => [k, v === null || v === void 0 ? void 0 : v.toString()]));
|
|
633
|
+
const result = await new LinkDepthSearchService({
|
|
634
|
+
contentTypeId,
|
|
635
|
+
linkFields,
|
|
636
|
+
filters,
|
|
637
|
+
sharedFilters,
|
|
638
|
+
params,
|
|
639
|
+
debug
|
|
640
|
+
}).DoSearch();
|
|
641
|
+
res.json(result);
|
|
642
|
+
} catch (error) {
|
|
643
|
+
// This is a runtime error encountered when processing a given request
|
|
644
|
+
console.error(error);
|
|
645
|
+
res.statusCode = 500;
|
|
646
|
+
res.json(error);
|
|
647
|
+
}
|
|
648
|
+
};
|
|
649
|
+
|
|
650
|
+
return linkDepthMiddleware;
|
|
651
|
+
} catch (error) {
|
|
652
|
+
// This will be an error building the middleware
|
|
653
|
+
// we can only serve what the error was as the request handler instead
|
|
654
|
+
console.error(error);
|
|
655
|
+
|
|
656
|
+
const errorMiddleware = async (req, res) => {
|
|
657
|
+
res.statusCode = 500;
|
|
658
|
+
res.json(JSON.stringify(error));
|
|
659
|
+
};
|
|
660
|
+
|
|
661
|
+
return errorMiddleware;
|
|
662
|
+
}
|
|
663
|
+
};
|
|
664
|
+
|
|
455
665
|
const servers$1 = SERVERS;
|
|
456
666
|
/* global SERVERS */
|
|
457
667
|
|
|
@@ -624,6 +834,8 @@ const staticAssets = (app, {
|
|
|
624
834
|
}));
|
|
625
835
|
};
|
|
626
836
|
|
|
837
|
+
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
838
|
+
|
|
627
839
|
/**
|
|
628
840
|
* Removes all key-value entries from the list cache.
|
|
629
841
|
*
|
|
@@ -2792,9 +3004,9 @@ var getNative$1 = _getNative,
|
|
|
2792
3004
|
root$2 = _root;
|
|
2793
3005
|
|
|
2794
3006
|
/* Built-in method references that are verified to be native. */
|
|
2795
|
-
var Set$
|
|
3007
|
+
var Set$1 = getNative$1(root$2, 'Set');
|
|
2796
3008
|
|
|
2797
|
-
var _Set = Set$
|
|
3009
|
+
var _Set = Set$1;
|
|
2798
3010
|
|
|
2799
3011
|
var getNative = _getNative,
|
|
2800
3012
|
root$1 = _root;
|
|
@@ -2807,7 +3019,7 @@ var _WeakMap = WeakMap$1;
|
|
|
2807
3019
|
var DataView = _DataView,
|
|
2808
3020
|
Map = _Map,
|
|
2809
3021
|
Promise$1 = _Promise,
|
|
2810
|
-
Set
|
|
3022
|
+
Set = _Set,
|
|
2811
3023
|
WeakMap = _WeakMap,
|
|
2812
3024
|
baseGetTag = _baseGetTag,
|
|
2813
3025
|
toSource = _toSource;
|
|
@@ -2825,7 +3037,7 @@ var dataViewTag$2 = '[object DataView]';
|
|
|
2825
3037
|
var dataViewCtorString = toSource(DataView),
|
|
2826
3038
|
mapCtorString = toSource(Map),
|
|
2827
3039
|
promiseCtorString = toSource(Promise$1),
|
|
2828
|
-
setCtorString = toSource(Set
|
|
3040
|
+
setCtorString = toSource(Set),
|
|
2829
3041
|
weakMapCtorString = toSource(WeakMap);
|
|
2830
3042
|
|
|
2831
3043
|
/**
|
|
@@ -2841,7 +3053,7 @@ var getTag$3 = baseGetTag;
|
|
|
2841
3053
|
if ((DataView && getTag$3(new DataView(new ArrayBuffer(1))) != dataViewTag$2) ||
|
|
2842
3054
|
(Map && getTag$3(new Map) != mapTag$3) ||
|
|
2843
3055
|
(Promise$1 && getTag$3(Promise$1.resolve()) != promiseTag) ||
|
|
2844
|
-
(Set
|
|
3056
|
+
(Set && getTag$3(new Set) != setTag$3) ||
|
|
2845
3057
|
(WeakMap && getTag$3(new WeakMap) != weakMapTag$1)) {
|
|
2846
3058
|
getTag$3 = function(value) {
|
|
2847
3059
|
var result = baseGetTag(value),
|