@stackbit/cms-contentful
Version:
Stackbit Contentful CMS Interface
388 lines • 15.8 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createPlainApiClient = createPlainApiClient;
exports.fetchEntryById = fetchEntryById;
exports.fetchAssetById = fetchAssetById;
exports.createEntry = createEntry;
exports.updateEntry = updateEntry;
exports.publishEntry = publishEntry;
exports.unpublishEntry = unpublishEntry;
exports.archiveEntry = archiveEntry;
exports.unarchiveEntry = unarchiveEntry;
exports.deleteEntry = deleteEntry;
exports.createAsset = createAsset;
exports.updateAsset = updateAsset;
exports.createAssetFromFile = createAssetFromFile;
exports.processAssetForAllLocales = processAssetForAllLocales;
exports.publishAsset = publishAsset;
exports.createValidateBulkAction = createValidateBulkAction;
exports.createPublishBulkAction = createPublishBulkAction;
exports.createUnpublishBulkAction = createUnpublishBulkAction;
exports.createWebhook = createWebhook;
exports.getBulkAction = getBulkAction;
exports.fetchEntriesByIds = fetchEntriesByIds;
exports.fetchAssetsByIds = fetchAssetsByIds;
exports.fetchAllEntries = fetchAllEntries;
exports.fetchEntriesUpdatedAfter = fetchEntriesUpdatedAfter;
exports.fetchAllAssets = fetchAllAssets;
exports.fetchAssetsUpdatedAfter = fetchAssetsUpdatedAfter;
exports.fetchAllLocales = fetchAllLocales;
exports.fetchAllUsers = fetchAllUsers;
exports.fetchAllContentTypes = fetchAllContentTypes;
exports.hasContentTypesUpdatedAfter = hasContentTypesUpdatedAfter;
exports.fetchContentTypesUpdatedAfter = fetchContentTypesUpdatedAfter;
exports.fetchAllEditorInterfaces = fetchAllEditorInterfaces;
exports.fetchAllAppInstallations = fetchAllAppInstallations;
exports.fetchAllWebhooks = fetchAllWebhooks;
exports.fetchAllReleases = fetchAllReleases;
exports.fetchAllSchedules = fetchAllSchedules;
exports.fetchScheduleById = fetchScheduleById;
exports.fetchEntityVersions = fetchEntityVersions;
exports.fetchEntityVersion = fetchEntityVersion;
exports.createScheduledAction = createScheduledAction;
exports.updateScheduledAction = updateScheduledAction;
exports.cancelScheduledAction = cancelScheduledAction;
exports.getScheduledAction = getScheduledAction;
exports.fetchAllItems = fetchAllItems;
exports.fetchAllItemsCursor = fetchAllItemsCursor;
const lodash_1 = __importDefault(require("lodash"));
const contentful_management_1 = require("contentful-management");
const contentful_scheduled_actions_converter_1 = require("./contentful-scheduled-actions-converter");
function createPlainApiClient({ accessToken, spaceId, environment, managementHost, uploadHost }) {
return (0, contentful_management_1.createClient)({
accessToken: accessToken,
...(managementHost ? { host: managementHost } : null),
...(uploadHost ? { hostUpload: uploadHost } : null)
}, {
type: 'plain',
defaults: {
spaceId: spaceId,
environmentId: environment
}
});
}
async function fetchEntryById(client, entryId) {
return client.entry.get({ entryId });
}
async function fetchAssetById(client, assetId) {
return client.asset.get({ assetId });
}
async function createEntry(client, contentTypeId, data) {
return client.entry.create({ contentTypeId }, data);
}
async function updateEntry(client, entryId, entry) {
return client.entry.update({ entryId }, entry);
}
async function publishEntry(client, entry) {
return client.entry.publish({ entryId: entry.sys.id }, entry);
}
async function unpublishEntry(client, entryId) {
return client.entry.unpublish({ entryId });
}
async function archiveEntry(client, entryId) {
return client.entry.archive({ entryId });
}
async function unarchiveEntry(client, entryId) {
return client.entry.unarchive({ entryId });
}
async function deleteEntry(client, entryId) {
return client.entry.delete({ entryId });
}
async function createAsset(client, data) {
return client.asset.create({}, data);
}
async function updateAsset(client, assetId, asset) {
return client.asset.update({ assetId }, asset);
}
async function createAssetFromFile(client, data) {
return client.asset.createFromFiles({}, data);
}
async function processAssetForAllLocales(client, data) {
return client.asset.processForAllLocales({}, data);
}
async function publishAsset(client, data) {
return client.asset.publish({ assetId: data.sys.id }, data);
}
async function createValidateBulkAction(client, options, data) {
return client.bulkAction.validate(options, data);
}
async function createPublishBulkAction(client, options, data) {
return client.bulkAction.publish(options, data);
}
async function createUnpublishBulkAction(client, options, data) {
return client.bulkAction.unpublish(options, data);
}
async function createWebhook(client, data) {
return client.webhook.create({}, data);
}
async function getBulkAction(client, data) {
return client.bulkAction.get(data);
}
async function fetchEntriesByIds(client, entryIds, query) {
const entryIdChunks = lodash_1.default.chunk(entryIds, 100);
let entries = [];
for (const entryIdsChunk of entryIdChunks) {
const result = await client.entry.getMany({
query: {
'sys.id[in]': entryIdsChunk.join(','),
limit: 1000,
...query
}
});
entries = entries.concat(result.items);
}
return entries;
}
async function fetchAssetsByIds(client, assetIds, query) {
const assetIdChunks = lodash_1.default.chunk(assetIds, 100);
let assets = [];
for (const entryIdsChunk of assetIdChunks) {
const result = await client.asset.getMany({
query: {
'sys.id[in]': entryIdsChunk.join(','),
limit: 1000,
...query
}
});
assets = assets.concat(result.items);
}
return assets;
}
async function fetchAllEntries(client, logger) {
return fetchAllItems({ getMany: client.entry.getMany, logger });
}
async function fetchEntriesUpdatedAfter(client, date, logger) {
return fetchAllItems({
getMany: client.entry.getMany,
logger,
query: {
'sys.updatedAt[gt]': date
}
});
}
async function fetchAllAssets(client, logger) {
return fetchAllItems({ getMany: client.asset.getMany, logger });
}
async function fetchAssetsUpdatedAfter(client, date, logger) {
return fetchAllItems({
getMany: client.asset.getMany,
logger,
query: {
'sys.updatedAt[gt]': date
}
});
}
async function fetchAllLocales(client, logger) {
return fetchAllItems({ getMany: client.locale.getMany, logger });
}
async function fetchAllUsers(client, logger) {
return fetchAllItems({ getMany: client.user.getManyForSpace, logger });
}
async function fetchAllContentTypes(client, logger) {
return fetchAllItems({ getMany: client.contentType.getMany, logger });
}
async function hasContentTypesUpdatedAfter(client, date, logger) {
const updatedContentTypes = await fetchAllItems({
getMany: client.contentType.getMany,
logger,
query: {
'sys.updatedAt[gt]': date,
limit: 1
}
});
return updatedContentTypes.length > 0;
}
async function fetchContentTypesUpdatedAfter(client, date, logger) {
return fetchAllItems({
getMany: client.contentType.getMany,
logger,
query: {
'sys.updatedAt[gt]': date
}
});
}
async function fetchAllEditorInterfaces(client, logger) {
return fetchAllItems({ getMany: client.editorInterface.getMany, logger });
}
async function fetchAllAppInstallations(client, logger) {
return fetchAllItems({ getMany: client.appInstallation.getMany, logger });
}
async function fetchAllWebhooks(client, logger) {
return fetchAllItems({ getMany: client.webhook.getMany, logger });
}
async function fetchAllReleases(client, logger) {
return fetchAllItemsCursor(client.release.query, {}, logger);
}
async function fetchAllSchedules(client, params, logger) {
return fetchAllItemsCursor(client.scheduledActions.getMany, {
'environment.sys.id': params.environment,
'entity.sys.id': params.entityId,
'sys.status': params.status
}, logger);
}
async function fetchScheduleById(client, params) {
return client.scheduledActions.get({ scheduledActionId: params.scheduleId, environmentId: params.environment });
}
async function fetchEntityVersions(client, params) {
return client.snapshot.getManyForEntry({ entryId: params.entityId, environmentId: params.environment });
}
async function fetchEntityVersion(client, params) {
return client.snapshot.getForEntry({ entryId: params.entityId, snapshotId: params.versionId, environmentId: params.environment });
}
async function createScheduledAction(client, options) {
const contentfulRelease = await client.release.create({}, {
entities: {
sys: { type: 'Array' },
items: options.documentIds.map((docId) => ({ sys: { linkType: 'Entry', type: 'Link', id: docId } }))
},
title: options.name
});
const contentfulSchedule = await client.scheduledActions.create({}, {
entity: { sys: { type: 'Link', linkType: 'Release', id: contentfulRelease.sys.id } },
environment: { sys: { type: 'Link', linkType: 'Environment', id: options.environment } },
scheduledFor: { datetime: options.executeAt },
action: options.action
});
return { schedule: (0, contentful_scheduled_actions_converter_1.convertScheduledAction)(contentfulRelease, contentfulSchedule), contentfulRelease, contentfulSchedule };
}
async function updateScheduledAction(client, scheduledActionId, options) {
let contentfulRelease = await client.release.get({ releaseId: scheduledActionId });
if (!contentfulRelease) {
throw new Error('Contentful release not found for scheduled action');
}
const releaseUpdateObj = {
...lodash_1.default.pick(contentfulRelease, ['title', 'entities']),
...(options.documentIds
? { entities: { sys: { type: 'Array' }, items: options.documentIds.map((docId) => ({ sys: { linkType: 'Entry', type: 'Link', id: docId } })) } }
: {}),
...(options.name ? { title: options.name } : {})
};
contentfulRelease = await client.release.update({ releaseId: scheduledActionId, version: contentfulRelease.sys.version }, releaseUpdateObj);
const contentfulSchedules = await fetchAllSchedules(client, {
environment: options.environment,
entityId: contentfulRelease.sys.id,
status: 'scheduled'
});
const releaseSchedule = (0, contentful_scheduled_actions_converter_1.findScheduleForRelease)(lodash_1.default.sortBy(contentfulSchedules, ['scheduledFor.datetime']));
if (!releaseSchedule) {
throw new Error('Contentful schedule not found for scheduled action, or schedule is already executed or cancelled');
}
const scheduleUpdateObj = {
...lodash_1.default.pick(releaseSchedule, ['action', 'entity', 'environment']),
scheduledFor: {
...releaseSchedule.scheduledFor,
...(options.executeAt ? { datetime: options.executeAt } : {})
}
};
const contentfulSchedule = await client.scheduledActions.update({ scheduledActionId: releaseSchedule.sys.id, version: releaseSchedule.sys.version }, scheduleUpdateObj);
return (0, contentful_scheduled_actions_converter_1.convertScheduledAction)(contentfulRelease, contentfulSchedule);
}
async function cancelScheduledAction(client, scheduledActionId, options) {
const contentfulRelease = await client.release.get({ releaseId: scheduledActionId });
if (!contentfulRelease) {
throw new Error('Contentful release not found for scheduled action');
}
const contentfulSchedules = await fetchAllSchedules(client, {
environment: options.environment,
entityId: contentfulRelease.sys.id,
status: 'scheduled'
});
let releaseSchedule = (0, contentful_scheduled_actions_converter_1.findScheduleForRelease)(lodash_1.default.sortBy(contentfulSchedules, ['scheduledFor.datetime']));
if (!releaseSchedule) {
throw new Error('Contentful schedule not found for scheduled action');
}
releaseSchedule = await client.scheduledActions.delete({ scheduledActionId: releaseSchedule.sys.id, environmentId: options.environment });
return (0, contentful_scheduled_actions_converter_1.convertScheduledAction)(contentfulRelease, releaseSchedule);
}
async function getScheduledAction(client, scheduledActionId, options) {
const contentfulRelease = await client.release.get({ releaseId: scheduledActionId });
if (!contentfulRelease) {
return null;
}
const contentfulSchedules = await fetchAllSchedules(client, {
environment: options.environment,
entityId: contentfulRelease.sys.id
});
const releaseSchedule = (0, contentful_scheduled_actions_converter_1.findScheduleForRelease)(lodash_1.default.sortBy(contentfulSchedules, ['scheduledFor.datetime']));
if (!releaseSchedule) {
return null;
}
return (0, contentful_scheduled_actions_converter_1.convertScheduledAction)(contentfulRelease, releaseSchedule);
}
async function fetchAllItems({ getMany, logger, query }) {
let limit = 1000;
let items = [];
let hasMoreItems = true;
let retries = 0;
while (hasMoreItems) {
try {
const result = await getMany({
query: {
skip: items.length,
limit: limit,
...query
}
});
items = items.concat(result.items);
hasMoreItems = result.total > items.length && result.items.length === limit;
retries = 0;
limit = 1000;
if (result.total > 1000) {
logger?.info(`Fetched ${items.length} of ${result.total} items`);
}
}
catch (err) {
if (retries > 4) {
throw err;
}
if (lodash_1.default.get(err, 'message')?.includes('Response size too big')) {
limit = Math.trunc(limit / 2);
}
else {
throw err;
}
retries++;
}
}
return items;
}
async function fetchAllItemsCursor(fn, query, logger) {
// Contentful didn't do a good job of typing scheduledActions.getMany, so the type names here are specific to Release,
// but apply to ScheduledActions as well, as both are implemented as cursorPaginatedCollections
let limit = 1000;
let items = [];
let hasMoreItems = true;
let pageNext = undefined;
let retries = 0;
while (hasMoreItems) {
try {
const result = await fn({
query: { ...query, pageNext, limit }
});
items = items.concat(result.items);
hasMoreItems = !!result.pages?.next;
const nextUrlParams = result.pages?.next?.split('?')[1];
pageNext = new URLSearchParams(nextUrlParams).get('pageNext') ?? undefined;
retries = 0;
limit = 1000;
logger?.info(`Fetched ${items.length} items`);
}
catch (err) {
if (retries > 4) {
throw err;
}
if (lodash_1.default.get(err, 'message')?.includes('Response size too big')) {
limit = Math.trunc(limit / 2);
}
else {
throw err;
}
retries++;
}
}
return items;
}
//# sourceMappingURL=contentful-api-client.js.map