Complete Email Sortierer implementation with Appwrite and Stripe integration
This commit is contained in:
247
server/node_modules/stripe/cjs/autoPagination.js
generated
vendored
Normal file
247
server/node_modules/stripe/cjs/autoPagination.js
generated
vendored
Normal file
@@ -0,0 +1,247 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.makeAutoPaginationMethods = void 0;
|
||||
const utils_js_1 = require("./utils.js");
|
||||
class StripeIterator {
|
||||
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 ListIterator extends StripeIterator {
|
||||
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 SearchIterator extends StripeIterator {
|
||||
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,
|
||||
});
|
||||
}
|
||||
}
|
||||
const makeAutoPaginationMethods = (stripeResource, requestArgs, spec, firstPagePromise) => {
|
||||
if (spec.methodType === 'search') {
|
||||
return makeAutoPaginationMethodsFromIterator(new SearchIterator(firstPagePromise, requestArgs, spec, stripeResource));
|
||||
}
|
||||
if (spec.methodType === 'list') {
|
||||
return makeAutoPaginationMethodsFromIterator(new ListIterator(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;
|
||||
}
|
||||
Reference in New Issue
Block a user