mongo works
This commit is contained in:
parent
ae6ccd559f
commit
125107da50
937 changed files with 205033 additions and 2 deletions
422
parts/3/followAlong/node_modules/sift/src/operations.ts
generated
vendored
Normal file
422
parts/3/followAlong/node_modules/sift/src/operations.ts
generated
vendored
Normal file
|
|
@ -0,0 +1,422 @@
|
|||
import {
|
||||
BaseOperation,
|
||||
EqualsOperation,
|
||||
Options,
|
||||
createTester,
|
||||
Tester,
|
||||
createQueryOperation,
|
||||
QueryOperation,
|
||||
Operation,
|
||||
Query,
|
||||
NamedGroupOperation,
|
||||
numericalOperation,
|
||||
containsOperation,
|
||||
} from "./core";
|
||||
import { Key, comparable, isFunction, isArray } from "./utils";
|
||||
|
||||
class $Ne extends BaseOperation<any> {
|
||||
readonly propop = true;
|
||||
private _test: Tester;
|
||||
init() {
|
||||
this._test = createTester(this.params, this.options.compare);
|
||||
}
|
||||
reset() {
|
||||
super.reset();
|
||||
this.keep = true;
|
||||
}
|
||||
next(item: any) {
|
||||
if (this._test(item)) {
|
||||
this.done = true;
|
||||
this.keep = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// https://docs.mongodb.com/manual/reference/operator/query/elemMatch/
|
||||
class $ElemMatch extends BaseOperation<Query<any>> {
|
||||
readonly propop = true;
|
||||
private _queryOperation: QueryOperation<any>;
|
||||
init() {
|
||||
if (!this.params || typeof this.params !== "object") {
|
||||
throw new Error(`Malformed query. $elemMatch must by an object.`);
|
||||
}
|
||||
this._queryOperation = createQueryOperation(
|
||||
this.params,
|
||||
this.owneryQuery,
|
||||
this.options,
|
||||
);
|
||||
}
|
||||
reset() {
|
||||
super.reset();
|
||||
this._queryOperation.reset();
|
||||
}
|
||||
next(item: any) {
|
||||
if (isArray(item)) {
|
||||
for (let i = 0, { length } = item; i < length; i++) {
|
||||
// reset query operation since item being tested needs to pass _all_ query
|
||||
// operations for it to be a success
|
||||
this._queryOperation.reset();
|
||||
|
||||
const child = item[i];
|
||||
this._queryOperation.next(child, i, item, false);
|
||||
this.keep = this.keep || this._queryOperation.keep;
|
||||
}
|
||||
this.done = true;
|
||||
} else {
|
||||
this.done = false;
|
||||
this.keep = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class $Not extends BaseOperation<Query<any>> {
|
||||
readonly propop = true;
|
||||
private _queryOperation: QueryOperation<any>;
|
||||
init() {
|
||||
this._queryOperation = createQueryOperation(
|
||||
this.params,
|
||||
this.owneryQuery,
|
||||
this.options,
|
||||
);
|
||||
}
|
||||
reset() {
|
||||
super.reset();
|
||||
this._queryOperation.reset();
|
||||
}
|
||||
next(item: any, key: Key, owner: any, root: boolean) {
|
||||
this._queryOperation.next(item, key, owner, root);
|
||||
this.done = this._queryOperation.done;
|
||||
this.keep = !this._queryOperation.keep;
|
||||
}
|
||||
}
|
||||
|
||||
export class $Size extends BaseOperation<any> {
|
||||
readonly propop = true;
|
||||
init() {}
|
||||
next(item) {
|
||||
if (isArray(item) && item.length === this.params) {
|
||||
this.done = true;
|
||||
this.keep = true;
|
||||
}
|
||||
// if (parent && parent.length === this.params) {
|
||||
// this.done = true;
|
||||
// this.keep = true;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
const assertGroupNotEmpty = (values: any[]) => {
|
||||
if (values.length === 0) {
|
||||
throw new Error(`$and/$or/$nor must be a nonempty array`);
|
||||
}
|
||||
};
|
||||
|
||||
class $Or extends BaseOperation<any> {
|
||||
readonly propop = false;
|
||||
private _ops: Operation<any>[];
|
||||
init() {
|
||||
assertGroupNotEmpty(this.params);
|
||||
this._ops = this.params.map((op) =>
|
||||
createQueryOperation(op, null, this.options),
|
||||
);
|
||||
}
|
||||
reset() {
|
||||
this.done = false;
|
||||
this.keep = false;
|
||||
for (let i = 0, { length } = this._ops; i < length; i++) {
|
||||
this._ops[i].reset();
|
||||
}
|
||||
}
|
||||
next(item: any, key: Key, owner: any) {
|
||||
let done = false;
|
||||
let success = false;
|
||||
for (let i = 0, { length } = this._ops; i < length; i++) {
|
||||
const op = this._ops[i];
|
||||
op.next(item, key, owner);
|
||||
if (op.keep) {
|
||||
done = true;
|
||||
success = op.keep;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.keep = success;
|
||||
this.done = done;
|
||||
}
|
||||
}
|
||||
|
||||
class $Nor extends $Or {
|
||||
readonly propop = false;
|
||||
next(item: any, key: Key, owner: any) {
|
||||
super.next(item, key, owner);
|
||||
this.keep = !this.keep;
|
||||
}
|
||||
}
|
||||
|
||||
class $In extends BaseOperation<any> {
|
||||
readonly propop = true;
|
||||
private _testers: Tester[];
|
||||
init() {
|
||||
const params = Array.isArray(this.params) ? this.params : [this.params];
|
||||
this._testers = params.map((value) => {
|
||||
if (containsOperation(value, this.options)) {
|
||||
throw new Error(`cannot nest $ under ${this.name.toLowerCase()}`);
|
||||
}
|
||||
return createTester(value, this.options.compare);
|
||||
});
|
||||
}
|
||||
next(item: any, key: Key, owner: any) {
|
||||
let done = false;
|
||||
let success = false;
|
||||
for (let i = 0, { length } = this._testers; i < length; i++) {
|
||||
const test = this._testers[i];
|
||||
if (test(item)) {
|
||||
done = true;
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.keep = success;
|
||||
this.done = done;
|
||||
}
|
||||
}
|
||||
|
||||
class $Nin extends BaseOperation<any> {
|
||||
readonly propop = true;
|
||||
private _in: $In;
|
||||
constructor(params: any, ownerQuery: any, options: Options, name: string) {
|
||||
super(params, ownerQuery, options, name);
|
||||
this._in = new $In(params, ownerQuery, options, name);
|
||||
}
|
||||
next(item: any, key: Key, owner: any, root: boolean) {
|
||||
this._in.next(item, key, owner);
|
||||
|
||||
if (isArray(owner) && !root) {
|
||||
if (this._in.keep) {
|
||||
this.keep = false;
|
||||
this.done = true;
|
||||
} else if (key == owner.length - 1) {
|
||||
this.keep = true;
|
||||
this.done = true;
|
||||
}
|
||||
} else {
|
||||
this.keep = !this._in.keep;
|
||||
this.done = true;
|
||||
}
|
||||
}
|
||||
reset() {
|
||||
super.reset();
|
||||
this._in.reset();
|
||||
}
|
||||
}
|
||||
|
||||
class $Exists extends BaseOperation<boolean> {
|
||||
readonly propop = true;
|
||||
next(item: any, key: Key, owner: any, root: boolean, leaf?: boolean) {
|
||||
if (!leaf) {
|
||||
this.done = true;
|
||||
this.keep = !this.params;
|
||||
} else if (owner.hasOwnProperty(key) === this.params) {
|
||||
this.done = true;
|
||||
this.keep = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class $And extends NamedGroupOperation {
|
||||
readonly propop = false;
|
||||
constructor(
|
||||
params: Query<any>[],
|
||||
owneryQuery: Query<any>,
|
||||
options: Options,
|
||||
name: string,
|
||||
) {
|
||||
super(
|
||||
params,
|
||||
owneryQuery,
|
||||
options,
|
||||
params.map((query) => createQueryOperation(query, owneryQuery, options)),
|
||||
name,
|
||||
);
|
||||
|
||||
assertGroupNotEmpty(params);
|
||||
}
|
||||
next(item: any, key: Key, owner: any, root: boolean) {
|
||||
this.childrenNext(item, key, owner, root);
|
||||
}
|
||||
}
|
||||
|
||||
class $All extends NamedGroupOperation {
|
||||
readonly propop = true;
|
||||
constructor(
|
||||
params: Query<any>[],
|
||||
owneryQuery: Query<any>,
|
||||
options: Options,
|
||||
name: string,
|
||||
) {
|
||||
super(
|
||||
params,
|
||||
owneryQuery,
|
||||
options,
|
||||
params.map((query) => createQueryOperation(query, owneryQuery, options)),
|
||||
name,
|
||||
);
|
||||
}
|
||||
next(item: any, key: Key, owner: any, root: boolean) {
|
||||
this.childrenNext(item, key, owner, root);
|
||||
}
|
||||
}
|
||||
|
||||
export const $eq = (params: any, owneryQuery: Query<any>, options: Options) =>
|
||||
new EqualsOperation(params, owneryQuery, options);
|
||||
export const $ne = (
|
||||
params: any,
|
||||
owneryQuery: Query<any>,
|
||||
options: Options,
|
||||
name: string,
|
||||
) => new $Ne(params, owneryQuery, options, name);
|
||||
export const $or = (
|
||||
params: Query<any>[],
|
||||
owneryQuery: Query<any>,
|
||||
options: Options,
|
||||
name: string,
|
||||
) => new $Or(params, owneryQuery, options, name);
|
||||
export const $nor = (
|
||||
params: Query<any>[],
|
||||
owneryQuery: Query<any>,
|
||||
options: Options,
|
||||
name: string,
|
||||
) => new $Nor(params, owneryQuery, options, name);
|
||||
export const $elemMatch = (
|
||||
params: any,
|
||||
owneryQuery: Query<any>,
|
||||
options: Options,
|
||||
name: string,
|
||||
) => new $ElemMatch(params, owneryQuery, options, name);
|
||||
export const $nin = (
|
||||
params: any,
|
||||
owneryQuery: Query<any>,
|
||||
options: Options,
|
||||
name: string,
|
||||
) => new $Nin(params, owneryQuery, options, name);
|
||||
export const $in = (
|
||||
params: any,
|
||||
owneryQuery: Query<any>,
|
||||
options: Options,
|
||||
name: string,
|
||||
) => {
|
||||
return new $In(params, owneryQuery, options, name);
|
||||
};
|
||||
|
||||
export const $lt = numericalOperation((params) => (b) => {
|
||||
return b != null && b < params;
|
||||
});
|
||||
export const $lte = numericalOperation((params) => (b) => {
|
||||
return b === params || b <= params;
|
||||
});
|
||||
export const $gt = numericalOperation((params) => (b) => {
|
||||
return b != null && b > params;
|
||||
});
|
||||
export const $gte = numericalOperation((params) => (b) => {
|
||||
return b === params || b >= params;
|
||||
});
|
||||
export const $mod = (
|
||||
[mod, equalsValue]: number[],
|
||||
owneryQuery: Query<any>,
|
||||
options: Options,
|
||||
) =>
|
||||
new EqualsOperation(
|
||||
(b) => comparable(b) % mod === equalsValue,
|
||||
owneryQuery,
|
||||
options,
|
||||
);
|
||||
export const $exists = (
|
||||
params: boolean,
|
||||
owneryQuery: Query<any>,
|
||||
options: Options,
|
||||
name: string,
|
||||
) => new $Exists(params, owneryQuery, options, name);
|
||||
export const $regex = (
|
||||
pattern: string,
|
||||
owneryQuery: Query<any>,
|
||||
options: Options,
|
||||
) =>
|
||||
new EqualsOperation(
|
||||
new RegExp(pattern, owneryQuery.$options),
|
||||
owneryQuery,
|
||||
options,
|
||||
);
|
||||
export const $not = (
|
||||
params: any,
|
||||
owneryQuery: Query<any>,
|
||||
options: Options,
|
||||
name: string,
|
||||
) => new $Not(params, owneryQuery, options, name);
|
||||
|
||||
const typeAliases = {
|
||||
number: (v) => typeof v === "number",
|
||||
string: (v) => typeof v === "string",
|
||||
bool: (v) => typeof v === "boolean",
|
||||
array: (v) => Array.isArray(v),
|
||||
null: (v) => v === null,
|
||||
timestamp: (v) => v instanceof Date,
|
||||
};
|
||||
|
||||
export const $type = (
|
||||
clazz: Function | string,
|
||||
owneryQuery: Query<any>,
|
||||
options: Options,
|
||||
) =>
|
||||
new EqualsOperation(
|
||||
(b) => {
|
||||
if (typeof clazz === "string") {
|
||||
if (!typeAliases[clazz]) {
|
||||
throw new Error(`Type alias does not exist`);
|
||||
}
|
||||
|
||||
return typeAliases[clazz](b);
|
||||
}
|
||||
|
||||
return b != null ? b instanceof clazz || b.constructor === clazz : false;
|
||||
},
|
||||
owneryQuery,
|
||||
options,
|
||||
);
|
||||
export const $and = (
|
||||
params: Query<any>[],
|
||||
ownerQuery: Query<any>,
|
||||
options: Options,
|
||||
name: string,
|
||||
) => new $And(params, ownerQuery, options, name);
|
||||
|
||||
export const $all = (
|
||||
params: Query<any>[],
|
||||
ownerQuery: Query<any>,
|
||||
options: Options,
|
||||
name: string,
|
||||
) => new $All(params, ownerQuery, options, name);
|
||||
export const $size = (
|
||||
params: number,
|
||||
ownerQuery: Query<any>,
|
||||
options: Options,
|
||||
) => new $Size(params, ownerQuery, options, "$size");
|
||||
export const $options = () => null;
|
||||
export const $where = (
|
||||
params: string | Function,
|
||||
ownerQuery: Query<any>,
|
||||
options: Options,
|
||||
) => {
|
||||
let test;
|
||||
|
||||
if (isFunction(params)) {
|
||||
test = params;
|
||||
} else if (!process.env.CSP_ENABLED) {
|
||||
test = new Function("obj", "return " + params);
|
||||
} else {
|
||||
throw new Error(
|
||||
`In CSP mode, sift does not support strings in "$where" condition`,
|
||||
);
|
||||
}
|
||||
|
||||
return new EqualsOperation((b) => test.bind(b)(b), ownerQuery, options);
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue