Compare commits
19
Commits
8c8866d338
..
v1.3.3
No files matched your search
@@ -1,5 +0,0 @@
|
|||||||
# Changelog
|
|
||||||
|
|
||||||
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.0.1 (2021-09-29)
|
|
||||||
+68
@@ -0,0 +1,68 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* путь к файлу типов ([d923969](https://git.archive.systems/Dezzpil/ivanovna.orm/commit/d92396967a79b51fe63d6620eb8b2169260f4ec7))
|
||||||
|
|
||||||
|
### [1.1.2](https://git.archive.systems/Dezzpil/ivanovna.orm/compare/v1.1.1...v1.1.2) (2021-09-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* заменил все unknow на any ([20a969c](https://git.archive.systems/Dezzpil/ivanovna.orm/commit/20a969c829d5d4d9ec5b4f001f6d13be3570a97d))
|
||||||
|
|
||||||
|
### [1.1.1](https://git.archive.systems/Dezzpil/ivanovna.orm/compare/v1.1.0...v1.1.1) (2021-09-29)
|
||||||
|
|
||||||
|
## [1.1.0](https://git.archive.systems/Dezzpil/ivanovna.orm/compare/v1.0.2...v1.1.0) (2021-09-29)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Добавил разметку для экстрактора апи и команду для сборника типов ([7f25b66](https://git.archive.systems/Dezzpil/ivanovna.orm/commit/7f25b665f4f27665595065f006c41669b0f77dd3))
|
||||||
|
|
||||||
|
### [1.0.2](https://git.archive.systems/Dezzpil/ivanovna.orm/compare/v1.0.1...v1.0.2) (2021-09-29)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Добавил главный файл с экспортами, поправил пэкадж и названия файла хранилища монги ([f998ee6](https://git.archive.systems/Dezzpil/ivanovna.orm/commit/f998ee630bdb5277f06743b0fb332dab9c6ec638))
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# Ivanovna ORM
|
||||||
|
|
||||||
|
Простая ОРМ для простейших задач.
|
||||||
|
|
||||||
|
Позволяет задать модели для таблиц или коллекций и предоставляет менеджер сущностей для манипуляций с ними.
|
||||||
|
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
|
||||||
|
"mainEntryPointFilePath": "<projectFolder>/dist/index.d.ts",
|
||||||
|
"apiReport": {
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
"docModel": {
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
"dtsRollup": {
|
||||||
|
"enabled": true,
|
||||||
|
"untrimmedFilePath": "",
|
||||||
|
"publicTrimmedFilePath": "<projectFolder>/orm.d.ts"
|
||||||
|
},
|
||||||
|
"tsdocMetadata": {
|
||||||
|
"enabled": false
|
||||||
|
},
|
||||||
|
"newlineKind": "lf",
|
||||||
|
"messages": {
|
||||||
|
"compilerMessageReporting": {
|
||||||
|
"default": {
|
||||||
|
"logLevel": "error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extractorMessageReporting": {
|
||||||
|
"default": {
|
||||||
|
"logLevel": "error"
|
||||||
|
},
|
||||||
|
"ae-internal-missing-underscore": {
|
||||||
|
"logLevel": "none",
|
||||||
|
"addToApiReportFile": false
|
||||||
|
},
|
||||||
|
"ae-forgotten-export": {
|
||||||
|
"logLevel": "error",
|
||||||
|
"addToApiReportFile": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tsdocMessageReporting": {
|
||||||
|
"default": {
|
||||||
|
"logLevel": "none"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
/** @public */
|
||||||
|
export declare abstract class Data {
|
||||||
|
[key: string]: any;
|
||||||
|
/**
|
||||||
|
* @deprecated use fromObject()
|
||||||
|
*/
|
||||||
|
static assign(vo: Data, values: ValuesObject): Data;
|
||||||
|
set(key: string, value: any): void;
|
||||||
|
fromObject(object: ValuesObject): void;
|
||||||
|
toObject(exclude?: string[]): ValuesObject;
|
||||||
|
abstract uniqKey(): string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare abstract class Entity<T extends Data> {
|
||||||
|
abstract _getRepo(storage: Storage_2): Repo<Entity<T>>;
|
||||||
|
abstract _getVO(): T;
|
||||||
|
protected _data: T;
|
||||||
|
private __id;
|
||||||
|
get data(): T;
|
||||||
|
get _id(): string;
|
||||||
|
set _id(value: string);
|
||||||
|
constructor(data?: T);
|
||||||
|
getUniqKey(): any;
|
||||||
|
isPersisted(): boolean;
|
||||||
|
toString(): any;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
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 */
|
||||||
|
export declare class ErrEntityHasNoUniqKeyValue extends Error {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class ErrEntityNotFound extends Error {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class ErrFoundNotUniqEntity extends Error {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class ErrNoSession extends ErrStorage {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare class ErrStorage extends Error {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare abstract class Repo<T extends Entity<any>> {
|
||||||
|
protected _storage: Storage_2;
|
||||||
|
protected _entity: T;
|
||||||
|
protected _limit: number;
|
||||||
|
protected _offset: number;
|
||||||
|
protected _transformer: (obj: any) => any;
|
||||||
|
/**
|
||||||
|
* Возвращает объект соотв. сущности, например new App()
|
||||||
|
*/
|
||||||
|
abstract Entity(): T;
|
||||||
|
/**
|
||||||
|
* Возвращает название коллекции/таблицы/... хранящей записи соотв. сущностей
|
||||||
|
*/
|
||||||
|
abstract Name(): string;
|
||||||
|
constructor(storage: Storage_2, transformer?: (obj: any) => any);
|
||||||
|
setTransformer(transformer?: (obj: any) => any): this;
|
||||||
|
get storage(): Storage_2;
|
||||||
|
save(entity: T): Promise<this>;
|
||||||
|
findById(id: string): Promise<T | null>;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
_findByParams(parameters: Record<string, any>, limit?: number, order?: Record<string, any>): Promise<T[]>;
|
||||||
|
findMany(parameters: Record<string, any>, order?: Record<string, any>): Promise<T[]>;
|
||||||
|
shift(limit?: number, offset?: number): this;
|
||||||
|
count(query?: Record<string, any>): Promise<number>;
|
||||||
|
remove(entity: T, silent?: boolean): Promise<this>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
declare abstract class Storage_2 {
|
||||||
|
protected _dsn: string;
|
||||||
|
constructor(dsn: string);
|
||||||
|
abstract find(name: string, query: Record<string, any>): Promise<StorageCursor>;
|
||||||
|
abstract save(name: string, uniqKey: string, data: Record<string, any>): Promise<string>;
|
||||||
|
abstract createSession(): StorageSession;
|
||||||
|
abstract count(name: string, query?: Record<string, any>): Promise<number>;
|
||||||
|
abstract remove(name: string, uniqKey: string, uniqVal: string | number): Promise<boolean>;
|
||||||
|
}
|
||||||
|
export { Storage_2 as Storage }
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare interface StorageCursor {
|
||||||
|
limit(number: number): StorageCursor;
|
||||||
|
sort(parameters: Record<string, any>): StorageCursor;
|
||||||
|
skip(offset: number): StorageCursor;
|
||||||
|
toArray(): Promise<any[]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare abstract class StorageSession {
|
||||||
|
abstract start(options?: Record<string, any>): Promise<void>;
|
||||||
|
abstract commit(fn: () => any, options?: Record<string, any>): Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export declare type ValuesObject = Record<string, any>;
|
||||||
|
|
||||||
|
export { }
|
||||||
Generated
+807
-57
File diff suppressed because it is too large.
Load diff
+17
-7
@@ -1,16 +1,23 @@
|
|||||||
{
|
{
|
||||||
"name": "ivna-orm",
|
"name": "ivna-orm",
|
||||||
"version": "1.0.1",
|
"version": "1.3.3",
|
||||||
"description": "Mini ORM for convenience",
|
"description": "Mini ORM for convenience",
|
||||||
"main": "src/index.ts",
|
"main": "dist/index.js",
|
||||||
"files": [
|
"files": [
|
||||||
"dist/app/**/*"
|
"dist/index.js",
|
||||||
|
"dist/index.d.ts",
|
||||||
|
"dist/app/**/*",
|
||||||
|
"src/index.ts",
|
||||||
|
"src/app/**/*",
|
||||||
|
"orm.d.ts"
|
||||||
],
|
],
|
||||||
|
"types": "orm.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "node --no-warnings node_modules/.bin/jest --runInBand --forceExit",
|
"test": "node --no-warnings node_modules/.bin/jest --runInBand --forceExit",
|
||||||
"prepare": "npm test && npm run build",
|
|
||||||
"build": "rimraf dist && tsc -b -v",
|
"build": "rimraf dist && tsc -b -v",
|
||||||
"release": "standard-version -i HISTORY.md"
|
"build:api": "npm run build && api-extractor run && rimraf 'dist/**/*.d.ts*'",
|
||||||
|
"release": "standard-version -i HISTORY.md",
|
||||||
|
"prepare": "npm test && npm run build:api"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -25,6 +32,7 @@
|
|||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@jest/test-sequencer": "^27.2.3",
|
"@jest/test-sequencer": "^27.2.3",
|
||||||
|
"@microsoft/api-extractor": "^7.18.11",
|
||||||
"@types/chai": "^4.2.22",
|
"@types/chai": "^4.2.22",
|
||||||
"@types/jest": "^27.0.2",
|
"@types/jest": "^27.0.2",
|
||||||
"@types/node": "^14.17.19",
|
"@types/node": "^14.17.19",
|
||||||
@@ -35,13 +43,12 @@
|
|||||||
"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",
|
||||||
"typescript": "^4.4.3"
|
"typescript": "^4.4.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"peerDependencies": {
|
||||||
"mongodb": "^4.1.2",
|
"mongodb": "^4.1.2",
|
||||||
"mongodb-client-encryption": "^1.2.7"
|
"mongodb-client-encryption": "^1.2.7"
|
||||||
},
|
},
|
||||||
@@ -52,5 +59,8 @@
|
|||||||
"semi": false,
|
"semi": false,
|
||||||
"singleQuote": true,
|
"singleQuote": true,
|
||||||
"tabWidth": 4
|
"tabWidth": 4
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"rfdc": "^1.3.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
-2
@@ -1,10 +1,15 @@
|
|||||||
import rfdc from 'rfdc'
|
import rfdc from 'rfdc'
|
||||||
|
|
||||||
type ValuesObject = Record<string, any>
|
/** @public */
|
||||||
|
export type ValuesObject = Record<string, any>
|
||||||
|
|
||||||
|
/** @public */
|
||||||
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]
|
||||||
@@ -24,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('__')) {
|
||||||
|
|||||||
@@ -2,10 +2,13 @@ import { Data } from './data'
|
|||||||
import { Repo } from './repo'
|
import { Repo } from './repo'
|
||||||
import { Storage } from './storage'
|
import { Storage } from './storage'
|
||||||
|
|
||||||
|
/** @public */
|
||||||
export type EntityConstructor<T extends Data> = new (data?: T) => Entity<T>
|
export type EntityConstructor<T extends Data> = new (data?: T) => Entity<T>
|
||||||
|
|
||||||
|
/** @public */
|
||||||
export class ErrEntityHasNoUniqKeyValue extends Error {}
|
export class ErrEntityHasNoUniqKeyValue extends Error {}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
export abstract class Entity<T extends Data> {
|
export abstract class Entity<T extends Data> {
|
||||||
abstract _getRepo(storage: Storage): Repo<Entity<T>>
|
abstract _getRepo(storage: Storage): Repo<Entity<T>>
|
||||||
abstract _getVO(): T
|
abstract _getVO(): T
|
||||||
|
|||||||
@@ -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())
|
||||||
|
}
|
||||||
|
}
|
||||||
+23
-14
@@ -1,9 +1,13 @@
|
|||||||
import { Entity } from './entity'
|
import { Entity } from './entity'
|
||||||
import { Storage } from './storage'
|
import { Storage } from './storage'
|
||||||
|
|
||||||
|
/** @public */
|
||||||
export class ErrFoundNotUniqEntity extends Error {}
|
export class ErrFoundNotUniqEntity extends Error {}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
export class ErrEntityNotFound extends Error {}
|
export class ErrEntityNotFound extends Error {}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
export abstract class Repo<T extends Entity<any>> {
|
export abstract class Repo<T extends Entity<any>> {
|
||||||
protected _storage: Storage
|
protected _storage: Storage
|
||||||
protected _entity: T
|
protected _entity: T
|
||||||
@@ -11,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()
|
||||||
*/
|
*/
|
||||||
@@ -21,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 {
|
||||||
@@ -70,9 +79,9 @@ export abstract class Repo<T extends Entity<any>> {
|
|||||||
* @protected
|
* @protected
|
||||||
*/
|
*/
|
||||||
async _findByParams(
|
async _findByParams(
|
||||||
parameters: Record<string, unknown>,
|
parameters: Record<string, any>,
|
||||||
limit?: number,
|
limit?: number,
|
||||||
order?: Record<string, unknown>
|
order?: Record<string, any>
|
||||||
): Promise<T[]> {
|
): Promise<T[]> {
|
||||||
const cursor = await this._storage.find(this.Name(), parameters)
|
const cursor = await this._storage.find(this.Name(), parameters)
|
||||||
if (limit && limit > 0) await cursor.limit(limit)
|
if (limit && limit > 0) await cursor.limit(limit)
|
||||||
@@ -86,7 +95,7 @@ export abstract class Repo<T extends Entity<any>> {
|
|||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
async findMany(parameters: Record<string, unknown>, order?: Record<string, unknown>): Promise<T[]> {
|
async findMany(parameters: Record<string, any>, order?: Record<string, any>): Promise<T[]> {
|
||||||
const cursor = await this._storage.find(this.Name(), parameters)
|
const cursor = await this._storage.find(this.Name(), parameters)
|
||||||
if (this._offset > 0) await cursor.skip(this._offset)
|
if (this._offset > 0) await cursor.skip(this._offset)
|
||||||
if (this._limit > 0) await cursor.limit(this._limit)
|
if (this._limit > 0) await cursor.limit(this._limit)
|
||||||
@@ -106,7 +115,7 @@ export abstract class Repo<T extends Entity<any>> {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
async count(query?: Record<string, unknown>): Promise<number> {
|
async count(query?: Record<string, any>): Promise<number> {
|
||||||
return this._storage.count(this.Name(), query)
|
return this._storage.count(this.Name(), query)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+13
-7
@@ -1,13 +1,18 @@
|
|||||||
|
/** @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[]>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
export class ErrStorage extends Error {}
|
export class ErrStorage extends Error {}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
export class ErrNoSession extends ErrStorage {}
|
export class ErrNoSession extends ErrStorage {}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
export abstract class Storage {
|
export abstract class Storage {
|
||||||
protected _dsn: string
|
protected _dsn: string
|
||||||
|
|
||||||
@@ -15,18 +20,19 @@ export abstract class Storage {
|
|||||||
this._dsn = dsn
|
this._dsn = dsn
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract find(name: string, query: Record<string, unknown>): Promise<StorageCursor>
|
abstract find(name: string, query: Record<string, any>): Promise<StorageCursor>
|
||||||
|
|
||||||
abstract save(name: string, uniqKey: string, data: Record<string, unknown>): 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, unknown>): 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 */
|
||||||
export abstract class StorageSession {
|
export abstract class StorageSession {
|
||||||
abstract start(options?: Record<string, unknown>): Promise<void>
|
abstract start(options?: Record<string, any>): Promise<void>
|
||||||
abstract commit(fn: () => any, options?: Record<string, unknown>): Promise<void>
|
abstract commit(fn: () => any, options?: Record<string, any>): Promise<void>
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
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 */
|
||||||
export class MongoStorage extends Storage {
|
export class MongoStorage extends Storage {
|
||||||
private readonly _client: MongoClient
|
private readonly _client: MongoClient
|
||||||
_session: ClientSession
|
_session: ClientSession
|
||||||
@@ -20,23 +21,23 @@ export class MongoStorage extends Storage {
|
|||||||
await this._client.connect()
|
await this._client.connect()
|
||||||
}
|
}
|
||||||
|
|
||||||
async find(collectionName: string, query: Record<string, unknown>): Promise<StorageCursor> {
|
async find(collectionName: string, query: Record<string, any>): Promise<StorageCursor> {
|
||||||
await this._connect()
|
await this._connect()
|
||||||
const coll = await this._client.db().collection(collectionName)
|
const coll = await this._client.db().collection(collectionName)
|
||||||
return coll.find(query)
|
return coll.find(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
async count(collectionName: string, query: Record<string, unknown>): Promise<number> {
|
async count(collectionName: string, query: Record<string, any>): Promise<number> {
|
||||||
await this._connect()
|
await this._connect()
|
||||||
const coll = await this._client.db().collection(collectionName)
|
const coll = await this._client.db().collection(collectionName)
|
||||||
return coll.countDocuments(query)
|
return coll.countDocuments(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
async save(collectionName: string, uniqKey: string, data: Record<string, unknown>): 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) {
|
||||||
@@ -47,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)
|
||||||
@@ -69,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)
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { EntityConstructor, ErrEntityHasNoUniqKeyValue } from './app/entity'
|
||||||
|
import { ErrEntityNotFound, ErrFoundNotUniqEntity } from './app/repo'
|
||||||
|
import { ErrNoSession, ErrStorage, StorageCursor, StorageSession } from './app/storage'
|
||||||
|
|
||||||
|
export { Data, ValuesObject } from './app/data'
|
||||||
|
export { Entity, EntityConstructor, ErrEntityHasNoUniqKeyValue } from './app/entity'
|
||||||
|
export { Repo, ErrFoundNotUniqEntity, ErrEntityNotFound } from './app/repo'
|
||||||
|
export { Storage, StorageCursor, ErrStorage, ErrNoSession, StorageSession } from './app/storage'
|
||||||
|
export { EntityManager } from './app/entity/manager'
|
||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -4,10 +4,9 @@
|
|||||||
"target": "ES2020",
|
"target": "ES2020",
|
||||||
"sourceMap": false,
|
"sourceMap": false,
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"declarationMap": false,
|
"declarationMap": true,
|
||||||
"allowJs": false,
|
"allowJs": false,
|
||||||
"checkJs": false,
|
"checkJs": false,
|
||||||
"removeComments": true,
|
|
||||||
"preserveConstEnums": true,
|
"preserveConstEnums": true,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
|||||||
Reference in new issue
Block a user