10 Commits
Author SHA1 Message Date
Nikita Dezzpil Orlov bcefbb7425 chore(release): 1.3.3 2021-10-13 14:56:17 +03:00
Nikita Dezzpil Orlov e1d03577dd fix: Потерялась зависимость rfdc
fix: Исправить опечатку number_
fix: Фикс в монге, коллекцию не надо создавать до проверки уникального ключа
fix: Заменить TypeError на ErrStorage в mongo
fix: Исправить collectionName в сигнатуре remove
2021-10-13 14:56:11 +03:00
Nikita Dezzpil Orlov 231895c7cd chore(release): 1.3.2 2021-10-05 15:49:21 +03:00
Nikita Dezzpil Orlov e282a887c3 fix: трансформер доступен для дочерних классов 2021-10-05 15:49:15 +03:00
Nikita Dezzpil Orlov 14a46a71b3 chore(release): 1.3.1 2021-10-05 14:31:47 +03:00
Nikita Dezzpil Orlov ead279ca5d fix: обновил API типов 2021-10-05 14:31:38 +03:00
Nikita Dezzpil Orlov 50261ac29e chore(release): 1.3.0 2021-10-05 14:30:26 +03:00
Nikita Dezzpil Orlov 017f735613 feat: добавил управление трансформацией данных для репозитория 2021-10-05 14:30:18 +03:00
Nikita Dezzpil Orlov 8e619112cd chore(release): 1.2.0 2021-10-04 18:20:04 +03:00
Nikita Dezzpil Orlov d0942e59d9 feat: добавил Entity Manager 2021-10-04 18:19:54 +03:00
11 changed files with 163 additions and 36 deletions

No files matched your search

+35
View File
@@ -2,6 +2,41 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [1.3.3](https://git.archive.systems/Dezzpil/ivanovna.orm/compare/v1.3.2...v1.3.3) (2021-10-13)
### Bug Fixes
* Потерялась зависимость rfdc ([e1d0357](https://git.archive.systems/Dezzpil/ivanovna.orm/commit/e1d03577dd973c6e651a8d175fbabcf5a8c1fd53))
### [1.3.2](https://git.archive.systems/Dezzpil/ivanovna.orm/compare/v1.3.1...v1.3.2) (2021-10-05)
### Bug Fixes
* трансформер доступен для дочерних классов ([e282a88](https://git.archive.systems/Dezzpil/ivanovna.orm/commit/e282a887c3e8c5fc6d159da9881f13adb2f527b4))
### [1.3.1](https://git.archive.systems/Dezzpil/ivanovna.orm/compare/v1.3.0...v1.3.1) (2021-10-05)
### Bug Fixes
* обновил API типов ([ead279c](https://git.archive.systems/Dezzpil/ivanovna.orm/commit/ead279ca5dbcc391aa30b224195295a4d1f81684))
## [1.3.0](https://git.archive.systems/Dezzpil/ivanovna.orm/compare/v1.2.0...v1.3.0) (2021-10-05)
### Features
* добавил управление трансформацией данных для репозитория ([017f735](https://git.archive.systems/Dezzpil/ivanovna.orm/commit/017f7356134c306c9ba46b19385c3e96444c613b))
## [1.2.0](https://git.archive.systems/Dezzpil/ivanovna.orm/compare/v1.1.3...v1.2.0) (2021-10-04)
### Features
* добавил Entity Manager ([d0942e5](https://git.archive.systems/Dezzpil/ivanovna.orm/commit/d0942e59d97d861aa3368ee96a3a15f0418263e4))
### [1.1.3](https://git.archive.systems/Dezzpil/ivanovna.orm/compare/v1.1.2...v1.1.3) (2021-10-04) ### [1.1.3](https://git.archive.systems/Dezzpil/ivanovna.orm/compare/v1.1.2...v1.1.3) (2021-10-04)
Vendored
+23 -6
View File
@@ -1,10 +1,13 @@
/** @public */ /** @public */
export declare abstract class Data { export declare abstract class Data {
[key: string]: any; [key: string]: any;
/**
* @deprecated use fromObject()
*/
static assign(vo: Data, values: ValuesObject): Data; static assign(vo: Data, values: ValuesObject): Data;
set(key: string, value: any): void; set(key: string, value: any): void;
fromObject(object: ValuesObject): void; fromObject(object: ValuesObject): void;
toObject(exclude?: string[]): Record<string, any>; toObject(exclude?: string[]): ValuesObject;
abstract uniqKey(): string; abstract uniqKey(): string;
} }
@@ -26,6 +29,20 @@ export declare abstract class Entity<T extends Data> {
/** @public */ /** @public */
export declare type EntityConstructor<T extends Data> = new (data?: T) => Entity<T>; export declare type EntityConstructor<T extends Data> = new (data?: T) => Entity<T>;
/** @public */
export declare class EntityManager {
private readonly _storage;
private _saveMap;
private _removeMap;
constructor(storage: Storage_2);
persist(entity: Entity<any>): this;
persistMany(entities: Entity<any>[]): this;
remove(entity: Entity<any>): this;
forget(): this;
flush(): Promise<this>;
refresh(entity: Entity<any>): Promise<Entity<any>>;
}
/** @public */ /** @public */
export declare class ErrEntityHasNoUniqKeyValue extends Error { export declare class ErrEntityHasNoUniqKeyValue extends Error {
} }
@@ -52,6 +69,7 @@ export declare abstract class Repo<T extends Entity<any>> {
protected _entity: T; protected _entity: T;
protected _limit: number; protected _limit: number;
protected _offset: number; protected _offset: number;
protected _transformer: (obj: any) => any;
/** /**
* Возвращает объект соотв. сущности, например new App() * Возвращает объект соотв. сущности, например new App()
*/ */
@@ -60,9 +78,8 @@ export declare abstract class Repo<T extends Entity<any>> {
* Возвращает название коллекции/таблицы/... хранящей записи соотв. сущностей * Возвращает название коллекции/таблицы/... хранящей записи соотв. сущностей
*/ */
abstract Name(): string; abstract Name(): string;
_transformer: (object: any) => any; constructor(storage: Storage_2, transformer?: (obj: any) => any);
constructor(storage: Storage_2); setTransformer(transformer?: (obj: any) => any): this;
resetTransformer(): void;
get storage(): Storage_2; get storage(): Storage_2;
save(entity: T): Promise<this>; save(entity: T): Promise<this>;
findById(id: string): Promise<T | null>; findById(id: string): Promise<T | null>;
@@ -85,13 +102,13 @@ declare abstract class Storage_2 {
abstract save(name: string, uniqKey: string, data: Record<string, any>): Promise<string>; abstract save(name: string, uniqKey: string, data: Record<string, any>): Promise<string>;
abstract createSession(): StorageSession; abstract createSession(): StorageSession;
abstract count(name: string, query?: Record<string, any>): Promise<number>; abstract count(name: string, query?: Record<string, any>): Promise<number>;
abstract remove(collectionName: string, uniqKeyName: string, uniqKey: string): Promise<boolean>; abstract remove(name: string, uniqKey: string, uniqVal: string | number): Promise<boolean>;
} }
export { Storage_2 as Storage } export { Storage_2 as Storage }
/** @public */ /** @public */
export declare interface StorageCursor { export declare interface StorageCursor {
limit(number_: number): StorageCursor; limit(number: number): StorageCursor;
sort(parameters: Record<string, any>): StorageCursor; sort(parameters: Record<string, any>): StorageCursor;
skip(offset: number): StorageCursor; skip(offset: number): StorageCursor;
toArray(): Promise<any[]>; toArray(): Promise<any[]>;
+7 -7
View File
@@ -1,13 +1,16 @@
{ {
"name": "ivna-orm", "name": "ivna-orm",
"version": "1.1.3", "version": "1.3.3",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ivna-orm", "name": "ivna-orm",
"version": "1.1.3", "version": "1.3.3",
"license": "ISC", "license": "ISC",
"dependencies": {
"rfdc": "^1.3.0"
},
"devDependencies": { "devDependencies": {
"@jest/test-sequencer": "^27.2.3", "@jest/test-sequencer": "^27.2.3",
"@microsoft/api-extractor": "^7.18.11", "@microsoft/api-extractor": "^7.18.11",
@@ -21,7 +24,6 @@
"jest-teamcity": "^1.10.0", "jest-teamcity": "^1.10.0",
"nanoid": "^3.1.28", "nanoid": "^3.1.28",
"prettier": "^2.4.1", "prettier": "^2.4.1",
"rfdc": "^1.3.0",
"standard-version": "^9.3.1", "standard-version": "^9.3.1",
"ts-jest": "^27.0.5", "ts-jest": "^27.0.5",
"ts-node": "^10.2.1", "ts-node": "^10.2.1",
@@ -5658,8 +5660,7 @@
"node_modules/rfdc": { "node_modules/rfdc": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
"integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA=="
"dev": true
}, },
"node_modules/rimraf": { "node_modules/rimraf": {
"version": "3.0.2", "version": "3.0.2",
@@ -11393,8 +11394,7 @@
"rfdc": { "rfdc": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
"integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA=="
"dev": true
}, },
"rimraf": { "rimraf": {
"version": "3.0.2", "version": "3.0.2",
+4 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "ivna-orm", "name": "ivna-orm",
"version": "1.1.3", "version": "1.3.3",
"description": "Mini ORM for convenience", "description": "Mini ORM for convenience",
"main": "dist/index.js", "main": "dist/index.js",
"files": [ "files": [
@@ -43,7 +43,6 @@
"jest-teamcity": "^1.10.0", "jest-teamcity": "^1.10.0",
"nanoid": "^3.1.28", "nanoid": "^3.1.28",
"prettier": "^2.4.1", "prettier": "^2.4.1",
"rfdc": "^1.3.0",
"standard-version": "^9.3.1", "standard-version": "^9.3.1",
"ts-jest": "^27.0.5", "ts-jest": "^27.0.5",
"ts-node": "^10.2.1", "ts-node": "^10.2.1",
@@ -60,5 +59,8 @@
"semi": false, "semi": false,
"singleQuote": true, "singleQuote": true,
"tabWidth": 4 "tabWidth": 4
},
"dependencies": {
"rfdc": "^1.3.0"
} }
} }
+4 -1
View File
@@ -7,6 +7,9 @@ export type ValuesObject = Record<string, any>
export abstract class Data { export abstract class Data {
[key: string]: any [key: string]: any
/**
* @deprecated use fromObject()
*/
static assign(vo: Data, values: ValuesObject): Data { static assign(vo: Data, values: ValuesObject): Data {
for (const key of Object.getOwnPropertyNames(values)) { for (const key of Object.getOwnPropertyNames(values)) {
vo[key] = values[key] vo[key] = values[key]
@@ -26,7 +29,7 @@ export abstract class Data {
} }
} }
toObject(exclude: string[] = []): Record<string, any> { toObject(exclude: string[] = []): ValuesObject {
const object = {} as ValuesObject const object = {} as ValuesObject
for (const key of Object.getOwnPropertyNames(this)) { for (const key of Object.getOwnPropertyNames(this)) {
if (key.startsWith('__')) { if (key.startsWith('__')) {
+64
View File
@@ -0,0 +1,64 @@
import { Entity } from '../entity'
import { Storage } from '../storage'
/** @public */
export class EntityManager {
private readonly _storage: Storage
private _saveMap: Map<string, Entity<any>>
private _removeMap: Map<string, Entity<any>>
constructor(storage: Storage) {
this._storage = storage
this._saveMap = new Map()
this._removeMap = new Map()
}
persist(entity: Entity<any>): this {
const key = [entity.constructor.name, entity.getUniqKey()].join('&')
this._saveMap.set(key, entity)
return this
}
persistMany(entities: Entity<any>[]): this {
for (let entity of entities) {
this.persist(entity)
}
return this
}
remove(entity: Entity<any>): this {
const key = [entity.constructor.name, entity.getUniqKey()].join('&')
this._removeMap.set(key, entity)
return this
}
forget(): this {
this._saveMap = new Map()
return this
}
async flush() {
if (!this._saveMap.size && !this._removeMap.size) return this
const session = this._storage.createSession()
await session.start()
await session.commit(async () => {
for (let en of this._saveMap.values()) {
await en._getRepo(this._storage).save(en)
}
this._saveMap = new Map()
for (let en of this._removeMap.values()) {
await en._getRepo(this._storage).remove(en)
}
this._removeMap = new Map()
})
return this
}
async refresh(entity: Entity<any>) {
const repo = entity._getRepo(this._storage)
return repo.findById(entity.getUniqKey())
}
}
+15 -10
View File
@@ -15,6 +15,8 @@ export abstract class Repo<T extends Entity<any>> {
protected _limit = 0 protected _limit = 0
protected _offset = 0 protected _offset = 0
protected _transformer: (obj: any) => any
/** /**
* Возвращает объект соотв. сущности, например new App() * Возвращает объект соотв. сущности, например new App()
*/ */
@@ -25,21 +27,24 @@ export abstract class Repo<T extends Entity<any>> {
*/ */
abstract Name(): string abstract Name(): string
_transformer: (object: any) => any constructor(storage: Storage, transformer?: (obj: any) => any) {
constructor(storage: Storage) {
this._storage = storage this._storage = storage
this._entity = this.Entity() this._entity = this.Entity()
this.resetTransformer() this.setTransformer(transformer)
} }
resetTransformer() { setTransformer(transformer?: (obj: any) => any): this {
this._transformer = function (object: any): any { if (transformer) {
const entity = this.Entity() this._transformer = transformer
entity.data.fromObject(object) } else {
entity._id = object._id this._transformer = function (object: any): any {
return entity const entity = this.Entity()
entity.data.fromObject(object)
entity._id = object._id
return entity
}
} }
return this
} }
get storage(): Storage { get storage(): Storage {
+2 -2
View File
@@ -1,6 +1,6 @@
/** @public */ /** @public */
export interface StorageCursor { export interface StorageCursor {
limit(number_: number): StorageCursor limit(number: number): StorageCursor
sort(parameters: Record<string, any>): StorageCursor sort(parameters: Record<string, any>): StorageCursor
skip(offset: number): StorageCursor skip(offset: number): StorageCursor
toArray(): Promise<any[]> toArray(): Promise<any[]>
@@ -28,7 +28,7 @@ export abstract class Storage {
abstract count(name: string, query?: Record<string, any>): Promise<number> abstract count(name: string, query?: Record<string, any>): Promise<number>
abstract remove(collectionName: string, uniqKeyName: string, uniqKey: string): Promise<boolean> abstract remove(name: string, uniqKey: string, uniqVal: string | number): Promise<boolean>
} }
/** @public */ /** @public */
+5 -5
View File
@@ -1,5 +1,5 @@
import { ClientSession, MongoClient, TransactionOptions } from 'mongodb' import { ClientSession, MongoClient, TransactionOptions } from 'mongodb'
import { Storage, StorageCursor, StorageSession } from '../storage' import { ErrStorage, Storage, StorageCursor, StorageSession } from '../storage'
import { ErrEntityHasNoUniqKeyValue } from '../entity' import { ErrEntityHasNoUniqKeyValue } from '../entity'
/** @public */ /** @public */
@@ -36,8 +36,8 @@ export class MongoStorage extends Storage {
async save(collectionName: string, uniqKey: string, data: Record<string, any>): Promise<string> { async save(collectionName: string, uniqKey: string, data: Record<string, any>): Promise<string> {
await this._connect() await this._connect()
const id = data[uniqKey] const id = data[uniqKey]
const coll = await this._client.db().collection(collectionName)
if (id !== null && id !== undefined) { if (id !== null && id !== undefined) {
const coll = await this._client.db().collection(collectionName)
const filter = { [uniqKey]: id } const filter = { [uniqKey]: id }
const result = await coll.findOneAndReplace(filter, data, { upsert: true }) const result = await coll.findOneAndReplace(filter, data, { upsert: true })
if (result.lastErrorObject) { if (result.lastErrorObject) {
@@ -48,7 +48,7 @@ export class MongoStorage extends Storage {
return result.lastErrorObject.upserted return result.lastErrorObject.upserted
} }
throw new TypeError(`can not save data to ${collectionName} with result ${result}`) throw new ErrStorage(`can not save data to ${collectionName} with result ${result}`)
} else { } else {
// Нельзя сохранить сущность без значения уникального ключа // Нельзя сохранить сущность без значения уникального ключа
// const result = await coll.insertOne(data) // const result = await coll.insertOne(data)
@@ -70,8 +70,8 @@ export class MongoStorage extends Storage {
return this._client return this._client
} }
async remove(collectionName: string, uniqKeyName: string, uniqKey: string): Promise<boolean> { async remove(name: string, uniqKeyName: string, uniqKey: string): Promise<boolean> {
const coll = await this._client.db().collection(collectionName) const coll = await this._client.db().collection(name)
const result = await coll.deleteOne({ [uniqKeyName]: uniqKey }) const result = await coll.deleteOne({ [uniqKeyName]: uniqKey })
return Promise.resolve(result.acknowledged) return Promise.resolve(result.acknowledged)
} }
+1
View File
@@ -6,3 +6,4 @@ export { Data, ValuesObject } from './app/data'
export { Entity, EntityConstructor, ErrEntityHasNoUniqKeyValue } from './app/entity' export { Entity, EntityConstructor, ErrEntityHasNoUniqKeyValue } from './app/entity'
export { Repo, ErrFoundNotUniqEntity, ErrEntityNotFound } from './app/repo' export { Repo, ErrFoundNotUniqEntity, ErrEntityNotFound } from './app/repo'
export { Storage, StorageCursor, ErrStorage, ErrNoSession, StorageSession } from './app/storage' export { Storage, StorageCursor, ErrStorage, ErrNoSession, StorageSession } from './app/storage'
export { EntityManager } from './app/entity/manager'
+3 -3
View File
@@ -9,8 +9,8 @@ export class MapCursor implements StorageCursor {
this._map = map this._map = map
} }
limit(number_: number): StorageCursor { limit(number: number): StorageCursor {
this._limit = number_ this._limit = number
return this return this
} }
@@ -67,7 +67,7 @@ export class MapStorage extends Storage {
return Promise.resolve(0) return Promise.resolve(0)
} }
async remove(collectionName: string, uniqKeyName: string, uniqKey: string): Promise<boolean> { async remove(name: string, uniqKeyName: string, uniqKey: string): Promise<boolean> {
return Promise.resolve(true) return Promise.resolve(true)
} }