semantic-network
Version:
A utility library for manipulating a list of links that form a semantic interface to a network of resources.
116 lines • 5.92 kB
JavaScript
import { __awaiter, __rest } from "tslib";
import { LinkUtil } from 'semantic-link';
import { instanceOfTrackedRepresentation } from '../utils/instanceOf/instanceOfTrackedRepresentation';
import { instanceOfCollection } from '../utils/instanceOf/instanceOfCollection';
import { pooledCollectionMakeStrategy, SparseRepresentationFactory, } from '../representation/sparseRepresentationFactory';
import { SingletonMerger } from '../representation/singletonMerger';
import anylogger from 'anylogger';
import { create } from '../representation/create';
import { CollectionMerger } from '../representation/collectionMerger';
import { LinkRelation } from '../linkRelation';
import { ResourceUtil } from '../utils/resourceUtil';
import { get } from '../representation/get';
import { EqualityUtil } from '../utils/equalityUtil';
const log = anylogger('SearchUtil');
export class SearchUtil {
/**
* Create or get a tracked resource that is a collection to store search collections. It
* is likely (but not required) that the resource is backed by a 'real' resource.
*
* This can be used to store search results in an ad-hoc manner where the search
* result doesn't have to have a name. The 'self' link of the search result can be used
* to identify what the search was (and should be unique).
*/
static makePooledCollection(context, options) {
if (instanceOfTrackedRepresentation(context)) {
const { rel = undefined } = Object.assign({}, options);
if (rel) {
const uri = LinkUtil.getUri(context, rel);
if (uri) {
const poolName = ResourceUtil.makeName(options);
const pool = context[poolName];
if (pool) {
if (instanceOfTrackedRepresentation(pool)) {
if (instanceOfCollection(pool)) {
return pool;
}
else {
throw new Error(`Pool '${poolName}' is not a collection`);
}
}
else {
throw new Error(`Attribute '${poolName}' is not a tracked resource`);
}
}
else {
const newSearches = SparseRepresentationFactory.make(Object.assign(Object.assign({}, options), { sparseType: 'collection', uri: uri }));
SingletonMerger.add(context, poolName, newSearches, options);
return newSearches;
}
}
else {
throw new Error(`Link relation '${rel}' not found`);
}
}
else {
throw new Error(`The pool collection requires a link relation`);
}
}
throw new Error(`Failed to create pool collection`);
}
/**
*
* Return a search result collection that is a tracked resource collection on the context collection.
*
* Each time this is called the new search result is merged into the search result collection that can
* be bound to the view.
*
* With each call, the pooled search collection will use existing items or fetch new ones to minimise the
* across the wire calls.
*
* The default implementation will create a '.pooled-search' sub-collection that can be view in devtool
*
* @param context resource that has the search collection as a link relation
* @param document the search fields that will be used for the search (and is merged into the create/search form)
* @param options
*/
static search(context, document, options) {
return __awaiter(this, void 0, void 0, function* () {
const _a = Object.assign({}, options), { searchRel = LinkRelation.Search, searchName = undefined, searchPooledPrefix = '.pooled-' } = _a, opts = __rest(_a, ["searchRel", "searchName", "searchPooledPrefix"]);
const pooledResource = SearchUtil.makePooledCollection(context, Object.assign(Object.assign({}, options), { rel: searchRel, name: searchName || `${searchPooledPrefix}${searchRel}` }));
const searchResource = yield get(context, Object.assign(Object.assign({}, opts), { rel: searchRel }));
const results = yield create(document, Object.assign(Object.assign({}, opts), { createContext: searchResource, makeSparseStrategy: (options) => pooledCollectionMakeStrategy(pooledResource, options) }));
if (results) {
// search collections don't want to merge the result links into the original search links
CollectionMerger.merge(searchResource, results, Object.assign({ mergeLinks: false }, opts));
}
else {
log.debug('no search results available');
}
return searchResource;
});
}
/**
* In-place add to a (search) collection a new item. This is used where the current list is being added to independently
* of a newly added collection without returning the entire search collection
*
* @default equalityMatch {@link CanonicalOrSelf}
*/
static update(collection, item, equalityMatch) {
if (instanceOfCollection(collection) && item) {
const index = collection.items.findIndex(r => EqualityUtil.matches(item, r, equalityMatch));
if (index >= 0) {
// if found, replace
collection.items.splice(index, 1, item);
}
else {
// else add to head
collection.items.splice(0, 0, item);
}
}
else {
log.debug('No collection found to update');
}
}
}
//# sourceMappingURL=searchUtil.js.map