Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 20.06.2016, 06:29
Аватар для ORMjs
Аспирант
Отправить личное сообщение для ORMjs Посмотреть профиль Найти все сообщения от ORMjs
 
Регистрация: 20.06.2016
Сообщений: 37

Представляем вам ORMjs
Ссылка на скачку https://www.npmjs.com/package/ormjs

ORMjs это использования стандартных структур языка яваскрипт, таких как классы, для взаимодействия с базой данных. Класс представляет собой аналог коллекции в базе данных, а инстанс класса документ в коллекции. Более подробно вот тут https://ru.wikipedia.org/wiki/ORM

Статические методы класса выполняются для работы с колелкцией, а методы инстансов для работы с самим документом.
Таким образом, мы работаем с базой, без селекторов или специального языка, А работаем как бы с яваскрипт обьектами и их методами. А оно само все сохраняется в базу данных.

Я намеренно скрыл реализацию базы данных, чтобы можно было подключать разные драйверы для разных баз данных. База данных должна быть лишь под капотом, и учавствовать лишь в сохранении состояния инстансов, а как она это будет делать, программиста пользователя, не должно волновать. В этом и суть этого фреймворка =)


Перевод документации:

ORMjs это javascript ООП интерфейс для базы данных.
Он использует ArangoDB, но в будущем я добавлю драйверы для других баз (таких как mongodb)

Концепция: Используя ES6 оператор await, геттеры и промисы,
мы можем ассинхронно совершать навигацию по дереву графов документов в базе данных.

Оно рекомендуется с использованием ES6, но вы так же можете писать на ES5

Я думаю что это эпично =) Это крайне крайне крайне крайне крайне элегантное API для работы с базой данных.
А что вы думаете об этом?

Она использует ArangoDB https://www.arangodb.com/2015/10/ben...godb-arangodb/
По ссылке тест производительности с другими базами данных типа Mongo.


API


static:
Model.get(_id) // получает модель по id
Model.add(obj) // создает модель на основе переданного обьекта
Model.remove(model) // удаляет модель
Model.restore(model) // восстанавливает удаленую модель
Model.save(model) // сохраняет изменения модели в базу данных
Model.update(model) // загружает состояние модели из базы данных


instance
Model.prototype.save() // псевдоним для Model.save(this)
Model.prototype.update() // псевдоним для Model.update(this)
Model.prototype.remove() // псевдоним для Model.remove(this)
Model.prototype.restore() // псевдоним для Model.remove(this)


Основы


Определим коллекцию User (именем коллекции станет имя класса)
let Model = require('ormjs')

class User extends Model {

	static schema = {
		// базовые типы
		name: String,
		male: Boolean,
		age: Number,
		birth: Date,
		tags: Set, // как массив, только с уникальными элементами
		status: ['sleep', 'eat'], // enum (значением поля может быть одно из перечисленных значений)

		// структуры
		messages: [String], // массив строк
		prop1: {prop2: [{tags: [String]}] }, // можно описывать сколь угодно сложные вложенные структуры

		// ссылки на сущности из других коллекций (ну или этой же)
		bestFriend: User, // ссылка на инстанс User
		friends: [User], // ссылка на массив инстансов User

		// опции поля
		name: String,
		name: {$type: String},
		name: {$type: String, test: /^\w+$/},
	}

}



Example 0:


let Model = require('ormjs')


class User extends Model {

	static schema = {
		name: String,
		age: Number,
	}

}


Usage:

(async function () {

	// adding user to db
	let user = await User.add({
		name: 'Ашот',
		age: 24,
  	})

	user._id // 'User/434370324723'
	user._removed // false
	user.name // 'Ашот'
	user.age // 24

	// change field
	user.name = 'Ololo'
	console.log(user.name) // 'Ololo' field is changed

	// reset changes
	await user.update() // load state from db
	user.name // 'Ашот'

	// saving changes
	user.name = 'Ololo' // change field
	await user.save() // save changes to db
	await user.update() // load state from db
	user.name // 'Ololo' because we save

}())


Example 1:

let Model = require('ormjs')


class User extends Model {

  static schema = {
    name: String,
    age: Number,
    friends: [User]
  }


  async addFriend(user) {
    let friends = await this.friends
    friends.push(user)
    await this.save()
  }


  async removeAllFriends(){
    this.friends = []
    await this.save()
  }

}


Usage:

(async function(){

  let user = await User.add({
    name: 'Ivan',
    age: 24,
    friends: []
  })

  await user.addFriend(user)
  await user.addFriend(user)
  await user.friends // [user, user]  two itself =)

  await user.removeAllFriends()
  await user.friends // []

  await user.friends === await user.friends // true

  user.name = 22
  await user.save() // ValidationError: Field `name` must be String, but have Number

})()



Example 2:

let Model = require('ormjs')


class Sector extends Model {

	static schema = {
		size: Number
	}

}


class User extends Model {

	static schema = {
		name: String,
		sector: Sector,
	}

}


Usage:

(async function () {

	let sector = await Sector.add({
		size: 236
	})

	let user = await User.add({
		name: 'Ашот',
		sector: sector
	})

	(await user.sector).size // 236


	let sector2 = await Sector.add({
		size: 1004
	})
	user.sector = sector2
	await user.save()

	(await user.sector).size // 1004 because this another sector ^__^


})()


Custom types:

System types is: String, Number, Boolean, Data, Set
Actually we can use custom types:

let Model = require('ormjs')


class Color {

	constructor(r, g, b) {
		this.r = r
		this.g = g
		this.b = b
	}


	// convert to db document
	toJSON() {
		return {
			r: this.r,
			g: this.g,
			b: this.b
		}
	}


	// restore from db document
	static fromJSON(json) {
		return new Color(json.r, json.g, json.b)
	}

}


class User extends Model {

	static schema = {
		name: String,
		color: Color
	}

}


Usage:

(async function () {

	let user = await User.add({
		name: 'Ашот',
		color: new Color(0, 255, 0)
	})

	user.color instanceof Color //true

}())


Schemas


Number
schema = {
	age: Number,
	age: {$type: Number},
	age: {$type: Number, min:0, max:100}
}



String
schema = {
	name: String,
	name: {$type: String},
	name: {$type: String, min:3, max:20, test:/^\w+$/}
}



Set
schema = {
	tags: Set,
	tags: {$type: Set},
	tags: {$type: Set, set: ['animals', 'porn', 'movie']}
}



Enum (for any type) Field value must be one of from enum array
schema = {
    status: ['pending', 'resolve', 'reject']
}



Это часть большого проекта, но я выгрузил её как отдельный модуль NPM, возможно она будет кому-то полезна.
https://github.com/uMaxmaxmaximus/ui...erver/core/orm

Напишите кто нибудь статью на хабре, кто умеет писать на хабре =)

Последний раз редактировалось ORMjs, 21.06.2016 в 14:52.
Ответить с цитированием
  #2 (permalink)  
Старый 20.06.2016, 07:26
Аватар для Erolast
Профессор
Отправить личное сообщение для Erolast Посмотреть профиль Найти все сообщения от Erolast
 
Регистрация: 24.09.2013
Сообщений: 1,436

Лол, ты же плевался с ES6) Изменил мнение?

И да, async/await - это уже ES7.
Ответить с цитированием
  #3 (permalink)  
Старый 20.06.2016, 07:38
Аватар для ORMjs
Аспирант
Отправить личное сообщение для ORMjs Посмотреть профиль Найти все сообщения от ORMjs
 
Регистрация: 20.06.2016
Сообщений: 37

Сообщение от Erolast
Лол, ты же плевался с ES6) Изменил мнение?
Блин ну че началось то?
Ну было дело, ну ошибался я, и про кофескрипт ошибался, ну я просто думал что вы все врете и хотите мне плохое посоветовать и зла желаете. И сами мучаетесь и хотите меня мучать. На самом деле я по прежнему ненавижу ES синтаксис и у меня в списке TODO 3 технических проэкта на ближайшие 2 года

1) MegaJS (это такой изоморфный фреймворк на базе UIjs (плюс позволит писать и под десктопы и мобилки как React Native))
2) CoffeeScript ES6
3) Аналог THREE с физикой (на Rust компилируемый в asm.js и wasm)

На самом деле эту ORM я написал за неделю, а там писать особо и нечего, потестируйте кто нить. Никогда в подобных ORM не хватало такой вот удобной ссылки на другую коллекцию let frields = await user.frields.

А вообще я поражаюсь как Babel написали стейт машину для ассинхронки. Это верх элеганства. Я бы не додумался, при том каллбак выполняется в том же конетксте следовательно сохраняются общие ппеременные и общий скоуп. Это феноминально.

Щас я короч пишу такой же прозрачный API для этой бд но на клиенте, чтобы можно было такой же код писать, типа дай юзера, дай его друзей и.т.п. но при том чтобы проходили разные валидации на то к каким полям человек имеет доступ а к каким нет, что может модифицировать а что нет, то есть плитику прав доступа делаю.

Чтобы больше не пистаь на клиенте api.getUsers() а писать как будто бы у нас база данных прям в браузере есть. Ну как в Meteor

============== Ребят ну активнее активнее, пожалуйста =)

Последний раз редактировалось ORMjs, 20.06.2016 в 07:58.
Ответить с цитированием
  #4 (permalink)  
Старый 20.06.2016, 17:12
Аватар для ORMjs
Аспирант
Отправить личное сообщение для ORMjs Посмотреть профиль Найти все сообщения от ORMjs
 
Регистрация: 20.06.2016
Сообщений: 37

Ну ребята, я даже доку написал, все как вы просили, ну скачайте кто нибудь, протестируйте ну. Ну 0 даунлоадов за сутки ну...
Ответить с цитированием
  #5 (permalink)  
Старый 20.06.2016, 18:53
Аватар для destus
Профессор
Отправить личное сообщение для destus Посмотреть профиль Найти все сообщения от destus
 
Регистрация: 18.05.2011
Сообщений: 1,207

Будет custom validation и populate как в mongoose? Можно писать на генераторах с подключенной библиотекой co вместо async/await?

Последний раз редактировалось destus, 20.06.2016 в 18:56.
Ответить с цитированием
  #6 (permalink)  
Старый 20.06.2016, 19:35
Аватар для cyber
I am Student
Отправить личное сообщение для cyber Посмотреть профиль Найти все сообщения от cyber
 
Регистрация: 17.12.2011
Сообщений: 4,415

ORMjs, ты серьезно на гитхаб закинул после babel?
__________________
Цитата:
Если ограничения и условия описываются как "коробка", то хитрость в том что бы найти именно коробку... Не думайте о чем то глобальном - найдите коробку.
Ответить с цитированием
  #7 (permalink)  
Старый 20.06.2016, 19:48
Аватар для ORMjs
Аспирант
Отправить личное сообщение для ORMjs Посмотреть профиль Найти все сообщения от ORMjs
 
Регистрация: 20.06.2016
Сообщений: 37

Сообщение от destus
и populate как в mongoose?
Тут как бы если ты сделаешь популейт то как он узнает какой глубины граф тебе отдать? Это бессмысленно. Я делаю щас прослойку для клиенд сайда, где можно используя такой же api общаться с базой и лазить по её графу (но с учетом кастомной логики привелегий и разрешений, и доступа к полям и все такое, проверка на юзера и все такое). Так что в популейт не будет необходимости, ровно как и в api.getUsers() и все такое прочее. Вы просто в браузере будете работать с массивоподобными обьектами которые являются срезами с базы данных, делать по ним выборки, изменять их, где у вашего юзера не доступа то будет ошибка и.т.п.

Сообщение от destus
Можно писать на генераторах с подключенной библиотекой co вместо async/await?
Я же так и написал) тут ссылки на другие коллекции возвращают промис и все, то есть можно вообще писать вот так user.friends.then(friendsArr=>) просто оператор async он как бы сахар для этого и ждет выполнения промиса, а если там не промис то просто возвращает это значение.

Сообщение от cyber
ты серьезно на гитхаб закинул после babel?
Ну а что не так? Как надо было? Я вообще-то на гитхаб весь проджект свой закинул, а orm это часть бякенда, который лежит в папке server. решил просто отдельный гитхаб не делать для orm

Последний раз редактировалось ORMjs, 20.06.2016 в 19:52.
Ответить с цитированием
  #8 (permalink)  
Старый 20.06.2016, 19:54
Аватар для ORMjs
Аспирант
Отправить личное сообщение для ORMjs Посмотреть профиль Найти все сообщения от ORMjs
 
Регистрация: 20.06.2016
Сообщений: 37

Сообщение от destus
Будет custom validation
Да кстати, мелочь но щас сделаю. Ты и так можешь делать кастомную валидацию перекрыв статический метод validate() но тогда вручную придется пробегаться по полям схемы, а она может быть крайне сложной. По этому я лучше добавлю просто опции полям типа {$type:String, $test: function(){}}

Но вообще предполагается что валидация должна делаться на уровне модели. То есть у неё есть методы типа addUser
removeMessages и они уже валидируют параметры передаваемые в них и как то сейвят состояние. Максимум что должно быть на слое ORM это как бы длинна данных (чтобы память не жрала 10000к строка например) и какие-то вещи связанные с длинной данных в базе данных и типом, а корректность данных, с точки зрения приложения, должна проверяться самими моделями и прогарммистом отдельно. То есть валидация это уже уровень ИСПОЛЬЗОВАНИЯ ORM а не внутри ORM. Но для удобства я щас добавлю функции $test

Последний раз редактировалось ORMjs, 20.06.2016 в 19:59.
Ответить с цитированием
  #9 (permalink)  
Старый 20.06.2016, 20:03
Аватар для destus
Профессор
Отправить личное сообщение для destus Посмотреть профиль Найти все сообщения от destus
 
Регистрация: 18.05.2011
Сообщений: 1,207

Цитата:
Я же так и написал) тут ссылки на другие коллекции возвращают промис и все, то есть можно вообще писать вот так user.friends.then(friendsArr=>) просто оператор async он как бы сахар для этого и ждет выполнения промиса, а если там не промис то просто возвращает это значение.
ок, просто для async надо Babel, а если делать проект с поддержкой ES6 браузерами из коробки, то можно всего-лишь подключить co размером ~4kb
Ответить с цитированием
  #10 (permalink)  
Старый 20.06.2016, 20:19
Аватар для ORMjs
Аспирант
Отправить личное сообщение для ORMjs Посмотреть профиль Найти все сообщения от ORMjs
 
Регистрация: 20.06.2016
Сообщений: 37

Ну а кто вообще пишет на es6 и es7 без Babel? К тому же await это просто сахар на промисы, так что ограничений тут нет =)

(В typescript кстати await например есть)
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Бесплатно напишу вам что-то на PHP а вы мне на JS mrbanan Работа 2 13.11.2015 20:40
Как вам открытие олимпиады ? DjDiablo Оффтопик 33 28.02.2014 22:52
Как Вам сайт Xtrance Ваши сайты и скрипты 2 26.04.2013 21:33
Как вам дизайн моего сайта? megaupload Оффтопик 156 16.02.2013 16:16
И как вам новая подсветка кода? Илья Кантор Сайт Javascript.ru 18 01.02.2010 03:01