UNPKG

semantic-network

Version:

A utility library for manipulating a list of links that form a semantic interface to a network of resources.

256 lines 10.7 kB
import { __awaiter } from "tslib"; import { LinkUtil } from 'semantic-link'; import { NamedRepresentationFactory } from '../representation/namedRepresentationFactory'; import { instanceOfSingleton } from '../utils/instanceOf/instanceOfSingleton'; import { ApiUtil } from '../apiUtil'; import { LinkRelation } from '../linkRelation'; import { SyncUtil } from './syncUtil'; import { instanceOfCollection } from '../utils/instanceOf/instanceOfCollection'; import { instanceOfDocumentCollection } from '../utils/instanceOf/instanceOfDocumentCollection'; import { instanceOfDocumentSingleton } from '../utils/instanceOf/instanceOfDocumentSingleton'; import { RepresentationUtil } from '../utils/representationUtil'; import anylogger from 'anylogger'; const log = anylogger('syncResource'); /** * Sync resources between two networks of data * * There six scenarios: * * key: x - undefined * + - specified * [empty] - not required * * options resource document * rel relOnDocument singleton collection singleton collection * 1. x x + + * 2. + + * 3. x x + + * 4. + x + * 5. x x + + * 6. + x + * * * Strategy One * ============ * * Retrieves a resource and synchronises (its attributes) from the document * * Note: this is used for syncing two documents through their parents * * * @example * * Resource Document * * sync * +-----+ +-----+ * | | <-----------+ | | * | | | | * +-----+ +-----+ * * * Strategy Two * ============ * * Retrieves a singleton resource on a parent resource and updates (its * attributes) based on a singleton of the same name in the given parent document. * * The parent maybe either a collection resource or a singleton resource * * Note: this is used for syncing two documents through their parents * * @example * * * parent singleton singleton parent * Resource Resource Document Document * * +----------+ +---------+ * | | sync | | * | +-----+ +-----+ | * | Named| | <-----------+ | |Named | * | | | | | | * | +-----+ +-----+ | * | | | | * | | ^ | | * +----------+ | +---------+ * | * + * looks for * * Strategy Three * ============== * * * Retrieves a resource item from a resource collection and synchronises (its attributes) from the document. * * @example * * resource * Collection Document * * +-----+ * | | * | | * +-----+ sync * X +---+ * X <-----------+ | x | * X +---+ * items * * Strategy Four * ============= * * * Retrieves a parent resource and its named collection with items (sparsely populated), finds the item in that * collection and then synchronises (its attributes) with the document. * * @example * * parent resource * Resource Collection Document * * +----------+ * | | * | +-----+ * | Named| | * | | | * | +-----+ sync * | | X +---+ * | | X <-----------+ | x | * +----------+ X +---+ * items * * Strategy Five * ============= * * * Retrieves a collection resource with items (sparsely populated), then synchronises the * collection items where each item may be updated (its attributes), a new item created or an item removed. * * @example * * resource document * Collection Collection * * * sync * +-----+ +-----+ * | | <-----------+ | | * | | | | * +-----+ +-----+ * X X * X items X items * X X * * * Strategy Six * ============ * * Retrieves a parent resource and its named collection with items (sparsely populated), then synchronises the * collection items where each item may be updated (its attributes), a new item created or an item removed. * * This method is used when you have context of one parent and the document collection * * @example * * parent resource document * Resource Collection Collection * * +----------+ * | | sync * | +-----+ +-----+ * | Named| | <-----------+ | | * | | | | | * | +-----+ +-----+ * | | X X * | | X items X items * +----------+ X X * * * * @param resource * @param document * @param strategies * @param options */ export function syncResource(resource, document, strategies = [], options) { return __awaiter(this, void 0, void 0, function* () { const { rel = undefined, relOnDocument = undefined, name = NamedRepresentationFactory.defaultNameStrategy(rel, resource), nameOnDocument = NamedRepresentationFactory.defaultNameStrategy(relOnDocument, document), } = Object.assign({}, options); // do not pass down options = Object.assign(Object.assign({}, options), { rel: undefined, name: undefined, relOnDocument: undefined, nameOnDocument: undefined }); if (!rel && !relOnDocument && instanceOfSingleton(resource) && instanceOfSingleton(document)) { const result = yield ApiUtil.get(resource, options); if (result) { log.debug('sync singleton on rel \'%s\' %s', rel, LinkUtil.getUri(resource, LinkRelation.Self)); const update = yield ApiUtil.update(resource, document, options); if (update) { yield (yield SyncUtil.syncResources(resource, document, strategies, options))(); } } } else if (!rel && !relOnDocument && instanceOfCollection(resource) && instanceOfDocumentCollection(document)) { log.debug('sync collection items %s', LinkUtil.getUri(resource, LinkRelation.Self)); const { info } = yield SyncUtil.synchroniseCollection(resource, document, options); if (info) { // populate the potentially sparse collection - we need to ensure that // any existing ones (old) are not stale and that any just created (sparse) // are hydrated yield ApiUtil.get(resource, Object.assign(Object.assign({}, options), { includeItems: true })); yield SyncUtil.tailRecursionThroughStrategies(strategies, info, options); } } else if (!rel && !relOnDocument && instanceOfCollection(resource) && instanceOfDocumentSingleton(document)) { log.debug('sync collection %s', LinkUtil.getUri(resource, LinkRelation.Self)); const result = yield ApiUtil.get(resource, options); if (instanceOfCollection(result)) { const syncInfo = yield SyncUtil.syncResourceInCollection(result, document, options); if (syncInfo) { return yield SyncUtil.syncInfos(strategies, options)(syncInfo); } } else { log.error('result is not a collection'); } return result; } else if (rel && !relOnDocument && instanceOfDocumentCollection(document)) { log.debug('collection (in named collection) \'%s\' on %s', name, LinkUtil.getUri(resource, LinkRelation.Self)); const result = yield ApiUtil.get(resource, Object.assign(Object.assign({}, options), { rel })); if (instanceOfCollection(result)) { // in the context of the collection, synchronise the collection part of the document yield syncResource(result, document, strategies, options); } else { log.info('No \'%s\' on resource %s', name, LinkUtil.getUri(resource, LinkRelation.Self)); } } else if (rel && !relOnDocument && instanceOfDocumentSingleton(document)) { log.debug('sync resource (named collection) \'%s\' on %s', name, LinkUtil.getUri(resource, LinkRelation.Self)); const namedResource = yield ApiUtil.get(resource, Object.assign(Object.assign({}, options), { rel })); if (instanceOfCollection(namedResource)) { const syncInfo = yield SyncUtil.syncResourceInCollection(namedResource, document, options); if (syncInfo) { return yield SyncUtil.syncInfos(strategies, options)(syncInfo); } } return namedResource; } else if (rel && relOnDocument) { const namedResource = yield ApiUtil.get(resource, Object.assign(Object.assign({}, options), { rel })); if (namedResource) { log.debug('sync resource (named singleton) \'%s\' on %s', name, LinkUtil.getUri(resource, LinkRelation.Self)); const namedDocument = RepresentationUtil.getProperty(document, nameOnDocument); const updated = yield ApiUtil.update(namedResource, namedDocument, options); if (updated) { yield (yield SyncUtil.syncResources(updated, namedDocument, strategies, options))(); } } else { log.debug('no update: singleton \'%s\' not found on %s', name, LinkUtil.getUri(resource, LinkRelation.Self)); } } return resource; }); } //# sourceMappingURL=syncResource.js.map