Skip to content

Instantly share code, notes, and snippets.

@stalniy
Created July 8, 2020 09:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stalniy/7f04c9bd24bb6bd176e9dd7f555240e5 to your computer and use it in GitHub Desktop.
Save stalniy/7f04c9bd24bb6bd176e9dd7f555240e5 to your computer and use it in GitHub Desktop.
UCAST sequelize
import { createInterpreter, InterpretationContext, Condition, FieldCondition, Comparable, CompoundCondition } from '@ucast/core'
import { MongoQueryParser, allParsingInstructions } from '@ucast/mongo';
import sequelize from 'sequelize';
const seq = new sequelize.Sequelize('sqlite::memory:');
class User extends sequelize.Model {}
User.init({
firstName: {
type: sequelize.DataTypes.STRING,
allowNull: false
},
lastName: {
type: sequelize.DataTypes.STRING
},
age: {
type: sequelize.DataTypes.INTEGER
}
}, {
sequelize: seq,
modelName: 'User'
});
type SeqOperator<C extends Condition> = <T extends typeof sequelize.Model>(condition: C, query: Query<T>, context: InterpretationContext<SeqOperator<C>>) => Query<T>;
class Query<T extends typeof sequelize.Model> {
private _query: any;
private _Model: T;
constructor(Model: T) {
this._query = { where: Object.create(null), include: [] };
this._Model = Model;
}
set(field: string, value: any) {
// TODO: check if field is of JSON data type or a field of relation
const { where } = this._query;
if (typeof where[field] === 'undefined') {
where[field] = value;
return this;
}
if (where[field][sequelize.Op.and]) {
where[sequelize.Op.and].push(value);
} else {
where[field] = {
[sequelize.Op.and]: [where[field], value]
};
}
return this;
}
toJSON() {
return this._query;
}
}
const $eq: SeqOperator<FieldCondition> = (condition, query) => {
return query.set(condition.field, condition.value);
};
const $lt: SeqOperator<FieldCondition<Comparable>> = (condition, query) => {
return query.set(condition.field, { [sequelize.Op.lt]: condition.value });
};
const $lte: SeqOperator<FieldCondition<Comparable>> = (condition, query) => {
return query.set(condition.field, { [sequelize.Op.lte]: condition.value });
};
const $gt: SeqOperator<FieldCondition<Comparable>> = (condition, query) => {
return query.set(condition.field, { [sequelize.Op.gt]: condition.value });
};
const $gte: SeqOperator<FieldCondition<Comparable>> = (condition, query) => {
return query.set(condition.field, { [sequelize.Op.gte]: condition.value });
};
const $and: SeqOperator<CompoundCondition> = (node, query, { interpret }) => {
node.value.forEach(condition => interpret(condition, query));
return query;
}
const interpret = createInterpreter({
$eq,
$lt,
$lte,
$gt,
$gte,
$and,
});
const parser = new MongoQueryParser(allParsingInstructions);
(async () => {
await seq.sync({ force: true });
const ast = parser.parse({
firstName: 'test',
age: { $lt: 10, $gt: 15 },
lastName: { $gt: 'A' }
});
const query = interpret(ast, new Query(User));
console.dir(query.toJSON(), { depth: null })
await User.findAll({ ...query.toJSON(), logging: console.log });
})()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment