@vendure/core
Version:
A modern, headless ecommerce framework
151 lines • 5.07 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.not = not;
exports.foundIn = foundIn;
exports.assertFound = assertFound;
exports.idsAreEqual = idsAreEqual;
exports.getAssetType = getAssetType;
exports.normalizeEmailAddress = normalizeEmailAddress;
exports.isEmailAddressLike = isEmailAddressLike;
exports.awaitPromiseOrObservable = awaitPromiseOrObservable;
exports.asyncObservable = asyncObservable;
exports.convertRelationPaths = convertRelationPaths;
const generated_types_1 = require("@vendure/common/lib/generated-types");
const rxjs_1 = require("rxjs");
/**
* Takes a predicate function and returns a negated version.
*/
function not(predicate) {
return (...args) => !predicate(...args);
}
/**
* Returns a predicate function which returns true if the item is found in the set,
* as determined by a === equality check on the given compareBy property.
*/
function foundIn(set, compareBy) {
return (item) => set.some(t => t[compareBy] === item[compareBy]);
}
/**
* Identity function which asserts to the type system that a promise which can resolve to T or undefined
* does in fact resolve to T.
* Used when performing a "find" operation on an entity which we are sure exists, as in the case that we
* just successfully created or updated it.
*/
function assertFound(promise) {
return promise;
}
/**
* Compare ID values for equality, taking into account the fact that they may not be of matching types
* (string or number).
*/
function idsAreEqual(id1, id2) {
if (id1 == null || id2 == null) {
return false;
}
return id1.toString() === id2.toString();
}
/**
* Returns the AssetType based on the mime type.
*/
function getAssetType(mimeType) {
const type = mimeType.split('/')[0];
switch (type) {
case 'image':
return generated_types_1.AssetType.IMAGE;
case 'video':
return generated_types_1.AssetType.VIDEO;
default:
return generated_types_1.AssetType.BINARY;
}
}
/**
* A simple normalization for email addresses. Lowercases the whole address,
* even though technically the local part (before the '@') is case-sensitive
* per the spec. In practice, however, it seems safe to treat emails as
* case-insensitive to allow for users who might vary the usage of
* upper/lower case. See more discussion here: https://ux.stackexchange.com/a/16849
*/
function normalizeEmailAddress(input) {
return isEmailAddressLike(input) ? input.trim().toLowerCase() : input.trim();
}
/**
* This is a "good enough" check for whether the input is an email address.
* From https://stackoverflow.com/a/32686261
* It is used to determine whether to apply normalization (lower-casing)
* when comparing identifiers in user lookups. This allows case-sensitive
* identifiers for other authentication methods.
*/
function isEmailAddressLike(input) {
if (input.length > 1000) {
// This limit is in place to prevent abuse via a polynomial-time regex attack
// See https://github.com/vendure-ecommerce/vendure/security/code-scanning/43
throw new Error('Input too long');
}
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(input.trim());
}
/**
* Converts a value that may be wrapped into a Promise or Observable into a Promise-wrapped
* value.
*/
async function awaitPromiseOrObservable(value) {
let result = await value;
if (result instanceof rxjs_1.Observable) {
result = await (0, rxjs_1.lastValueFrom)(result);
}
return result;
}
/**
* @description
* Returns an observable which executes the given async work function and completes with
* the returned value. This is useful in methods which need to return
* an Observable but also want to work with async (Promise-returning) code.
*
* @example
* ```ts
* \@Controller()
* export class MyWorkerController {
*
* \@MessagePattern('test')
* handleTest() {
* return asyncObservable(async observer => {
* const value = await this.connection.fetchSomething();
* return value;
* });
* }
* }
* ```
*/
function asyncObservable(work) {
return new rxjs_1.Observable(subscriber => {
void (async () => {
try {
const result = await work(subscriber);
if (result) {
subscriber.next(result);
}
subscriber.complete();
}
catch (e) {
subscriber.error(e);
}
})();
});
}
function convertRelationPaths(relationPaths) {
const result = {};
if (relationPaths == null) {
return undefined;
}
for (const path of relationPaths) {
const parts = path.split('.');
let current = result;
for (const [i, part] of Object.entries(parts)) {
if (!current[part]) {
current[part] = +i === parts.length - 1 ? true : {};
}
current = current[part];
}
}
return result;
}
//# sourceMappingURL=utils.js.map