UNPKG

contentful-export

Version:

this tool allows you to export a space to a JSON dump

107 lines (104 loc) 4.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.calculateExpiryTimestamp = calculateExpiryTimestamp; exports.isEmbargoedAsset = isEmbargoedAsset; exports.shouldCreateNewCacheItem = void 0; exports.signUrl = signUrl; var _jsonwebtoken = _interopRequireDefault(require("jsonwebtoken")); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const SIX_HOURS_IN_MS = 6 * 60 * 60 * 1000; const assetKeyCache = new Map(); /** * @param {string} host - The Contentful API host. * @param {string} accessToken - The access token for the Contentful API. * @param {string} spaceId - The ID of the Contentful space. * @param {string} environmentId - The ID of the Contentful environment. * @param {number} expiresAtMs - The expiration time in milliseconds. * @param {import('axios').AxiosInstance} httpClient - The HTTP client to use for requests. */ function createAssetKey(host, accessToken, spaceId, environmentId, expiresAtMs, httpClient) { return httpClient(`https://${host}/spaces/${spaceId}/environments/${environmentId}/asset_keys`, { method: 'POST', data: JSON.stringify({ expiresAt: Math.floor(expiresAtMs / 1000) // in seconds }), headers: { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json' } }); } const shouldCreateNewCacheItem = (cacheItem, currentExpiresAtMs) => !cacheItem || currentExpiresAtMs - cacheItem.expiresAtMs > SIX_HOURS_IN_MS; exports.shouldCreateNewCacheItem = shouldCreateNewCacheItem; async function createCachedAssetKey(host, accessToken, spaceId, environmentId, minExpiresAtMs, httpClient) { const cacheKey = `${host}:${spaceId}:${environmentId}`; let cacheItem = assetKeyCache.get(cacheKey); if (shouldCreateNewCacheItem(cacheItem, minExpiresAtMs)) { const expiresAtMs = calculateExpiryTimestamp(); if (minExpiresAtMs > expiresAtMs) { throw new Error(`Cannot fetch an asset key so far in the future: ${minExpiresAtMs} > ${expiresAtMs}`); } try { const assetKeyResponse = await createAssetKey(host, accessToken, spaceId, environmentId, expiresAtMs, httpClient); cacheItem = { expiresAtMs, result: assetKeyResponse.data }; assetKeyCache.set(cacheKey, cacheItem); } catch (err) { // If we encounter an error, make sure to clear the cache item if this is the most recent fetch. const curCacheItem = assetKeyCache.get(cacheKey); if (curCacheItem === cacheItem) { assetKeyCache.delete(cacheKey); } return Promise.reject(err); } } return cacheItem.result; } function generateSignedToken(secret, urlWithoutQueryParams, expiresAtMs) { // Convert expiresAtMs to seconds, if defined const exp = expiresAtMs ? Math.floor(expiresAtMs / 1000) : undefined; return _jsonwebtoken.default.sign({ sub: urlWithoutQueryParams, exp }, secret, { algorithm: 'HS256' }); } function generateSignedUrl(policy, secret, url, expiresAtMs) { const parsedUrl = new URL(url); const urlWithoutQueryParams = parsedUrl.origin + parsedUrl.pathname; const token = generateSignedToken(secret, urlWithoutQueryParams, expiresAtMs); parsedUrl.searchParams.set('token', token); parsedUrl.searchParams.set('policy', policy); return parsedUrl.toString(); } function isEmbargoedAsset(url) { const pattern = /((images)|(assets)|(downloads)|(videos))\.secure\./; return pattern.test(url); } function calculateExpiryTimestamp() { return Date.now() + SIX_HOURS_IN_MS; } /** * @param {string} host - The Contentful API host. * @param {string} accessToken - The access token for the Contentful API. * @param {string} spaceId - The ID of the Contentful space. * @param {string} environmentId - The ID of the Contentful environment. * @param {string} url - The URL to be signed. * @param {number} expiresAtMs - The expiration time in milliseconds. * @param {import('axios').AxiosInstance} httpClient - The HTTP client to use for requests. */ function signUrl(host, accessToken, spaceId, environmentId, url, expiresAtMs, httpClient) { // handle urls without protocol if (url.startsWith('//')) { url = 'https:' + url; } return createCachedAssetKey(host, accessToken, spaceId, environmentId, expiresAtMs, httpClient).then(({ policy, secret }) => generateSignedUrl(policy, secret, url, expiresAtMs)); }