@sanity/desk-tool
Version:
Tool for managing all sorts of content in a structured manner
151 lines (147 loc) • 8.86 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useReferringDocuments = useReferringDocuments;
var _react = require("react");
var _document = _interopRequireDefault(require("part:@sanity/base/datastore/document"));
var _client = _interopRequireDefault(require("part:@sanity/base/client"));
var _internal = require("@sanity/base/_internal");
var _rxjs = require("rxjs");
var _operators = require("rxjs/operators");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
// this is used in place of `instanceof` so the matching can be more robust and
// won't have any issues with dual packages etc
// https://nodejs.org/api/packages.html#dual-package-hazard
function isClientError(e) {
if (typeof e !== 'object') return false;
if (!e) return false;
return 'statusCode' in e && 'response' in e;
}
var versionedClient = _client.default.withConfig({
apiVersion: '2022-03-07'
});
var DEFAULT_POLL_INTERVAL = 5000;
// only fetches when the document is visible
var createVisiblePoll = interval => (0, _rxjs.fromEvent)(document, 'visibilitychange').pipe(
// add empty emission to have this fire on creation
(0, _operators.startWith)(null), (0, _operators.map)(() => document.visibilityState === 'visible'), (0, _operators.distinctUntilChanged)(), (0, _operators.switchMap)(visible => visible ?
// using timer instead of interval since timer will emit on creation
(0, _rxjs.timer)(0, interval || DEFAULT_POLL_INTERVAL) : _rxjs.EMPTY), (0, _operators.shareReplay)({
refCount: true,
bufferSize: 1
}));
function getDocumentExistence(documentId) {
var draftId = (0, _internal.getDraftId)(documentId);
var publishedId = (0, _internal.getPublishedId)(documentId);
var requestOptions = {
uri: versionedClient.getDataUrl('doc', "".concat(draftId, ",").concat(publishedId)),
json: true,
query: {
excludeContent: 'true'
},
tag: 'use-referring-documents.document-existence'
};
return versionedClient.observable.request(requestOptions).pipe((0, _operators.map)(_ref => {
var omitted = _ref.omitted;
var nonExistant = omitted.filter(doc => doc.reason === 'existence');
if (nonExistant.length === 2) {
// None of the documents exist
return undefined;
}
if (nonExistant.length === 0) {
// Both exist, so use the published one
return publishedId;
}
// If the draft does not exist, use the published ID, and vice versa
return nonExistant.some(doc => doc.id === draftId) ? publishedId : draftId;
}));
}
/**
* fetches the cross-dataset references using the client observable.request
* method (for that requests can be automatically cancelled)
*/
function fetchCrossDatasetReferences(documentId, visiblePoll$) {
return visiblePoll$.pipe((0, _operators.switchMap)(() => getDocumentExistence(documentId)), (0, _operators.switchMap)(checkDocumentId => {
if (!checkDocumentId) {
return (0, _rxjs.of)({
totalCount: 0,
references: []
});
}
var currentDataset = _client.default.config().dataset;
return versionedClient.observable.request({
url: "/data/references/".concat(currentDataset, "/documents/").concat(checkDocumentId, "/to?excludeInternalReferences=true&excludePaths=true"),
tag: 'use-referring-documents.external'
}).pipe((0, _operators.catchError)(e => {
// it's possible that referencing document doesn't exist yet so the
// API will return a 404. In those cases, we want to catch and return
// a response with no references
if (isClientError(e) && e.statusCode === 404) {
return (0, _rxjs.of)({
totalCount: 0,
references: []
});
}
throw e;
}));
}));
}
var useInternalReferences = (0, _internal.createHookFromObservableFactory)(documentId => {
var referencesClause = '*[references($documentId)][0...100]{_id,_type}';
var totalClause = 'count(*[references($documentId)])';
var fetchQuery = "{\"references\":".concat(referencesClause, ",\"totalCount\":").concat(totalClause, "}");
var listenQuery = '*[references($documentId)]';
return _document.default.listenQuery({
fetch: fetchQuery,
listen: listenQuery
}, {
documentId
}, {
tag: 'use-referring-documents',
transitions: ['appear', 'disappear'],
throttleTime: 5000
});
});
var useCrossDatasetReferences = (0, _internal.createHookFromObservableFactory)((documentId, interval) => {
var visiblePoll$ = createVisiblePoll(interval);
return visiblePoll$.pipe((0, _operators.switchMap)(() => fetchCrossDatasetReferences(documentId, visiblePoll$)));
});
function useReferringDocuments(documentId) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var publishedId = (0, _internal.getPublishedId)(documentId);
var _useInternalReference = useInternalReferences(publishedId),
_useInternalReference2 = _slicedToArray(_useInternalReference, 2),
internalReferences = _useInternalReference2[0],
isInternalReferencesLoading = _useInternalReference2[1];
var _useCrossDatasetRefer = useCrossDatasetReferences(publishedId, options.externalPollInterval),
_useCrossDatasetRefer2 = _slicedToArray(_useCrossDatasetRefer, 2),
crossDatasetReferences = _useCrossDatasetRefer2[0],
isCrossDatasetReferencesLoading = _useCrossDatasetRefer2[1];
var projectIds = (0, _react.useMemo)(() => {
return Array.from(new Set(crossDatasetReferences === null || crossDatasetReferences === void 0 ? void 0 : crossDatasetReferences.references.map(crossDatasetReference => crossDatasetReference.projectId).filter(Boolean))).sort();
}, [crossDatasetReferences === null || crossDatasetReferences === void 0 ? void 0 : crossDatasetReferences.references]);
var datasetNames = (0, _react.useMemo)(() => {
return Array.from(new Set(crossDatasetReferences === null || crossDatasetReferences === void 0 ? void 0 : crossDatasetReferences.references
// .filter((name) => typeof name === 'string')
.map(crossDatasetReference => (crossDatasetReference === null || crossDatasetReference === void 0 ? void 0 : crossDatasetReference.datasetName) || '').filter(datasetName => Boolean(datasetName) && datasetName !== ''))).sort();
}, [crossDatasetReferences === null || crossDatasetReferences === void 0 ? void 0 : crossDatasetReferences.references]);
var hasUnknownDatasetNames = (0, _react.useMemo)(() => {
return Boolean(crossDatasetReferences === null || crossDatasetReferences === void 0 ? void 0 : crossDatasetReferences.references.some(crossDatasetReference => typeof crossDatasetReference.datasetName !== 'string'));
}, [crossDatasetReferences === null || crossDatasetReferences === void 0 ? void 0 : crossDatasetReferences.references]);
return {
totalCount: ((internalReferences === null || internalReferences === void 0 ? void 0 : internalReferences.totalCount) || 0) + ((crossDatasetReferences === null || crossDatasetReferences === void 0 ? void 0 : crossDatasetReferences.totalCount) || 0),
projectIds,
datasetNames,
hasUnknownDatasetNames,
internalReferences,
crossDatasetReferences,
isLoading: isInternalReferencesLoading || isCrossDatasetReferencesLoading
};
}