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
341 lines
11 KiB
JavaScript
341 lines
11 KiB
JavaScript
import * as qs from 'qs';
|
|
const OPTIONS_KEYS = [
|
|
'apiKey',
|
|
'idempotencyKey',
|
|
'stripeAccount',
|
|
'apiVersion',
|
|
'maxNetworkRetries',
|
|
'timeout',
|
|
'host',
|
|
'authenticator',
|
|
'stripeContext',
|
|
'additionalHeaders',
|
|
];
|
|
export function isOptionsHash(o) {
|
|
return (o &&
|
|
typeof o === 'object' &&
|
|
OPTIONS_KEYS.some((prop) => Object.prototype.hasOwnProperty.call(o, prop)));
|
|
}
|
|
/**
|
|
* Stringifies an Object, accommodating nested objects
|
|
* (forming the conventional key 'parent[child]=value')
|
|
*/
|
|
export function queryStringifyRequestData(data, apiMode) {
|
|
return (qs
|
|
.stringify(data, {
|
|
serializeDate: (d) => Math.floor(d.getTime() / 1000).toString(),
|
|
arrayFormat: apiMode == 'v2' ? 'repeat' : 'indices',
|
|
})
|
|
// Don't use strict form encoding by changing the square bracket control
|
|
// characters back to their literals. This is fine by the server, and
|
|
// makes these parameter strings easier to read.
|
|
.replace(/%5B/g, '[')
|
|
.replace(/%5D/g, ']'));
|
|
}
|
|
/**
|
|
* Outputs a new function with interpolated object property values.
|
|
* Use like so:
|
|
* const fn = makeURLInterpolator('some/url/{param1}/{param2}');
|
|
* fn({ param1: 123, param2: 456 }); // => 'some/url/123/456'
|
|
*/
|
|
export const makeURLInterpolator = (() => {
|
|
const rc = {
|
|
'\n': '\\n',
|
|
'"': '\\"',
|
|
'\u2028': '\\u2028',
|
|
'\u2029': '\\u2029',
|
|
};
|
|
return (str) => {
|
|
const cleanString = str.replace(/["\n\r\u2028\u2029]/g, ($0) => rc[$0]);
|
|
return (outputs) => {
|
|
return cleanString.replace(/\{([\s\S]+?)\}/g, ($0, $1) =>
|
|
// @ts-ignore
|
|
encodeURIComponent(outputs[$1] || ''));
|
|
};
|
|
};
|
|
})();
|
|
export function extractUrlParams(path) {
|
|
const params = path.match(/\{\w+\}/g);
|
|
if (!params) {
|
|
return [];
|
|
}
|
|
return params.map((param) => param.replace(/[{}]/g, ''));
|
|
}
|
|
/**
|
|
* Return the data argument from a list of arguments
|
|
*
|
|
* @param {object[]} args
|
|
* @returns {object}
|
|
*/
|
|
export function getDataFromArgs(args) {
|
|
if (!Array.isArray(args) || !args[0] || typeof args[0] !== 'object') {
|
|
return {};
|
|
}
|
|
if (!isOptionsHash(args[0])) {
|
|
return args.shift();
|
|
}
|
|
const argKeys = Object.keys(args[0]);
|
|
const optionKeysInArgs = argKeys.filter((key) => OPTIONS_KEYS.includes(key));
|
|
// In some cases options may be the provided as the first argument.
|
|
// Here we're detecting a case where there are two distinct arguments
|
|
// (the first being args and the second options) and with known
|
|
// option keys in the first so that we can warn the user about it.
|
|
if (optionKeysInArgs.length > 0 &&
|
|
optionKeysInArgs.length !== argKeys.length) {
|
|
emitWarning(`Options found in arguments (${optionKeysInArgs.join(', ')}). Did you mean to pass an options object? See https://github.com/stripe/stripe-node/wiki/Passing-Options.`);
|
|
}
|
|
return {};
|
|
}
|
|
/**
|
|
* Return the options hash from a list of arguments
|
|
*/
|
|
export function getOptionsFromArgs(args) {
|
|
const opts = {
|
|
host: null,
|
|
headers: {},
|
|
settings: {},
|
|
};
|
|
if (args.length > 0) {
|
|
const arg = args[args.length - 1];
|
|
if (typeof arg === 'string') {
|
|
opts.authenticator = createApiKeyAuthenticator(args.pop());
|
|
}
|
|
else if (isOptionsHash(arg)) {
|
|
const params = Object.assign({}, args.pop());
|
|
const extraKeys = Object.keys(params).filter((key) => !OPTIONS_KEYS.includes(key));
|
|
if (extraKeys.length) {
|
|
emitWarning(`Invalid options found (${extraKeys.join(', ')}); ignoring.`);
|
|
}
|
|
if (params.apiKey) {
|
|
opts.authenticator = createApiKeyAuthenticator(params.apiKey);
|
|
}
|
|
if (params.idempotencyKey) {
|
|
opts.headers['Idempotency-Key'] = params.idempotencyKey;
|
|
}
|
|
if (params.stripeAccount) {
|
|
opts.headers['Stripe-Account'] = params.stripeAccount;
|
|
}
|
|
if (params.stripeContext) {
|
|
if (opts.headers['Stripe-Account']) {
|
|
throw new Error("Can't specify both stripeAccount and stripeContext.");
|
|
}
|
|
opts.headers['Stripe-Context'] = params.stripeContext;
|
|
}
|
|
if (params.apiVersion) {
|
|
opts.headers['Stripe-Version'] = params.apiVersion;
|
|
}
|
|
if (Number.isInteger(params.maxNetworkRetries)) {
|
|
opts.settings.maxNetworkRetries = params.maxNetworkRetries;
|
|
}
|
|
if (Number.isInteger(params.timeout)) {
|
|
opts.settings.timeout = params.timeout;
|
|
}
|
|
if (params.host) {
|
|
opts.host = params.host;
|
|
}
|
|
if (params.authenticator) {
|
|
if (params.apiKey) {
|
|
throw new Error("Can't specify both apiKey and authenticator.");
|
|
}
|
|
if (typeof params.authenticator !== 'function') {
|
|
throw new Error('The authenticator must be a function ' +
|
|
'receiving a request as the first parameter.');
|
|
}
|
|
opts.authenticator = params.authenticator;
|
|
}
|
|
if (params.additionalHeaders) {
|
|
opts.headers = params.additionalHeaders;
|
|
}
|
|
}
|
|
}
|
|
return opts;
|
|
}
|
|
/**
|
|
* Provide simple "Class" extension mechanism.
|
|
* <!-- Public API accessible via Stripe.StripeResource.extend -->
|
|
*/
|
|
export function protoExtend(sub) {
|
|
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
const Super = this;
|
|
const Constructor = Object.prototype.hasOwnProperty.call(sub, 'constructor')
|
|
? sub.constructor
|
|
: function (...args) {
|
|
Super.apply(this, args);
|
|
};
|
|
// This initialization logic is somewhat sensitive to be compatible with
|
|
// divergent JS implementations like the one found in Qt. See here for more
|
|
// context:
|
|
//
|
|
// https://github.com/stripe/stripe-node/pull/334
|
|
Object.assign(Constructor, Super);
|
|
Constructor.prototype = Object.create(Super.prototype);
|
|
Object.assign(Constructor.prototype, sub);
|
|
return Constructor;
|
|
}
|
|
/**
|
|
* Remove empty values from an object
|
|
*/
|
|
export function removeNullish(obj) {
|
|
if (typeof obj !== 'object') {
|
|
throw new Error('Argument must be an object');
|
|
}
|
|
return Object.keys(obj).reduce((result, key) => {
|
|
if (obj[key] != null) {
|
|
result[key] = obj[key];
|
|
}
|
|
return result;
|
|
}, {});
|
|
}
|
|
/**
|
|
* Normalize standard HTTP Headers:
|
|
* {'foo-bar': 'hi'}
|
|
* becomes
|
|
* {'Foo-Bar': 'hi'}
|
|
*/
|
|
export function normalizeHeaders(obj) {
|
|
if (!(obj && typeof obj === 'object')) {
|
|
return obj;
|
|
}
|
|
return Object.keys(obj).reduce((result, header) => {
|
|
result[normalizeHeader(header)] = obj[header];
|
|
return result;
|
|
}, {});
|
|
}
|
|
/**
|
|
* Stolen from https://github.com/marten-de-vries/header-case-normalizer/blob/master/index.js#L36-L41
|
|
* without the exceptions which are irrelevant to us.
|
|
*/
|
|
export function normalizeHeader(header) {
|
|
return header
|
|
.split('-')
|
|
.map((text) => text.charAt(0).toUpperCase() + text.substr(1).toLowerCase())
|
|
.join('-');
|
|
}
|
|
export function callbackifyPromiseWithTimeout(promise, callback) {
|
|
if (callback) {
|
|
// Ensure callback is called outside of promise stack.
|
|
return promise.then((res) => {
|
|
setTimeout(() => {
|
|
callback(null, res);
|
|
}, 0);
|
|
}, (err) => {
|
|
setTimeout(() => {
|
|
callback(err, null);
|
|
}, 0);
|
|
});
|
|
}
|
|
return promise;
|
|
}
|
|
/**
|
|
* Allow for special capitalization cases (such as OAuth)
|
|
*/
|
|
export function pascalToCamelCase(name) {
|
|
if (name === 'OAuth') {
|
|
return 'oauth';
|
|
}
|
|
else {
|
|
return name[0].toLowerCase() + name.substring(1);
|
|
}
|
|
}
|
|
export function emitWarning(warning) {
|
|
if (typeof process.emitWarning !== 'function') {
|
|
return console.warn(`Stripe: ${warning}`); /* eslint-disable-line no-console */
|
|
}
|
|
return process.emitWarning(warning, 'Stripe');
|
|
}
|
|
export function isObject(obj) {
|
|
const type = typeof obj;
|
|
return (type === 'function' || type === 'object') && !!obj;
|
|
}
|
|
// For use in multipart requests
|
|
export function flattenAndStringify(data) {
|
|
const result = {};
|
|
const step = (obj, prevKey) => {
|
|
Object.entries(obj).forEach(([key, value]) => {
|
|
const newKey = prevKey ? `${prevKey}[${key}]` : key;
|
|
if (isObject(value)) {
|
|
if (!(value instanceof Uint8Array) &&
|
|
!Object.prototype.hasOwnProperty.call(value, 'data')) {
|
|
// Non-buffer non-file Objects are recursively flattened
|
|
return step(value, newKey);
|
|
}
|
|
else {
|
|
// Buffers and file objects are stored without modification
|
|
result[newKey] = value;
|
|
}
|
|
}
|
|
else {
|
|
// Primitives are converted to strings
|
|
result[newKey] = String(value);
|
|
}
|
|
});
|
|
};
|
|
step(data, null);
|
|
return result;
|
|
}
|
|
export function validateInteger(name, n, defaultVal) {
|
|
if (!Number.isInteger(n)) {
|
|
if (defaultVal !== undefined) {
|
|
return defaultVal;
|
|
}
|
|
else {
|
|
throw new Error(`${name} must be an integer`);
|
|
}
|
|
}
|
|
return n;
|
|
}
|
|
export function determineProcessUserAgentProperties() {
|
|
return typeof process === 'undefined'
|
|
? {}
|
|
: {
|
|
lang_version: process.version,
|
|
platform: process.platform,
|
|
};
|
|
}
|
|
export function createApiKeyAuthenticator(apiKey) {
|
|
const authenticator = (request) => {
|
|
request.headers.Authorization = 'Bearer ' + apiKey;
|
|
return Promise.resolve();
|
|
};
|
|
// For testing
|
|
authenticator._apiKey = apiKey;
|
|
return authenticator;
|
|
}
|
|
/**
|
|
* Joins an array of Uint8Arrays into a single Uint8Array
|
|
*/
|
|
export function concat(arrays) {
|
|
const totalLength = arrays.reduce((len, array) => len + array.length, 0);
|
|
const merged = new Uint8Array(totalLength);
|
|
let offset = 0;
|
|
arrays.forEach((array) => {
|
|
merged.set(array, offset);
|
|
offset += array.length;
|
|
});
|
|
return merged;
|
|
}
|
|
/**
|
|
* Replaces Date objects with Unix timestamps
|
|
*/
|
|
function dateTimeReplacer(key, value) {
|
|
if (this[key] instanceof Date) {
|
|
return Math.floor(this[key].getTime() / 1000).toString();
|
|
}
|
|
return value;
|
|
}
|
|
/**
|
|
* JSON stringifies an Object, replacing Date objects with Unix timestamps
|
|
*/
|
|
export function jsonStringifyRequestData(data) {
|
|
return JSON.stringify(data, dateTimeReplacer);
|
|
}
|
|
/**
|
|
* Inspects the given path to determine if the endpoint is for v1 or v2 API
|
|
*/
|
|
export function getAPIMode(path) {
|
|
if (!path) {
|
|
return 'v1';
|
|
}
|
|
return path.startsWith('/v2') ? 'v2' : 'v1';
|
|
}
|