Server IP : 162.213.251.212 / Your IP : 13.59.123.182 [ Web Server : LiteSpeed System : Linux business55.web-hosting.com 4.18.0-553.lve.el8.x86_64 #1 SMP Mon May 27 15:27:34 UTC 2024 x86_64 User : allssztx ( 535) PHP Version : 8.1.31 Disable Function : NONE Domains : 1 Domains MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : OFF | Pkexec : OFF Directory : /proc/self/root/home/allssztx/clarkesmusicservices.com/node_modules/sift/src/ |
Upload File : |
import { isArray, Key, Comparator, isVanillaObject, comparable, equals, coercePotentiallyNull, isProperty, } from "./utils"; export interface Operation<TItem> { readonly keep: boolean; readonly done: boolean; propop: boolean; reset(); next(item: TItem, key?: Key, owner?: any, root?: boolean, leaf?: boolean); } export type Tester = ( item: any, key?: Key, owner?: any, root?: boolean, leaf?: boolean, ) => boolean; export interface NamedOperation { name: string; } export type OperationCreator<TItem> = ( params: any, parentQuery: any, options: Options, name: string, ) => Operation<TItem>; export type BasicValueQuery<TValue> = { $eq?: TValue; $ne?: TValue; $lt?: TValue; $gt?: TValue; $lte?: TValue; $gte?: TValue; $in?: TValue[]; $nin?: TValue[]; $all?: TValue[]; $mod?: [number, number]; $exists?: boolean; $regex?: string | RegExp; $size?: number; $where?: ((this: TValue, obj: TValue) => boolean) | string; $options?: "i" | "g" | "m" | "u"; $type?: Function; $not?: NestedQuery<TValue>; $or?: NestedQuery<TValue>[]; $nor?: NestedQuery<TValue>[]; $and?: NestedQuery<TValue>[]; }; export type ArrayValueQuery<TValue> = { $elemMatch?: Query<TValue>; } & BasicValueQuery<TValue>; type Unpacked<T> = T extends (infer U)[] ? U : T; export type ValueQuery<TValue> = TValue extends Array<any> ? ArrayValueQuery<Unpacked<TValue>> : BasicValueQuery<TValue>; type NotObject = string | number | Date | boolean | Array<any>; export type ShapeQuery<TItemSchema> = TItemSchema extends NotObject ? {} : { [k in keyof TItemSchema]?: TItemSchema[k] | ValueQuery<TItemSchema[k]> }; export type NestedQuery<TItemSchema> = ValueQuery<TItemSchema> & ShapeQuery<TItemSchema>; export type Query<TItemSchema> = | TItemSchema | RegExp | NestedQuery<TItemSchema>; export type QueryOperators<TValue = any> = keyof ValueQuery<TValue>; /** * Walks through each value given the context - used for nested operations. E.g: * { "person.address": { $eq: "blarg" }} */ const walkKeyPathValues = ( item: any, keyPath: Key[], next: Tester, depth: number, key: Key, owner: any, ) => { const currentKey = keyPath[depth]; // if array, then try matching. Might fall through for cases like: // { $eq: [1, 2, 3] }, [ 1, 2, 3 ]. if ( isArray(item) && isNaN(Number(currentKey)) && !isProperty(item, currentKey) ) { for (let i = 0, { length } = item; i < length; i++) { // if FALSE is returned, then terminate walker. For operations, this simply // means that the search critera was met. if (!walkKeyPathValues(item[i], keyPath, next, depth, i, item)) { return false; } } } if (depth === keyPath.length || item == null) { return next(item, key, owner, depth === 0, depth === keyPath.length); } return walkKeyPathValues( item[currentKey], keyPath, next, depth + 1, currentKey, item, ); }; export abstract class BaseOperation<TParams, TItem = any> implements Operation<TItem> { keep: boolean; done: boolean; abstract propop: boolean; constructor( readonly params: TParams, readonly owneryQuery: any, readonly options: Options, readonly name?: string, ) { this.init(); } protected init() {} reset() { this.done = false; this.keep = false; } abstract next( item: any, key: Key, parent: any, root: boolean, leaf?: boolean, ); } abstract class GroupOperation extends BaseOperation<any> { keep: boolean; done: boolean; constructor( params: any, owneryQuery: any, options: Options, public readonly children: Operation<any>[], ) { super(params, owneryQuery, options); } /** */ reset() { this.keep = false; this.done = false; for (let i = 0, { length } = this.children; i < length; i++) { this.children[i].reset(); } } abstract next(item: any, key: Key, owner: any, root: boolean); /** */ protected childrenNext( item: any, key: Key, owner: any, root: boolean, leaf?: boolean, ) { let done = true; let keep = true; for (let i = 0, { length } = this.children; i < length; i++) { const childOperation = this.children[i]; if (!childOperation.done) { childOperation.next(item, key, owner, root, leaf); } if (!childOperation.keep) { keep = false; } if (childOperation.done) { if (!childOperation.keep) { break; } } else { done = false; } } this.done = done; this.keep = keep; } } export abstract class NamedGroupOperation extends GroupOperation implements NamedOperation { abstract propop: boolean; constructor( params: any, owneryQuery: any, options: Options, children: Operation<any>[], readonly name: string, ) { super(params, owneryQuery, options, children); } } export class QueryOperation<TItem> extends GroupOperation { readonly propop = true; /** */ next(item: TItem, key: Key, parent: any, root: boolean) { this.childrenNext(item, key, parent, root); } } export class NestedOperation extends GroupOperation { readonly propop = true; constructor( readonly keyPath: Key[], params: any, owneryQuery: any, options: Options, children: Operation<any>[], ) { super(params, owneryQuery, options, children); } /** */ next(item: any, key: Key, parent: any) { walkKeyPathValues( item, this.keyPath, this._nextNestedValue, 0, key, parent, ); } /** */ private _nextNestedValue = ( value: any, key: Key, owner: any, root: boolean, leaf: boolean, ) => { this.childrenNext(value, key, owner, root, leaf); return !this.done; }; } export const createTester = (a, compare: Comparator) => { if (a instanceof Function) { return a; } if (a instanceof RegExp) { return (b) => { const result = typeof b === "string" && a.test(b); a.lastIndex = 0; return result; }; } const comparableA = comparable(a); return (b) => compare(comparableA, comparable(b)); }; export class EqualsOperation<TParam> extends BaseOperation<TParam> { readonly propop = true; private _test: Tester; init() { this._test = createTester(this.params, this.options.compare); } next(item, key: Key, parent: any) { if (!Array.isArray(parent) || parent.hasOwnProperty(key)) { if (this._test(item, key, parent)) { this.done = true; this.keep = true; } } } } export const createEqualsOperation = ( params: any, owneryQuery: any, options: Options, ) => new EqualsOperation(params, owneryQuery, options); export const numericalOperationCreator = (createNumericalOperation: OperationCreator<any>) => (params: any, owneryQuery: any, options: Options, name: string) => { return createNumericalOperation(params, owneryQuery, options, name); }; export const numericalOperation = (createTester: (value: any) => Tester) => numericalOperationCreator( (params: any, owneryQuery: Query<any>, options: Options, name: string) => { const typeofParams = typeof comparable(params); const test = createTester(params); return new EqualsOperation( (b) => { const actualValue = coercePotentiallyNull(b); return ( typeof comparable(actualValue) === typeofParams && test(actualValue) ); }, owneryQuery, options, name, ); }, ); export type Options = { operations: { [identifier: string]: OperationCreator<any>; }; compare: (a, b) => boolean; }; const createNamedOperation = ( name: string, params: any, parentQuery: any, options: Options, ) => { const operationCreator = options.operations[name]; if (!operationCreator) { throwUnsupportedOperation(name); } return operationCreator(params, parentQuery, options, name); }; const throwUnsupportedOperation = (name: string) => { throw new Error(`Unsupported operation: ${name}`); }; export const containsOperation = (query: any, options: Options) => { for (const key in query) { if (options.operations.hasOwnProperty(key) || key.charAt(0) === "$") return true; } return false; }; const createNestedOperation = ( keyPath: Key[], nestedQuery: any, parentKey: string, owneryQuery: any, options: Options, ) => { if (containsOperation(nestedQuery, options)) { const [selfOperations, nestedOperations] = createQueryOperations( nestedQuery, parentKey, options, ); if (nestedOperations.length) { throw new Error( `Property queries must contain only operations, or exact objects.`, ); } return new NestedOperation( keyPath, nestedQuery, owneryQuery, options, selfOperations, ); } return new NestedOperation(keyPath, nestedQuery, owneryQuery, options, [ new EqualsOperation(nestedQuery, owneryQuery, options), ]); }; export const createQueryOperation = <TItem, TSchema = TItem>( query: Query<TSchema>, owneryQuery: any = null, { compare, operations }: Partial<Options> = {}, ): QueryOperation<TItem> => { const options = { compare: compare || equals, operations: Object.assign({}, operations || {}), }; const [selfOperations, nestedOperations] = createQueryOperations( query, null, options, ); const ops = []; if (selfOperations.length) { ops.push( new NestedOperation([], query, owneryQuery, options, selfOperations), ); } ops.push(...nestedOperations); if (ops.length === 1) { return ops[0]; } return new QueryOperation(query, owneryQuery, options, ops); }; const createQueryOperations = ( query: any, parentKey: string, options: Options, ) => { const selfOperations = []; const nestedOperations = []; if (!isVanillaObject(query)) { selfOperations.push(new EqualsOperation(query, query, options)); return [selfOperations, nestedOperations]; } for (const key in query) { if (options.operations.hasOwnProperty(key)) { const op = createNamedOperation(key, query[key], query, options); if (op) { if (!op.propop && parentKey && !options.operations[parentKey]) { throw new Error( `Malformed query. ${key} cannot be matched against property.`, ); } } // probably just a flag for another operation (like $options) if (op != null) { selfOperations.push(op); } } else if (key.charAt(0) === "$") { throwUnsupportedOperation(key); } else { nestedOperations.push( createNestedOperation(key.split("."), query[key], key, query, options), ); } } return [selfOperations, nestedOperations]; }; export const createOperationTester = <TItem>(operation: Operation<TItem>) => (item: TItem, key?: Key, owner?: any) => { operation.reset(); operation.next(item, key, owner); return operation.keep; }; export const createQueryTester = <TItem, TSchema = TItem>( query: Query<TSchema>, options: Partial<Options> = {}, ) => { return createOperationTester( createQueryOperation<TItem, TSchema>(query, null, options), ); };