Ich habe soweit automatisiert the Emails sortieren aber ich muss noch schauen was es fur bugs es gibt wenn die app online ist deswegen wurde ich mit diesen Commit die website veroffentlichen obwohjl es sein konnte das es noch nicht fertig ist und verkaufs bereit
292 lines
11 KiB
JavaScript
292 lines
11 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.makeAutoPaginationMethods = void 0;
|
|
const utils_js_1 = require("./utils.js");
|
|
class V1Iterator {
|
|
constructor(firstPagePromise, requestArgs, spec, stripeResource) {
|
|
this.index = 0;
|
|
this.pagePromise = firstPagePromise;
|
|
this.promiseCache = { currentPromise: null };
|
|
this.requestArgs = requestArgs;
|
|
this.spec = spec;
|
|
this.stripeResource = stripeResource;
|
|
}
|
|
async iterate(pageResult) {
|
|
if (!(pageResult &&
|
|
pageResult.data &&
|
|
typeof pageResult.data.length === 'number')) {
|
|
throw Error('Unexpected: Stripe API response does not have a well-formed `data` array.');
|
|
}
|
|
const reverseIteration = isReverseIteration(this.requestArgs);
|
|
if (this.index < pageResult.data.length) {
|
|
const idx = reverseIteration
|
|
? pageResult.data.length - 1 - this.index
|
|
: this.index;
|
|
const value = pageResult.data[idx];
|
|
this.index += 1;
|
|
return { value, done: false };
|
|
}
|
|
else if (pageResult.has_more) {
|
|
// Reset counter, request next page, and recurse.
|
|
this.index = 0;
|
|
this.pagePromise = this.getNextPage(pageResult);
|
|
const nextPageResult = await this.pagePromise;
|
|
return this.iterate(nextPageResult);
|
|
}
|
|
return { done: true, value: undefined };
|
|
}
|
|
/** @abstract */
|
|
getNextPage(_pageResult) {
|
|
throw new Error('Unimplemented');
|
|
}
|
|
async _next() {
|
|
return this.iterate(await this.pagePromise);
|
|
}
|
|
next() {
|
|
/**
|
|
* If a user calls `.next()` multiple times in parallel,
|
|
* return the same result until something has resolved
|
|
* to prevent page-turning race conditions.
|
|
*/
|
|
if (this.promiseCache.currentPromise) {
|
|
return this.promiseCache.currentPromise;
|
|
}
|
|
const nextPromise = (async () => {
|
|
const ret = await this._next();
|
|
this.promiseCache.currentPromise = null;
|
|
return ret;
|
|
})();
|
|
this.promiseCache.currentPromise = nextPromise;
|
|
return nextPromise;
|
|
}
|
|
}
|
|
class V1ListIterator extends V1Iterator {
|
|
getNextPage(pageResult) {
|
|
const reverseIteration = isReverseIteration(this.requestArgs);
|
|
const lastId = getLastId(pageResult, reverseIteration);
|
|
return this.stripeResource._makeRequest(this.requestArgs, this.spec, {
|
|
[reverseIteration ? 'ending_before' : 'starting_after']: lastId,
|
|
});
|
|
}
|
|
}
|
|
class V1SearchIterator extends V1Iterator {
|
|
getNextPage(pageResult) {
|
|
if (!pageResult.next_page) {
|
|
throw Error('Unexpected: Stripe API response does not have a well-formed `next_page` field, but `has_more` was true.');
|
|
}
|
|
return this.stripeResource._makeRequest(this.requestArgs, this.spec, {
|
|
page: pageResult.next_page,
|
|
});
|
|
}
|
|
}
|
|
class V2ListIterator {
|
|
constructor(firstPagePromise, requestArgs, spec, stripeResource) {
|
|
this.currentPageIterator = (async () => {
|
|
const page = await firstPagePromise;
|
|
return page.data[Symbol.iterator]();
|
|
})();
|
|
this.nextPageUrl = (async () => {
|
|
const page = await firstPagePromise;
|
|
return page.next_page_url || null;
|
|
})();
|
|
this.requestArgs = requestArgs;
|
|
this.spec = spec;
|
|
this.stripeResource = stripeResource;
|
|
}
|
|
async turnPage() {
|
|
const nextPageUrl = await this.nextPageUrl;
|
|
if (!nextPageUrl)
|
|
return null;
|
|
this.spec.fullPath = nextPageUrl;
|
|
const page = await this.stripeResource._makeRequest([], this.spec, {});
|
|
this.nextPageUrl = Promise.resolve(page.next_page_url);
|
|
this.currentPageIterator = Promise.resolve(page.data[Symbol.iterator]());
|
|
return this.currentPageIterator;
|
|
}
|
|
async next() {
|
|
{
|
|
const result = (await this.currentPageIterator).next();
|
|
if (!result.done)
|
|
return { done: false, value: result.value };
|
|
}
|
|
const nextPageIterator = await this.turnPage();
|
|
if (!nextPageIterator) {
|
|
return { done: true, value: undefined };
|
|
}
|
|
const result = nextPageIterator.next();
|
|
if (!result.done)
|
|
return { done: false, value: result.value };
|
|
return { done: true, value: undefined };
|
|
}
|
|
}
|
|
const makeAutoPaginationMethods = (stripeResource, requestArgs, spec, firstPagePromise) => {
|
|
const apiMode = (0, utils_js_1.getAPIMode)(spec.fullPath || spec.path);
|
|
if (apiMode !== 'v2' && spec.methodType === 'search') {
|
|
return makeAutoPaginationMethodsFromIterator(new V1SearchIterator(firstPagePromise, requestArgs, spec, stripeResource));
|
|
}
|
|
if (apiMode !== 'v2' && spec.methodType === 'list') {
|
|
return makeAutoPaginationMethodsFromIterator(new V1ListIterator(firstPagePromise, requestArgs, spec, stripeResource));
|
|
}
|
|
if (apiMode === 'v2' && spec.methodType === 'list') {
|
|
return makeAutoPaginationMethodsFromIterator(new V2ListIterator(firstPagePromise, requestArgs, spec, stripeResource));
|
|
}
|
|
return null;
|
|
};
|
|
exports.makeAutoPaginationMethods = makeAutoPaginationMethods;
|
|
const makeAutoPaginationMethodsFromIterator = (iterator) => {
|
|
const autoPagingEach = makeAutoPagingEach((...args) => iterator.next(...args));
|
|
const autoPagingToArray = makeAutoPagingToArray(autoPagingEach);
|
|
const autoPaginationMethods = {
|
|
autoPagingEach,
|
|
autoPagingToArray,
|
|
// Async iterator functions:
|
|
next: () => iterator.next(),
|
|
return: () => {
|
|
// This is required for `break`.
|
|
return {};
|
|
},
|
|
[getAsyncIteratorSymbol()]: () => {
|
|
return autoPaginationMethods;
|
|
},
|
|
};
|
|
return autoPaginationMethods;
|
|
};
|
|
/**
|
|
* ----------------
|
|
* Private Helpers:
|
|
* ----------------
|
|
*/
|
|
function getAsyncIteratorSymbol() {
|
|
if (typeof Symbol !== 'undefined' && Symbol.asyncIterator) {
|
|
return Symbol.asyncIterator;
|
|
}
|
|
// Follow the convention from libraries like iterall: https://github.com/leebyron/iterall#asynciterator-1
|
|
return '@@asyncIterator';
|
|
}
|
|
function getDoneCallback(args) {
|
|
if (args.length < 2) {
|
|
return null;
|
|
}
|
|
const onDone = args[1];
|
|
if (typeof onDone !== 'function') {
|
|
throw Error(`The second argument to autoPagingEach, if present, must be a callback function; received ${typeof onDone}`);
|
|
}
|
|
return onDone;
|
|
}
|
|
/**
|
|
* We allow four forms of the `onItem` callback (the middle two being equivalent),
|
|
*
|
|
* 1. `.autoPagingEach((item) => { doSomething(item); return false; });`
|
|
* 2. `.autoPagingEach(async (item) => { await doSomething(item); return false; });`
|
|
* 3. `.autoPagingEach((item) => doSomething(item).then(() => false));`
|
|
* 4. `.autoPagingEach((item, next) => { doSomething(item); next(false); });`
|
|
*
|
|
* In addition to standard validation, this helper
|
|
* coalesces the former forms into the latter form.
|
|
*/
|
|
function getItemCallback(args) {
|
|
if (args.length === 0) {
|
|
return undefined;
|
|
}
|
|
const onItem = args[0];
|
|
if (typeof onItem !== 'function') {
|
|
throw Error(`The first argument to autoPagingEach, if present, must be a callback function; received ${typeof onItem}`);
|
|
}
|
|
// 4. `.autoPagingEach((item, next) => { doSomething(item); next(false); });`
|
|
if (onItem.length === 2) {
|
|
return onItem;
|
|
}
|
|
if (onItem.length > 2) {
|
|
throw Error(`The \`onItem\` callback function passed to autoPagingEach must accept at most two arguments; got ${onItem}`);
|
|
}
|
|
// This magically handles all three of these usecases (the latter two being functionally identical):
|
|
// 1. `.autoPagingEach((item) => { doSomething(item); return false; });`
|
|
// 2. `.autoPagingEach(async (item) => { await doSomething(item); return false; });`
|
|
// 3. `.autoPagingEach((item) => doSomething(item).then(() => false));`
|
|
return function _onItem(item, next) {
|
|
const shouldContinue = onItem(item);
|
|
next(shouldContinue);
|
|
};
|
|
}
|
|
function getLastId(listResult, reverseIteration) {
|
|
const lastIdx = reverseIteration ? 0 : listResult.data.length - 1;
|
|
const lastItem = listResult.data[lastIdx];
|
|
const lastId = lastItem && lastItem.id;
|
|
if (!lastId) {
|
|
throw Error('Unexpected: No `id` found on the last item while auto-paging a list.');
|
|
}
|
|
return lastId;
|
|
}
|
|
function makeAutoPagingEach(asyncIteratorNext) {
|
|
return function autoPagingEach( /* onItem?, onDone? */) {
|
|
const args = [].slice.call(arguments);
|
|
const onItem = getItemCallback(args);
|
|
const onDone = getDoneCallback(args);
|
|
if (args.length > 2) {
|
|
throw Error(`autoPagingEach takes up to two arguments; received ${args}`);
|
|
}
|
|
const autoPagePromise = wrapAsyncIteratorWithCallback(asyncIteratorNext,
|
|
// @ts-ignore we might need a null check
|
|
onItem);
|
|
return (0, utils_js_1.callbackifyPromiseWithTimeout)(autoPagePromise, onDone);
|
|
};
|
|
}
|
|
function makeAutoPagingToArray(autoPagingEach) {
|
|
return function autoPagingToArray(opts, onDone) {
|
|
const limit = opts && opts.limit;
|
|
if (!limit) {
|
|
throw Error('You must pass a `limit` option to autoPagingToArray, e.g., `autoPagingToArray({limit: 1000});`.');
|
|
}
|
|
if (limit > 10000) {
|
|
throw Error('You cannot specify a limit of more than 10,000 items to fetch in `autoPagingToArray`; use `autoPagingEach` to iterate through longer lists.');
|
|
}
|
|
const promise = new Promise((resolve, reject) => {
|
|
const items = [];
|
|
autoPagingEach((item) => {
|
|
items.push(item);
|
|
if (items.length >= limit) {
|
|
return false;
|
|
}
|
|
})
|
|
.then(() => {
|
|
resolve(items);
|
|
})
|
|
.catch(reject);
|
|
});
|
|
// @ts-ignore
|
|
return (0, utils_js_1.callbackifyPromiseWithTimeout)(promise, onDone);
|
|
};
|
|
}
|
|
function wrapAsyncIteratorWithCallback(asyncIteratorNext, onItem) {
|
|
return new Promise((resolve, reject) => {
|
|
function handleIteration(iterResult) {
|
|
if (iterResult.done) {
|
|
resolve();
|
|
return;
|
|
}
|
|
const item = iterResult.value;
|
|
return new Promise((next) => {
|
|
// Bit confusing, perhaps; we pass a `resolve` fn
|
|
// to the user, so they can decide when and if to continue.
|
|
// They can return false, or a promise which resolves to false, to break.
|
|
onItem(item, next);
|
|
}).then((shouldContinue) => {
|
|
if (shouldContinue === false) {
|
|
return handleIteration({ done: true, value: undefined });
|
|
}
|
|
else {
|
|
return asyncIteratorNext().then(handleIteration);
|
|
}
|
|
});
|
|
}
|
|
asyncIteratorNext()
|
|
.then(handleIteration)
|
|
.catch(reject);
|
|
});
|
|
}
|
|
function isReverseIteration(requestArgs) {
|
|
const args = [].slice.call(requestArgs);
|
|
const dataFromArgs = (0, utils_js_1.getDataFromArgs)(args);
|
|
return !!dataFromArgs.ending_before;
|
|
}
|