@cloud-cli/store
Version:
Data store abstraction
129 lines (128 loc) • 3.35 kB
JavaScript
const meta = Symbol();
const resourceName = Symbol();
function getMetadataOf(target, property) {
const ctor = target.constructor && target.constructor !== Function ? target.constructor : target;
let map = ctor[meta];
if (!map) {
map = ctor[meta] = new Map();
}
if (!property) {
return map;
}
if (!map.get(property)) {
const q = { type: String, name: property };
map.set(property, q);
return q;
}
return map.get(property);
}
export function Model(name) {
return function (target) {
const meta = getMetadataOf(target);
meta.set(resourceName, name);
};
}
export function NotNull() {
return function (target, property) {
const meta = getMetadataOf(target, property);
meta.notNull = true;
};
}
export function Unique() {
return function (target, property) {
const meta = getMetadataOf(target, property);
meta.unique = true;
};
}
export function Primary() {
return function (target, property) {
const meta = getMetadataOf(target, property);
meta.primary = true;
};
}
export function Property(type, defaultValue) {
return function (target, name) {
Object.assign(getMetadataOf(target, name), {
name,
type,
defaultValue,
});
};
}
const operators = {
is: '=',
isNot: '!=',
isLike: 'like',
gt: '>',
lt: '<',
gte: '>=',
lte: '<=',
};
export class Query {
constructor() {
this.q = [];
}
push(field, operator, value) {
this.q.push([field, operator, value]);
return this;
}
where(field) {
const q = this;
const p = new Proxy({}, {
get(_t, operator) {
return (value) => q.push(field, operators[operator], value);
},
});
return p;
}
toJSON() {
return this.q;
}
}
export class Resource {
static use(driver) {
Resource.driver = driver;
}
static describe(resourceOrModel) {
const resource = typeof resourceOrModel !== 'function' ? Object.getPrototypeOf(resourceOrModel).constructor : resourceOrModel;
const meta = getMetadataOf(resource);
const name = meta.get(resourceName);
if (!name) {
throw new Error('Name is missing. Did you add @Model() to your class?');
}
const fields = Array.from(meta.entries())
.filter((f) => f[0] !== resourceName)
.map((f) => f[1]);
if (!fields.find((f) => f.primary)) {
fields.unshift({
name: 'id',
type: Number,
primary: true,
});
}
return { name, fields };
}
static async find(resource, query) {
return Resource.driver.findAll(resource, query);
}
static async create(resource) {
return Resource.driver.create(resource);
}
constructor(props) {
if (props) {
Object.assign(this, props);
}
}
async save() {
return Resource.driver.save(this);
}
async remove() {
return Resource.driver.remove(this);
}
async find() {
return Resource.driver.find(this);
}
}
Resource.getMetadataOf = getMetadataOf;
export class ResourceDriver {
}