-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
23 changed files
with
395 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
.DS_Store | ||
.env | ||
.idea | ||
database |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"imports": { | ||
"@core": "./src/mod.ts", | ||
"@core/classes": "./src/classes/mod.ts", | ||
"@core/decorators": "./src/decorators/mod.ts", | ||
"@core/utils": "./src/utils/mod.ts", | ||
"@core/errors": "./src/errors/mod.ts" | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import {Schema} from "./mod.ts" | ||
import {FileUtils, ColumnsUtils} from "./utils/mod.ts" | ||
|
||
interface InstanceOptions { | ||
isNew: boolean; | ||
} | ||
|
||
export class Instance<T extends { _id: string }> { | ||
constructor(private _schema: Schema, | ||
private _fields: T, | ||
private _options: InstanceOptions) { | ||
} | ||
|
||
set fields(value: T) { | ||
this._fields = value | ||
} | ||
|
||
get fields(): T { | ||
return this._fields | ||
} | ||
|
||
public delete() { | ||
const db = FileUtils.readJson<T>("./database/db.json") | ||
const filtered_table = db[this._schema.name] | ||
.filter(row => row._id !== this._fields._id) | ||
FileUtils.writeJson("./database/db.json", { | ||
...db, | ||
[this._schema.name]: filtered_table | ||
}) | ||
} | ||
|
||
public save() { | ||
const db = FileUtils.readJson<T>("./database/db.json") | ||
|
||
if (!this._options.isNew) { | ||
const filtered_table = db[this._schema.name] | ||
.filter(row => row._id !== this._fields._id) | ||
|
||
new ColumnsUtils(this._schema.columns, filtered_table, this._fields) | ||
filtered_table.push(this._fields) | ||
FileUtils.writeJson("./database/db.json", { | ||
...db, | ||
[this._schema.name]: filtered_table | ||
} | ||
) | ||
} else { | ||
const table = db[this._schema.name] ?? [] | ||
|
||
new ColumnsUtils(this._schema.columns, table, this._fields) | ||
table.push({...this._fields, _id: crypto.randomUUID()}) | ||
FileUtils.writeJson("./database/db.json", { | ||
...db, | ||
[this._schema.name]: table | ||
} | ||
) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import {Schema, Instance} from "./mod.ts" | ||
import {FileUtils, ObjectUtils} from "./utils/mod.ts" | ||
|
||
export class Model<T extends { _id: string }> { | ||
constructor( | ||
private schema: Schema | ||
) { | ||
} | ||
|
||
public create(args: T) { | ||
return new Instance(this.schema, args, {isNew: true}) | ||
} | ||
|
||
public findById(_id: string) { | ||
const db = FileUtils.readJson<T>("./database/db.json") | ||
const table = db[this.schema.name] ?? [] | ||
const candidate = table.find(row => row._id === _id) | ||
|
||
if (candidate === undefined) { | ||
throw new Error("No record found") | ||
} | ||
|
||
return new Instance<T>(this.schema, candidate, { | ||
isNew: false | ||
}) | ||
} | ||
|
||
public find(args: Partial<T>) { | ||
const db = FileUtils.readJson<T>("./database/db.json") | ||
const table = db[this.schema.name] ?? [] | ||
const keys = Object.keys(args) as unknown as Array<keyof T> | ||
|
||
const filtered_table = table.filter(row => | ||
keys.every(key => | ||
ObjectUtils.nestedCheck(row, key, args[key]))) | ||
|
||
return filtered_table.map(row => new Instance<T>(this.schema, row, { | ||
isNew: false | ||
})) | ||
} | ||
|
||
public findOne(args: Partial<T>) { | ||
return this.find(args)[0] | ||
} | ||
|
||
public findAll() { | ||
const db = FileUtils.readJson<T>("./database/db.json") | ||
return db[this.schema.name].map(row => new Instance<T>(this.schema, row, { | ||
isNew: false | ||
})) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import {getFormat} from "./decorators/mod.ts"; | ||
import {ColumnRules} from "./interfaces/IColumn.ts"; | ||
|
||
export class Schema { | ||
constructor( | ||
private _name: string = '', | ||
private _columns: ColumnRules[] = [] | ||
) { | ||
} | ||
|
||
get name(): string { | ||
return this._name; | ||
} | ||
|
||
get columns(): ColumnRules[] { | ||
return this._columns; | ||
} | ||
|
||
public static initializeSchema<T extends { new(...args: unknown[]): unknown }>(args: T ) { | ||
const instance = new (args as any)() | ||
|
||
const keys = Object.keys(instance).filter(key => key !== "_table_name" && key !== "_id"); | ||
const options = keys.map(key => ({ | ||
name: key, options: getFormat(instance, key) | ||
})) | ||
|
||
return new Schema(instance["_table_name"], options); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import {FileUtils} from "./utils/mod.ts"; | ||
|
||
export class Table { | ||
public static async init(name: string) { | ||
try { | ||
const isExists = await FileUtils.isFileExists("./database/db.json"); | ||
|
||
if (isExists) { | ||
return this; | ||
} | ||
|
||
await FileUtils.createOrCheckDir("./database"); | ||
await FileUtils.writeJson("./database/db.json", {[name]: []}); | ||
return this; | ||
} catch (e) { | ||
console.error(e.message); | ||
} | ||
} | ||
|
||
public static async nuke(name: string) { | ||
try { | ||
await FileUtils.writeJson("./database/db.json", {[name]: []}); | ||
return this; | ||
} catch (e) { | ||
console.error(e.message); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export class Document { | ||
_id!: string; | ||
_table_name!: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export {Document} from "./Document.ts"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import {Reflect} from "https://deno.land/x/[email protected]/mod.ts"; | ||
import {ColumnProps} from "../interfaces/IColumn.ts"; | ||
|
||
const formatMetadataKey = Symbol("columns"); | ||
|
||
export function getFormat(target: unknown, propertyKey: string) { | ||
return Reflect.getMetadata(formatMetadataKey, target, propertyKey); | ||
} | ||
|
||
export function Column(options: ColumnProps) { | ||
const optionsProxy = options.allowNull === undefined | ||
? {...options, allowNull: false} | ||
: {...options, allowNull: true}; | ||
|
||
return Reflect.metadata(formatMetadataKey, optionsProxy); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import {Table} from "../Table.ts"; | ||
|
||
export function TinyTable(name: string) { | ||
return function<T extends { new(...args: any[]): Record<string, any> }>(Constructor: T) { | ||
return class extends Constructor { | ||
_table_name: string = name; | ||
_id!: string; | ||
|
||
constructor(...args: any[]) { | ||
super(...args); | ||
Table.init(name); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export {getFormat, Column} from "./Column.ts" | ||
export {TinyTable} from "./TinyTable.ts" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
export class ErrorWithHint extends Error { | ||
constructor(message: string, hint: string) { | ||
super(` | ||
Message: ${message} | ||
Hint: ${hint} | ||
`); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export {ErrorWithHint} from "./ErrorWithHint.ts"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
export type OptionTypes = "string" | "number" | "boolean" | "date" | "json" | "array"; | ||
|
||
export interface ColumnProps { | ||
unique?: boolean; | ||
type?: OptionTypes; | ||
allowNull?: boolean; | ||
default?: any; | ||
} | ||
|
||
export interface ColumnRules { | ||
name: string; | ||
options: ColumnProps; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export type {OptionTypes, ColumnRules, ColumnProps} from './IColumn.ts' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export {Model} from "./Model.ts"; | ||
export {Schema} from "./Schema.ts"; | ||
export {Table} from "./Table.ts"; | ||
export {Instance} from "./Instance.ts"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import {ColumnRules, OptionTypes} from "../interfaces/mod.ts"; | ||
import {ErrorWithHint} from "../errors/mod.ts"; | ||
import {parse} from "https://deno.land/[email protected]/datetime/mod.ts"; | ||
|
||
export class ColumnsUtils<T> { | ||
constructor( | ||
private columnRules: ColumnRules[] = [], | ||
private table: Array<T> = [], | ||
private record: T | ||
) { | ||
this.run(); | ||
} | ||
|
||
private checkType(value: T[keyof T], columnName: string, checkType?: OptionTypes) { | ||
const valueType = typeof value; | ||
|
||
if (checkType === "date") { | ||
try { | ||
return parse(String(value), "yyyy-MM-dd"); | ||
} catch (_) { | ||
throw new Error(`${columnName} must be data`); | ||
} | ||
} | ||
|
||
if (checkType === "array") { | ||
if (!Array.isArray(value)) throw new Error(`${columnName} must be array`); | ||
return; | ||
} | ||
|
||
if (checkType === "json") { | ||
if (typeof value === "object" && !Array.isArray(value) && value !== null) return; | ||
throw new Error(`${columnName} must be json`); | ||
} | ||
|
||
if (valueType !== checkType) { | ||
throw new Error(`${columnName} must be ${checkType}`); | ||
} | ||
} | ||
|
||
private unique(column: ColumnRules) { | ||
const name = column.name as keyof T; | ||
|
||
if (this.table.some(row => row[name] === this.record[name])) { | ||
throw new ErrorWithHint( | ||
`${String(name)} must be unique`, | ||
`${this.record[name]} is already exists` | ||
); | ||
} | ||
} | ||
|
||
private type(column: ColumnRules) { | ||
const name = column.name as keyof T; | ||
const value = this.record[name]; | ||
return this.checkType(value, String(name), column.options.type); | ||
} | ||
|
||
private default(column: ColumnRules) { | ||
const name = column.name as keyof T; | ||
this.record[name] = column.options.default; | ||
} | ||
|
||
private run() { | ||
this.columnRules.map(rule => { | ||
if (rule.options.allowNull && | ||
this.record[rule.name as keyof T] === undefined && | ||
rule.options.default === undefined) return; | ||
|
||
|
||
if ( | ||
rule.options.default !== undefined && | ||
this.record[rule.name as keyof T] === undefined) this.default(rule); | ||
|
||
rule.options.type !== undefined && this.type(rule); | ||
rule.options.unique !== undefined && this.unique(rule); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { ensureDir } from "https://deno.land/[email protected]/fs/mod.ts"; | ||
|
||
export class FileUtils { | ||
static writeJson<T>(path: string, data: Record<string, unknown> | Array<T | never>): string { | ||
try { | ||
Deno.writeTextFileSync(path, JSON.stringify(data)); | ||
return "Written to " + path; | ||
} catch (e) { | ||
return e.message; | ||
} | ||
} | ||
|
||
static async isFileExists(path: string): Promise<boolean> { | ||
try { | ||
await Deno.stat(path); | ||
return true; | ||
} catch (e) { | ||
console.log(e.message) | ||
return false; | ||
} | ||
} | ||
|
||
static async createOrCheckDir(path: string): Promise<string> { | ||
try { | ||
await ensureDir(path); | ||
return "Created directory " + path; | ||
} catch (e) { | ||
return e.message; | ||
} | ||
} | ||
|
||
static readJson<T>(path: string): Record<string, Array<T>> { | ||
try { | ||
const data = Deno.readTextFileSync(path); | ||
return JSON.parse(data); | ||
} catch (_e) { | ||
return {}; | ||
} | ||
} | ||
} |
Oops, something went wrong.