@sqb/connect 4.2.1 → 4.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -0
- package/{dist/client/Adapter.js → cjs/client/adapter.js} +0 -0
- package/{dist/client/CursorStream.js → cjs/client/cursor-stream.js} +5 -2
- package/{dist/client/Cursor.js → cjs/client/cursor.js} +18 -11
- package/{dist → cjs}/client/extensions.js +0 -0
- package/{dist/client/FieldInfoMap.js → cjs/client/field-info-map.js} +2 -0
- package/{dist → cjs}/client/helpers.js +2 -2
- package/{dist/client/SqbClient.js → cjs/client/sqb-client.js} +16 -10
- package/{dist/client/SqbConnection.js → cjs/client/sqb-connection.js} +17 -14
- package/{dist → cjs}/client/types.js +0 -0
- package/cjs/index.js +42 -0
- package/{dist → cjs}/orm/backward.js +8 -8
- package/{dist → cjs}/orm/base-entity.js +8 -7
- package/{dist → cjs}/orm/commands/command.helper.js +9 -9
- package/{dist → cjs}/orm/commands/count.command.js +2 -2
- package/{dist → cjs}/orm/commands/create.command.js +12 -12
- package/{dist → cjs}/orm/commands/destroy.command.js +2 -2
- package/{dist → cjs}/orm/commands/find.command.js +100 -88
- package/{dist → cjs}/orm/commands/row-converter.js +10 -7
- package/{dist → cjs}/orm/commands/update.command.js +10 -10
- package/{dist → cjs}/orm/decorators/column.decorator.js +3 -3
- package/{dist → cjs}/orm/decorators/embedded.decorator.js +3 -3
- package/cjs/orm/decorators/entity.decorator.js +179 -0
- package/{dist → cjs}/orm/decorators/events.decorator.js +13 -13
- package/{dist → cjs}/orm/decorators/foreignkey.decorator.js +3 -3
- package/{dist → cjs}/orm/decorators/index.decorator.js +5 -5
- package/cjs/orm/decorators/link.decorator.js +70 -0
- package/{dist → cjs}/orm/decorators/primarykey.decorator.js +7 -7
- package/{dist → cjs}/orm/decorators/transform.decorator.js +5 -5
- package/cjs/orm/model/association-field-metadata.js +24 -0
- package/{dist → cjs}/orm/model/association-node.js +5 -2
- package/{dist → cjs}/orm/model/association.js +31 -39
- package/{dist/orm/model/column-element-metadata.js → cjs/orm/model/column-field-metadata.js} +8 -8
- package/{dist/orm/model/embedded-element-metadata.js → cjs/orm/model/embedded-field-metadata.js} +8 -8
- package/{dist → cjs}/orm/model/entity-metadata.js +90 -91
- package/{dist/orm/model/element-metadata.js → cjs/orm/model/field-metadata.js} +0 -0
- package/{dist → cjs}/orm/model/index-metadata.js +0 -0
- package/{dist → cjs}/orm/model/link-chain.js +12 -15
- package/{dist → cjs}/orm/orm.const.js +0 -0
- package/{dist → cjs}/orm/orm.type.js +0 -0
- package/{dist → cjs}/orm/repository.class.js +25 -22
- package/{dist → cjs}/orm/util/apply-mixins.js +0 -0
- package/{dist → cjs}/orm/util/extract-keyvalues.js +5 -5
- package/{dist → cjs}/orm/util/orm.helper.js +10 -10
- package/{dist/orm/util/serialize-element.js → cjs/orm/util/serialize-field.js} +2 -2
- package/cjs/package.json +3 -0
- package/{dist → cjs}/types.js +0 -0
- package/{dist/client/Adapter.d.ts → esm/client/adapter.d.ts} +1 -1
- package/esm/client/adapter.js +1 -0
- package/{dist/client/CursorStream.d.ts → esm/client/cursor-stream.d.ts} +1 -1
- package/esm/client/cursor-stream.js +96 -0
- package/{dist/client/Cursor.d.ts → esm/client/cursor.d.ts} +5 -5
- package/esm/client/cursor.js +252 -0
- package/{dist → esm}/client/extensions.d.ts +1 -1
- package/esm/client/extensions.js +9 -0
- package/{dist/client/FieldInfoMap.d.ts → esm/client/field-info-map.d.ts} +1 -1
- package/esm/client/field-info-map.js +50 -0
- package/{dist → esm}/client/helpers.d.ts +3 -3
- package/esm/client/helpers.js +125 -0
- package/{dist/client/SqbClient.d.ts → esm/client/sqb-client.d.ts} +4 -10
- package/esm/client/sqb-client.js +166 -0
- package/{dist/client/SqbConnection.d.ts → esm/client/sqb-connection.d.ts} +4 -4
- package/esm/client/sqb-connection.js +270 -0
- package/{dist → esm}/client/types.d.ts +5 -13
- package/esm/client/types.js +1 -0
- package/esm/index.d.ts +33 -0
- package/esm/index.js +32 -0
- package/{dist → esm}/orm/backward.d.ts +1 -1
- package/esm/orm/backward.js +17 -0
- package/{dist → esm}/orm/base-entity.d.ts +1 -1
- package/esm/orm/base-entity.js +25 -0
- package/{dist → esm}/orm/commands/command.helper.d.ts +2 -2
- package/esm/orm/commands/command.helper.js +135 -0
- package/{dist → esm}/orm/commands/count.command.d.ts +3 -3
- package/esm/orm/commands/count.command.js +26 -0
- package/{dist → esm}/orm/commands/create.command.d.ts +2 -2
- package/esm/orm/commands/create.command.js +85 -0
- package/{dist → esm}/orm/commands/destroy.command.d.ts +3 -3
- package/esm/orm/commands/destroy.command.js +26 -0
- package/{dist → esm}/orm/commands/find.command.d.ts +9 -9
- package/esm/orm/commands/find.command.js +318 -0
- package/{dist → esm}/orm/commands/row-converter.d.ts +5 -5
- package/esm/orm/commands/row-converter.js +186 -0
- package/{dist → esm}/orm/commands/update.command.d.ts +3 -3
- package/esm/orm/commands/update.command.js +80 -0
- package/esm/orm/decorators/column.decorator.d.ts +4 -0
- package/esm/orm/decorators/column.decorator.js +19 -0
- package/esm/orm/decorators/embedded.decorator.d.ts +3 -0
- package/esm/orm/decorators/embedded.decorator.js +12 -0
- package/{dist → esm}/orm/decorators/entity.decorator.d.ts +17 -17
- package/esm/orm/decorators/entity.decorator.js +175 -0
- package/{dist → esm}/orm/decorators/events.decorator.d.ts +0 -0
- package/esm/orm/decorators/events.decorator.js +55 -0
- package/{dist → esm}/orm/decorators/foreignkey.decorator.d.ts +1 -1
- package/esm/orm/decorators/foreignkey.decorator.js +9 -0
- package/{dist → esm}/orm/decorators/index.decorator.d.ts +1 -1
- package/esm/orm/decorators/index.decorator.js +17 -0
- package/esm/orm/decorators/link.decorator.d.ts +13 -0
- package/esm/orm/decorators/link.decorator.js +66 -0
- package/{dist → esm}/orm/decorators/primarykey.decorator.d.ts +1 -1
- package/esm/orm/decorators/primarykey.decorator.js +20 -0
- package/{dist → esm}/orm/decorators/transform.decorator.d.ts +1 -1
- package/esm/orm/decorators/transform.decorator.js +19 -0
- package/esm/orm/model/association-field-metadata.d.ts +12 -0
- package/esm/orm/model/association-field-metadata.js +20 -0
- package/{dist → esm}/orm/model/association-node.d.ts +1 -1
- package/esm/orm/model/association-node.js +24 -0
- package/{dist → esm}/orm/model/association.d.ts +6 -7
- package/esm/orm/model/association.js +118 -0
- package/{dist/orm/model/column-element-metadata.d.ts → esm/orm/model/column-field-metadata.d.ts} +10 -14
- package/esm/orm/model/column-field-metadata.js +28 -0
- package/esm/orm/model/embedded-field-metadata.d.ts +14 -0
- package/esm/orm/model/embedded-field-metadata.js +25 -0
- package/esm/orm/model/entity-metadata.d.ts +50 -0
- package/esm/orm/model/entity-metadata.js +337 -0
- package/esm/orm/model/field-metadata.d.ts +16 -0
- package/esm/orm/model/field-metadata.js +1 -0
- package/{dist → esm}/orm/model/index-metadata.d.ts +0 -0
- package/esm/orm/model/index-metadata.js +1 -0
- package/esm/orm/model/link-chain.d.ts +13 -0
- package/esm/orm/model/link-chain.js +43 -0
- package/{dist → esm}/orm/orm.const.d.ts +0 -0
- package/esm/orm/orm.const.js +2 -0
- package/{dist → esm}/orm/orm.type.d.ts +3 -4
- package/esm/orm/orm.type.js +1 -0
- package/{dist → esm}/orm/repository.class.d.ts +31 -31
- package/esm/orm/repository.class.js +238 -0
- package/{dist → esm}/orm/util/apply-mixins.d.ts +0 -0
- package/esm/orm/util/apply-mixins.js +9 -0
- package/{dist → esm}/orm/util/extract-keyvalues.d.ts +1 -1
- package/esm/orm/util/extract-keyvalues.js +57 -0
- package/esm/orm/util/orm.helper.d.ts +13 -0
- package/esm/orm/util/orm.helper.js +28 -0
- package/esm/orm/util/serialize-field.d.ts +2 -0
- package/esm/orm/util/serialize-field.js +39 -0
- package/esm/types.d.ts +8 -0
- package/esm/types.js +1 -0
- package/package.json +53 -40
- package/dist/index.d.ts +0 -33
- package/dist/index.js +0 -42
- package/dist/orm/decorators/column.decorator.d.ts +0 -4
- package/dist/orm/decorators/embedded.decorator.d.ts +0 -3
- package/dist/orm/decorators/entity.decorator.js +0 -179
- package/dist/orm/decorators/link.decorator.d.ts +0 -23
- package/dist/orm/decorators/link.decorator.js +0 -88
- package/dist/orm/model/association-element-metadata.d.ts +0 -10
- package/dist/orm/model/association-element-metadata.js +0 -15
- package/dist/orm/model/element-metadata.d.ts +0 -7
- package/dist/orm/model/embedded-element-metadata.d.ts +0 -14
- package/dist/orm/model/entity-metadata.d.ts +0 -50
- package/dist/orm/model/link-chain.d.ts +0 -15
- package/dist/orm/util/orm.helper.d.ts +0 -13
- package/dist/orm/util/serialize-element.d.ts +0 -2
- package/dist/types.d.ts +0 -2
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AssociationFieldOptions } from '../model/association-field-metadata.js';
|
|
2
|
+
import { TypeThunk } from '../orm.type.js';
|
|
3
|
+
declare type LinkArgs<T> = {
|
|
4
|
+
sourceKey?: string;
|
|
5
|
+
targetKey?: keyof T;
|
|
6
|
+
where?: object | object[];
|
|
7
|
+
};
|
|
8
|
+
declare type LinkPropertyDecorator = PropertyDecorator & {
|
|
9
|
+
toOne<T>(type: TypeThunk<T>, args?: LinkArgs<T>): LinkPropertyDecorator;
|
|
10
|
+
toMany<T>(type: TypeThunk<T>, args?: LinkArgs<T>): LinkPropertyDecorator;
|
|
11
|
+
};
|
|
12
|
+
export declare function Link(options?: AssociationFieldOptions): LinkPropertyDecorator;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { EntityMetadata } from '../model/entity-metadata.js';
|
|
2
|
+
import { LinkChain } from '../model/link-chain.js';
|
|
3
|
+
export function Link(options) {
|
|
4
|
+
let root;
|
|
5
|
+
let chain;
|
|
6
|
+
const fn = (target, propertyKey) => {
|
|
7
|
+
if (typeof propertyKey !== 'string')
|
|
8
|
+
throw new TypeError('Symbol properties are not allowed');
|
|
9
|
+
const reflectType = Reflect.getMetadata("design:type", target, propertyKey);
|
|
10
|
+
if (!root) {
|
|
11
|
+
if (reflectType === Array)
|
|
12
|
+
throw new TypeError(`Can't get type information while it is an array. Please define entity type`);
|
|
13
|
+
if (!EntityMetadata.get(reflectType))
|
|
14
|
+
throw new TypeError(`No entity metadata found for type "${reflectType}"`);
|
|
15
|
+
fn.toOne(reflectType);
|
|
16
|
+
}
|
|
17
|
+
if (reflectType !== Array && root.first.returnsMany())
|
|
18
|
+
throw new TypeError(`Link returns single instance however property type is an array`);
|
|
19
|
+
if (reflectType === Array && !root.first.returnsMany())
|
|
20
|
+
throw new TypeError(`Link returns array of instances however property type is not an array`);
|
|
21
|
+
const entity = EntityMetadata.define(target.constructor);
|
|
22
|
+
// @ts-ignore
|
|
23
|
+
// noinspection JSConstantReassignment
|
|
24
|
+
root.first.source = entity.ctor;
|
|
25
|
+
EntityMetadata.defineAssociationField(entity, propertyKey, root.first, options);
|
|
26
|
+
};
|
|
27
|
+
fn.toOne = (type, args) => {
|
|
28
|
+
if (chain) {
|
|
29
|
+
chain = chain.linkToOne(type, args?.targetKey, args?.sourceKey);
|
|
30
|
+
if (args?.where)
|
|
31
|
+
chain.where(args.where);
|
|
32
|
+
return fn;
|
|
33
|
+
}
|
|
34
|
+
root = linkToOne(type, args?.targetKey, args?.sourceKey);
|
|
35
|
+
chain = root;
|
|
36
|
+
if (args?.where)
|
|
37
|
+
chain.where(args.where);
|
|
38
|
+
return fn;
|
|
39
|
+
};
|
|
40
|
+
fn.toMany = (type, args) => {
|
|
41
|
+
if (chain) {
|
|
42
|
+
chain = chain.linkToMany(type, args?.targetKey, args?.sourceKey);
|
|
43
|
+
if (args?.where)
|
|
44
|
+
chain.where(args.where);
|
|
45
|
+
return fn;
|
|
46
|
+
}
|
|
47
|
+
root = linkToMany(type, args?.targetKey, args?.sourceKey);
|
|
48
|
+
chain = root;
|
|
49
|
+
if (args?.where)
|
|
50
|
+
chain.where(args.where);
|
|
51
|
+
return fn;
|
|
52
|
+
};
|
|
53
|
+
return fn;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Crates an Link Chain object
|
|
57
|
+
*/
|
|
58
|
+
function linkToOne(type, targetKey, sourceKey) {
|
|
59
|
+
return new LinkChain(type, targetKey, sourceKey);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Crates an Link Chain object
|
|
63
|
+
*/
|
|
64
|
+
function linkToMany(type, targetKey, sourceKey) {
|
|
65
|
+
return new LinkChain(type, targetKey, sourceKey, true);
|
|
66
|
+
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { IndexMetadata } from '../model/index-metadata';
|
|
1
|
+
import { IndexMetadata } from '../model/index-metadata.js';
|
|
2
2
|
export declare function PrimaryKey(fields: string | string[], options?: Omit<IndexMetadata, 'columns' | 'unique' | 'primary'>): ClassDecorator;
|
|
3
3
|
export declare function PrimaryKey(options?: Omit<IndexMetadata, 'columns' | 'unique' | 'primary'>): PropertyDecorator;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { EntityMetadata } from '../model/entity-metadata.js';
|
|
2
|
+
import { Column } from './column.decorator.js';
|
|
3
|
+
export function PrimaryKey(arg0, arg1) {
|
|
4
|
+
return function (target, propertyKey) {
|
|
5
|
+
if (arguments.length === 1) {
|
|
6
|
+
if (!(typeof arg0 === 'string' || Array.isArray(arg0)))
|
|
7
|
+
throw new Error(`You must specify primary index column(s)`);
|
|
8
|
+
const meta = EntityMetadata.define(target);
|
|
9
|
+
EntityMetadata.setPrimaryKeys(meta, arg0, arg1);
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
if (!target.constructor)
|
|
13
|
+
throw new Error('Property decorators can be used for class properties only');
|
|
14
|
+
if (typeof propertyKey !== 'string')
|
|
15
|
+
throw new Error('Index() decorator can be used for string property keys only');
|
|
16
|
+
const meta = EntityMetadata.define(target.constructor);
|
|
17
|
+
Column({ notNull: true })(target, propertyKey);
|
|
18
|
+
EntityMetadata.setPrimaryKeys(meta, propertyKey, arg0);
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { ColumnTransformFunction } from '../orm.type';
|
|
1
|
+
import { ColumnTransformFunction } from '../orm.type.js';
|
|
2
2
|
export declare function Parse(fn: ColumnTransformFunction): PropertyDecorator;
|
|
3
3
|
export declare function Serialize(fn: ColumnTransformFunction): PropertyDecorator;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { EntityMetadata } from '../model/entity-metadata.js';
|
|
2
|
+
export function Parse(fn) {
|
|
3
|
+
return (target, propertyKey) => {
|
|
4
|
+
if (typeof propertyKey !== 'string')
|
|
5
|
+
throw new Error('You can define a Column for only string properties');
|
|
6
|
+
const entity = EntityMetadata.define(target.constructor);
|
|
7
|
+
EntityMetadata.defineColumnField(entity, propertyKey)
|
|
8
|
+
.parse = fn;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export function Serialize(fn) {
|
|
12
|
+
return (target, propertyKey) => {
|
|
13
|
+
if (typeof propertyKey !== 'string')
|
|
14
|
+
throw new Error('You can define a Column for only string properties');
|
|
15
|
+
const entity = EntityMetadata.define(target.constructor);
|
|
16
|
+
EntityMetadata.defineColumnField(entity, propertyKey)
|
|
17
|
+
.serialize = fn;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { AssociationNode } from './association-node.js';
|
|
2
|
+
import { EntityMetadata } from './entity-metadata.js';
|
|
3
|
+
import { FieldMetadata } from './field-metadata.js';
|
|
4
|
+
export declare type AssociationFieldOptions = Partial<Omit<AssociationFieldMetadata, 'entity' | 'name' | 'kind' | 'association'>>;
|
|
5
|
+
export interface AssociationFieldMetadata extends FieldMetadata {
|
|
6
|
+
readonly kind: 'association';
|
|
7
|
+
readonly association: AssociationNode;
|
|
8
|
+
}
|
|
9
|
+
export declare namespace AssociationFieldMetadata {
|
|
10
|
+
function create(entity: EntityMetadata, name: string, association: AssociationNode, options?: AssociationFieldOptions): AssociationFieldMetadata;
|
|
11
|
+
function assign(target: AssociationFieldMetadata, options: AssociationFieldOptions): void;
|
|
12
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
2
|
+
export var AssociationFieldMetadata;
|
|
3
|
+
(function (AssociationFieldMetadata) {
|
|
4
|
+
function create(entity, name, association, options = {}) {
|
|
5
|
+
const result = {
|
|
6
|
+
kind: 'association',
|
|
7
|
+
entity,
|
|
8
|
+
name,
|
|
9
|
+
association
|
|
10
|
+
};
|
|
11
|
+
if (options)
|
|
12
|
+
AssociationFieldMetadata.assign(result, options);
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
AssociationFieldMetadata.create = create;
|
|
16
|
+
function assign(target, options) {
|
|
17
|
+
Object.assign(target, _.omit(options, ['entity', 'name', 'kind', 'association']));
|
|
18
|
+
}
|
|
19
|
+
AssociationFieldMetadata.assign = assign;
|
|
20
|
+
})(AssociationFieldMetadata || (AssociationFieldMetadata = {}));
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Association } from './association.js';
|
|
2
|
+
export class AssociationNode extends Association {
|
|
3
|
+
prior;
|
|
4
|
+
next;
|
|
5
|
+
conditions;
|
|
6
|
+
getFirst() {
|
|
7
|
+
let l = this;
|
|
8
|
+
while (l.prior)
|
|
9
|
+
l = l.prior;
|
|
10
|
+
return l;
|
|
11
|
+
}
|
|
12
|
+
getLast() {
|
|
13
|
+
let l = this;
|
|
14
|
+
while (l.next)
|
|
15
|
+
l = l.next;
|
|
16
|
+
return l;
|
|
17
|
+
}
|
|
18
|
+
returnsMany() {
|
|
19
|
+
const n = super.returnsMany();
|
|
20
|
+
if (n)
|
|
21
|
+
return n;
|
|
22
|
+
return !!(this.next && this.next.returnsMany());
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { EntityMetadata } from './entity-metadata';
|
|
1
|
+
import { AssociationSettings, TypeThunk } from '../orm.type.js';
|
|
2
|
+
import { ColumnFieldMetadata } from './column-field-metadata.js';
|
|
3
|
+
import { EntityMetadata } from './entity-metadata.js';
|
|
4
4
|
export declare class Association {
|
|
5
5
|
private _resolved?;
|
|
6
6
|
private _source?;
|
|
@@ -14,15 +14,14 @@ export declare class Association {
|
|
|
14
14
|
readonly target: TypeThunk;
|
|
15
15
|
readonly sourceKey?: string;
|
|
16
16
|
readonly targetKey?: string;
|
|
17
|
-
readonly
|
|
17
|
+
readonly many: boolean;
|
|
18
18
|
constructor(name: string, args: AssociationSettings);
|
|
19
19
|
resolveSource(): Promise<EntityMetadata>;
|
|
20
20
|
resolveTarget(): Promise<EntityMetadata>;
|
|
21
21
|
resolveSourceKey(): Promise<string>;
|
|
22
|
-
resolveSourceProperty(): Promise<
|
|
22
|
+
resolveSourceProperty(): Promise<ColumnFieldMetadata>;
|
|
23
23
|
resolveTargetKey(): Promise<string>;
|
|
24
|
-
resolveTargetProperty(): Promise<
|
|
25
|
-
get sourceBelongsToTarget(): boolean;
|
|
24
|
+
resolveTargetProperty(): Promise<ColumnFieldMetadata>;
|
|
26
25
|
returnsMany(): boolean;
|
|
27
26
|
protected _resolveKeys(): Promise<void>;
|
|
28
27
|
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { camelCase } from 'putil-varhelpers';
|
|
2
|
+
import { resolveEntityMeta } from '../util/orm.helper.js';
|
|
3
|
+
import { EntityMetadata } from './entity-metadata.js';
|
|
4
|
+
export class Association {
|
|
5
|
+
_resolved;
|
|
6
|
+
_source; // cached value
|
|
7
|
+
_target; // cached value
|
|
8
|
+
_sourceKey; // cached value
|
|
9
|
+
_targetKey; // cached value
|
|
10
|
+
_sourceProperty;
|
|
11
|
+
_targetProperty;
|
|
12
|
+
name;
|
|
13
|
+
source;
|
|
14
|
+
target;
|
|
15
|
+
sourceKey;
|
|
16
|
+
targetKey;
|
|
17
|
+
many;
|
|
18
|
+
constructor(name, args) {
|
|
19
|
+
this.name = name;
|
|
20
|
+
this.source = args.source;
|
|
21
|
+
this.target = args.target;
|
|
22
|
+
this.sourceKey = args.sourceKey;
|
|
23
|
+
this.targetKey = args.targetKey;
|
|
24
|
+
this.many = !!args.many;
|
|
25
|
+
}
|
|
26
|
+
async resolveSource() {
|
|
27
|
+
this._source = await resolveEntityMeta(this.source);
|
|
28
|
+
if (!this._source)
|
|
29
|
+
throw new Error(`Can't resolve source entity of association "${this.name}"`);
|
|
30
|
+
return this._source;
|
|
31
|
+
}
|
|
32
|
+
async resolveTarget() {
|
|
33
|
+
this._target = await resolveEntityMeta(this.target);
|
|
34
|
+
if (!this._target)
|
|
35
|
+
throw new Error(`Can't resolve target entity of association "${this.name}"`);
|
|
36
|
+
return this._target;
|
|
37
|
+
}
|
|
38
|
+
async resolveSourceKey() {
|
|
39
|
+
await this._resolveKeys();
|
|
40
|
+
// @ts-ignore
|
|
41
|
+
return this._sourceKey;
|
|
42
|
+
}
|
|
43
|
+
async resolveSourceProperty() {
|
|
44
|
+
await this._resolveKeys();
|
|
45
|
+
// @ts-ignore
|
|
46
|
+
return this._sourceProperty;
|
|
47
|
+
}
|
|
48
|
+
async resolveTargetKey() {
|
|
49
|
+
await this._resolveKeys();
|
|
50
|
+
// @ts-ignore
|
|
51
|
+
return this._targetKey;
|
|
52
|
+
}
|
|
53
|
+
async resolveTargetProperty() {
|
|
54
|
+
await this._resolveKeys();
|
|
55
|
+
// @ts-ignore
|
|
56
|
+
return this._targetProperty;
|
|
57
|
+
}
|
|
58
|
+
returnsMany() {
|
|
59
|
+
return this.many;
|
|
60
|
+
}
|
|
61
|
+
async _resolveKeys() {
|
|
62
|
+
if (this._resolved)
|
|
63
|
+
return;
|
|
64
|
+
const source = await this.resolveSource();
|
|
65
|
+
const target = await this.resolveTarget();
|
|
66
|
+
let sourceKey = this.sourceKey;
|
|
67
|
+
let targetKey = this.targetKey;
|
|
68
|
+
if (!(sourceKey && targetKey)) {
|
|
69
|
+
// Try to determine key fields from foreign key from source to target
|
|
70
|
+
let foreign = await EntityMetadata.getForeignKeyFor(source, target);
|
|
71
|
+
if (foreign && foreign !== this) {
|
|
72
|
+
await foreign._resolveKeys();
|
|
73
|
+
this._sourceKey = foreign._sourceKey;
|
|
74
|
+
this._sourceProperty = foreign._sourceProperty;
|
|
75
|
+
this._targetKey = foreign._targetKey;
|
|
76
|
+
this._targetProperty = foreign._targetProperty;
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
// Try to determine key fields from foreign key from target to source
|
|
81
|
+
foreign = await EntityMetadata.getForeignKeyFor(target, source);
|
|
82
|
+
if (foreign && foreign !== this) {
|
|
83
|
+
await foreign._resolveKeys();
|
|
84
|
+
this._sourceKey = foreign._targetKey;
|
|
85
|
+
this._sourceProperty = foreign._targetProperty;
|
|
86
|
+
this._targetKey = foreign._sourceKey;
|
|
87
|
+
this._targetProperty = foreign._sourceProperty;
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const master = source;
|
|
92
|
+
const detail = target;
|
|
93
|
+
let masterKey = sourceKey || '';
|
|
94
|
+
let detailKey = targetKey || '';
|
|
95
|
+
if (!detailKey) {
|
|
96
|
+
const primaryIndexColumns = EntityMetadata.getPrimaryIndexColumns(detail);
|
|
97
|
+
detailKey = primaryIndexColumns && primaryIndexColumns.length === 1 ?
|
|
98
|
+
primaryIndexColumns[0].name : 'id';
|
|
99
|
+
}
|
|
100
|
+
if (!masterKey) {
|
|
101
|
+
// snake-case
|
|
102
|
+
masterKey = detail.name[0].toLowerCase() + detail.name.substring(1) + '_' + detailKey;
|
|
103
|
+
if (!EntityMetadata.getColumnField(master, masterKey))
|
|
104
|
+
masterKey = camelCase(masterKey);
|
|
105
|
+
}
|
|
106
|
+
targetKey = detailKey;
|
|
107
|
+
sourceKey = masterKey;
|
|
108
|
+
}
|
|
109
|
+
this._targetProperty = EntityMetadata.getColumnField(target, targetKey);
|
|
110
|
+
if (!this._targetProperty)
|
|
111
|
+
throw new Error(`Can't determine target key of ${this.name}`);
|
|
112
|
+
this._sourceProperty = EntityMetadata.getColumnField(source, sourceKey);
|
|
113
|
+
if (!this._sourceProperty)
|
|
114
|
+
throw new Error(`Can't determine source key of ${this.name}`);
|
|
115
|
+
this._targetKey = targetKey;
|
|
116
|
+
this._sourceKey = sourceKey;
|
|
117
|
+
}
|
|
118
|
+
}
|
package/{dist/orm/model/column-element-metadata.d.ts → esm/orm/model/column-field-metadata.d.ts}
RENAMED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { DataType } from '@sqb/builder';
|
|
2
|
-
import type { ColumnAutoGenerationStrategy, ColumnTransformFunction, DefaultValueGetter, EnumValue, FieldValue } from '../orm.type';
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
export declare type
|
|
6
|
-
export interface
|
|
2
|
+
import type { ColumnAutoGenerationStrategy, ColumnTransformFunction, DefaultValueGetter, EnumValue, FieldValue } from '../orm.type.js';
|
|
3
|
+
import type { EntityMetadata } from './entity-metadata.js';
|
|
4
|
+
import { FieldMetadata } from './field-metadata.js';
|
|
5
|
+
export declare type ColumnFieldOptions = Partial<Omit<ColumnFieldMetadata, 'entity' | 'name' | 'kind'>>;
|
|
6
|
+
export interface ColumnFieldMetadata extends FieldMetadata {
|
|
7
7
|
readonly kind: 'column';
|
|
8
8
|
/**
|
|
9
9
|
Name of table field
|
|
@@ -11,7 +11,7 @@ export interface ColumnElementMetadata extends ElementMetadata {
|
|
|
11
11
|
fieldName: string;
|
|
12
12
|
/**
|
|
13
13
|
JS type. String, Boolean, Person etc
|
|
14
|
-
|
|
14
|
+
*/
|
|
15
15
|
type?: Function;
|
|
16
16
|
/**
|
|
17
17
|
* Column data type
|
|
@@ -57,10 +57,6 @@ export interface ColumnElementMetadata extends ElementMetadata {
|
|
|
57
57
|
* Indicates if column value can be null
|
|
58
58
|
*/
|
|
59
59
|
notNull?: boolean;
|
|
60
|
-
/**
|
|
61
|
-
* Indicates whether or not to hide this column by default when making queries.
|
|
62
|
-
*/
|
|
63
|
-
hidden?: boolean;
|
|
64
60
|
/**
|
|
65
61
|
* Indicates if column value is used in update queries
|
|
66
62
|
*/
|
|
@@ -72,8 +68,8 @@ export interface ColumnElementMetadata extends ElementMetadata {
|
|
|
72
68
|
parse?: ColumnTransformFunction;
|
|
73
69
|
serialize?: ColumnTransformFunction;
|
|
74
70
|
}
|
|
75
|
-
export declare namespace
|
|
76
|
-
function create(entity: EntityMetadata, name: string, options?:
|
|
77
|
-
function assign(target:
|
|
78
|
-
function checkEnumValue(col:
|
|
71
|
+
export declare namespace ColumnFieldMetadata {
|
|
72
|
+
function create(entity: EntityMetadata, name: string, options?: ColumnFieldOptions): ColumnFieldMetadata;
|
|
73
|
+
function assign(target: ColumnFieldMetadata, options: ColumnFieldOptions): void;
|
|
74
|
+
function checkEnumValue(col: ColumnFieldMetadata, v: FieldValue): void;
|
|
79
75
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
2
|
+
export var ColumnFieldMetadata;
|
|
3
|
+
(function (ColumnFieldMetadata) {
|
|
4
|
+
function create(entity, name, options = {}) {
|
|
5
|
+
const result = {
|
|
6
|
+
kind: 'column',
|
|
7
|
+
entity,
|
|
8
|
+
name,
|
|
9
|
+
fieldName: name
|
|
10
|
+
};
|
|
11
|
+
if (options)
|
|
12
|
+
ColumnFieldMetadata.assign(result, options);
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
ColumnFieldMetadata.create = create;
|
|
16
|
+
function assign(target, options) {
|
|
17
|
+
Object.assign(target, _.omit(options, ['entity', 'name', 'kind']));
|
|
18
|
+
}
|
|
19
|
+
ColumnFieldMetadata.assign = assign;
|
|
20
|
+
function checkEnumValue(col, v) {
|
|
21
|
+
if (v === undefined || !col.enum || (v == null && !col.notNull))
|
|
22
|
+
return;
|
|
23
|
+
const enumKeys = Array.isArray(col.enum) ? col.enum : Object.keys(col.enum);
|
|
24
|
+
if (!enumKeys.includes(v))
|
|
25
|
+
throw new Error(`${col.entity.name}.${col.name} value must be one of (${enumKeys})`);
|
|
26
|
+
}
|
|
27
|
+
ColumnFieldMetadata.checkEnumValue = checkEnumValue;
|
|
28
|
+
})(ColumnFieldMetadata || (ColumnFieldMetadata = {}));
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { TypeThunk } from '../orm.type.js';
|
|
2
|
+
import type { EntityMetadata } from './entity-metadata.js';
|
|
3
|
+
import { FieldMetadata } from './field-metadata.js';
|
|
4
|
+
export declare type EmbeddedFieldOptions = Partial<Omit<EmbeddedFieldMetadata, 'entity' | 'name' | 'kind' | 'type'>>;
|
|
5
|
+
export interface EmbeddedFieldMetadata extends FieldMetadata {
|
|
6
|
+
readonly kind: 'object';
|
|
7
|
+
type: TypeThunk;
|
|
8
|
+
fieldNamePrefix?: string;
|
|
9
|
+
fieldNameSuffix?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare namespace EmbeddedFieldMetadata {
|
|
12
|
+
function create(entity: EntityMetadata, name: string, type: TypeThunk, options?: EmbeddedFieldOptions): EmbeddedFieldMetadata;
|
|
13
|
+
function resolveType(meta: EmbeddedFieldMetadata): Promise<EntityMetadata>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { resolveEntityMeta } from '../util/orm.helper.js';
|
|
2
|
+
export var EmbeddedFieldMetadata;
|
|
3
|
+
(function (EmbeddedFieldMetadata) {
|
|
4
|
+
function create(entity, name, type, options) {
|
|
5
|
+
const result = {
|
|
6
|
+
kind: 'object',
|
|
7
|
+
entity,
|
|
8
|
+
name,
|
|
9
|
+
type
|
|
10
|
+
};
|
|
11
|
+
if (options?.fieldNamePrefix)
|
|
12
|
+
result.fieldNamePrefix = options.fieldNamePrefix;
|
|
13
|
+
if (options?.fieldNameSuffix)
|
|
14
|
+
result.fieldNameSuffix = options.fieldNameSuffix;
|
|
15
|
+
return result;
|
|
16
|
+
}
|
|
17
|
+
EmbeddedFieldMetadata.create = create;
|
|
18
|
+
async function resolveType(meta) {
|
|
19
|
+
const typ = await resolveEntityMeta(meta.type);
|
|
20
|
+
if (typ)
|
|
21
|
+
return typ;
|
|
22
|
+
throw new Error(`Can't resolve type of ${meta.entity.name}.${meta.name}`);
|
|
23
|
+
}
|
|
24
|
+
EmbeddedFieldMetadata.resolveType = resolveType;
|
|
25
|
+
})(EmbeddedFieldMetadata || (EmbeddedFieldMetadata = {}));
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Maybe, Type } from 'ts-gems';
|
|
2
|
+
import { Ctor, TypeThunk } from '../orm.type.js';
|
|
3
|
+
import { Association } from './association.js';
|
|
4
|
+
import { AssociationFieldMetadata, AssociationFieldOptions } from './association-field-metadata.js';
|
|
5
|
+
import { AssociationNode } from './association-node.js';
|
|
6
|
+
import { ColumnFieldMetadata, ColumnFieldOptions } from './column-field-metadata.js';
|
|
7
|
+
import { EmbeddedFieldMetadata, EmbeddedFieldOptions } from './embedded-field-metadata.js';
|
|
8
|
+
import { IndexMetadata } from './index-metadata.js';
|
|
9
|
+
export declare type AnyFieldMetadata = ColumnFieldMetadata | EmbeddedFieldMetadata | AssociationFieldMetadata;
|
|
10
|
+
export declare type EntityOptions = Partial<Pick<EntityMetadata, 'name' | 'schema' | 'comment' | 'tableName'>>;
|
|
11
|
+
export interface EntityMetadata {
|
|
12
|
+
readonly ctor: Type;
|
|
13
|
+
readonly name: string;
|
|
14
|
+
tableName?: string;
|
|
15
|
+
schema?: string;
|
|
16
|
+
comment?: string;
|
|
17
|
+
fields: Record<string, AnyFieldMetadata>;
|
|
18
|
+
indexes: IndexMetadata[];
|
|
19
|
+
foreignKeys: Association[];
|
|
20
|
+
eventListeners: Record<string, Function[]>;
|
|
21
|
+
}
|
|
22
|
+
export declare namespace EntityMetadata {
|
|
23
|
+
function define(ctor: Ctor): EntityMetadata;
|
|
24
|
+
function get(ctor: Ctor): Maybe<EntityMetadata>;
|
|
25
|
+
function getOwn(ctor: Ctor): Maybe<EntityMetadata>;
|
|
26
|
+
function getField(entity: EntityMetadata, fieldName: string): Maybe<AnyFieldMetadata>;
|
|
27
|
+
function getColumnField(entity: EntityMetadata, fieldName: string): Maybe<ColumnFieldMetadata>;
|
|
28
|
+
function getEmbeddedField(entity: EntityMetadata, fieldName: string): Maybe<EmbeddedFieldMetadata>;
|
|
29
|
+
function getAssociationField(entity: EntityMetadata, fieldName: string): Maybe<AssociationFieldMetadata>;
|
|
30
|
+
function findField(entity: EntityMetadata, predicate: (el: AnyFieldMetadata) => boolean): Maybe<AnyFieldMetadata>;
|
|
31
|
+
function getColumnFieldByFieldName(entity: EntityMetadata, fieldName: string): Maybe<ColumnFieldMetadata>;
|
|
32
|
+
function getFieldNames(entity: EntityMetadata, filter?: (el: AnyFieldMetadata) => boolean): string[];
|
|
33
|
+
function getColumnFieldNames(entity: EntityMetadata): string[];
|
|
34
|
+
function getEmbeddedFieldNames(entity: EntityMetadata): string[];
|
|
35
|
+
function getAssociationFieldNames(entity: EntityMetadata): string[];
|
|
36
|
+
function getNonAssociationFieldNames(entity: EntityMetadata): string[];
|
|
37
|
+
function getInsertColumnNames(entity: EntityMetadata): string[];
|
|
38
|
+
function getUpdateColumnNames(entity: EntityMetadata): string[];
|
|
39
|
+
function getPrimaryIndex(entity: EntityMetadata): Maybe<IndexMetadata>;
|
|
40
|
+
function getPrimaryIndexColumns(entity: EntityMetadata): ColumnFieldMetadata[];
|
|
41
|
+
function getForeignKeyFor(src: EntityMetadata, trg: EntityMetadata): Promise<Maybe<Association>>;
|
|
42
|
+
function addIndex(entity: EntityMetadata, index: IndexMetadata): void;
|
|
43
|
+
function addForeignKey(entity: EntityMetadata, propertyKey: string, target: TypeThunk, targetKey?: string): void;
|
|
44
|
+
function addEventListener(entity: EntityMetadata, event: string, fn: Function): void;
|
|
45
|
+
function defineColumnField(entity: EntityMetadata, name: string, options?: ColumnFieldOptions): ColumnFieldMetadata;
|
|
46
|
+
function defineEmbeddedField(entity: EntityMetadata, name: string, type: TypeThunk, options?: EmbeddedFieldOptions): EmbeddedFieldMetadata;
|
|
47
|
+
function defineAssociationField(entity: EntityMetadata, propertyKey: string, association: AssociationNode, options?: AssociationFieldOptions): AssociationFieldMetadata;
|
|
48
|
+
function setPrimaryKeys(entity: EntityMetadata, column: string | string[], options?: Omit<IndexMetadata, 'columns' | 'unique' | 'primary'>): void;
|
|
49
|
+
function mixin(derived: EntityMetadata, base: EntityMetadata, filter?: (n: string) => boolean): void;
|
|
50
|
+
}
|