@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
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Type } from 'ts-gems';
|
|
2
2
|
import { DataType } from '@sqb/builder';
|
|
3
|
-
import type { FieldInfoMap } from '../../client/
|
|
4
|
-
import { SqbConnection } from '../../client/
|
|
5
|
-
import { ColumnTransformFunction } from '../orm.type';
|
|
6
|
-
import type { Repository } from '../repository.class';
|
|
7
|
-
import type { FindCommand } from './find.command';
|
|
3
|
+
import type { FieldInfoMap } from '../../client/field-info-map';
|
|
4
|
+
import { SqbConnection } from '../../client/sqb-connection.js';
|
|
5
|
+
import { ColumnTransformFunction } from '../orm.type.js';
|
|
6
|
+
import type { Repository } from '../repository.class.js';
|
|
7
|
+
import type { FindCommand } from './find.command.js';
|
|
8
8
|
export interface ValueProperty {
|
|
9
9
|
fieldAlias: string;
|
|
10
10
|
dataType?: DataType;
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { DataType } from '@sqb/builder';
|
|
2
|
+
const isValueProperty = (prop) => {
|
|
3
|
+
return prop.fieldAlias && !prop.converter;
|
|
4
|
+
};
|
|
5
|
+
const isObjectProperty = (prop) => {
|
|
6
|
+
return prop.converter && !prop.findCommand;
|
|
7
|
+
};
|
|
8
|
+
const isNestedProperty = (prop) => {
|
|
9
|
+
return prop.converter && prop.findCommand;
|
|
10
|
+
};
|
|
11
|
+
export class RowConverter {
|
|
12
|
+
resultType;
|
|
13
|
+
parent;
|
|
14
|
+
_properties = {};
|
|
15
|
+
_propertyKeys;
|
|
16
|
+
constructor(resultType, parent) {
|
|
17
|
+
this.resultType = resultType;
|
|
18
|
+
this.parent = parent;
|
|
19
|
+
}
|
|
20
|
+
addValueProperty(args) {
|
|
21
|
+
this._propertyKeys = undefined;
|
|
22
|
+
const item = {
|
|
23
|
+
fieldAlias: args.fieldAlias,
|
|
24
|
+
dataType: args.dataType,
|
|
25
|
+
parse: args.parse
|
|
26
|
+
};
|
|
27
|
+
this._properties[args.name] = item;
|
|
28
|
+
return item;
|
|
29
|
+
}
|
|
30
|
+
addObjectProperty(args) {
|
|
31
|
+
this._checkCircularDep(args.type);
|
|
32
|
+
this._propertyKeys = undefined;
|
|
33
|
+
const converter = new RowConverter(args.type, this);
|
|
34
|
+
const item = {
|
|
35
|
+
converter,
|
|
36
|
+
type: args.type
|
|
37
|
+
};
|
|
38
|
+
this._properties[args.name] = item;
|
|
39
|
+
return item;
|
|
40
|
+
}
|
|
41
|
+
addNestedProperty(args) {
|
|
42
|
+
this._checkCircularDep(args.type);
|
|
43
|
+
const converter = new RowConverter(args.type, this);
|
|
44
|
+
const item = {
|
|
45
|
+
converter,
|
|
46
|
+
type: args.type,
|
|
47
|
+
parentField: args.parentField,
|
|
48
|
+
keyField: args.keyField,
|
|
49
|
+
findCommand: args.findCommand,
|
|
50
|
+
sort: args.sort,
|
|
51
|
+
paramValues: []
|
|
52
|
+
};
|
|
53
|
+
this._properties[args.name] = item;
|
|
54
|
+
return item;
|
|
55
|
+
}
|
|
56
|
+
get keys() {
|
|
57
|
+
if (!this._propertyKeys)
|
|
58
|
+
this._propertyKeys = Object.keys(this._properties);
|
|
59
|
+
return this._propertyKeys;
|
|
60
|
+
}
|
|
61
|
+
async transform(connection, fields, rows, onTransform) {
|
|
62
|
+
const rowLen = rows.length;
|
|
63
|
+
const result = [];
|
|
64
|
+
for (let rowIdx = 0; rowIdx < rowLen; rowIdx++) {
|
|
65
|
+
const row = rows[rowIdx];
|
|
66
|
+
const o = (await this._rowToObject(connection, fields, row)) || {};
|
|
67
|
+
if (onTransform)
|
|
68
|
+
onTransform(fields, row, o);
|
|
69
|
+
result.push(o);
|
|
70
|
+
}
|
|
71
|
+
if (!this.keys)
|
|
72
|
+
return result;
|
|
73
|
+
await this._iterateForNested(this, connection, fields, rows, result);
|
|
74
|
+
// Return only non empty objects
|
|
75
|
+
return result.filter(x => !!x);
|
|
76
|
+
}
|
|
77
|
+
_rowToObject(executor, fields, row) {
|
|
78
|
+
// Cache keys for better performance
|
|
79
|
+
const fieldKeys = this.keys;
|
|
80
|
+
const fieldsLen = fieldKeys.length;
|
|
81
|
+
let result;
|
|
82
|
+
for (let elIdx = 0; elIdx < fieldsLen; elIdx++) {
|
|
83
|
+
const elKey = fieldKeys[elIdx];
|
|
84
|
+
const prop = this._properties[elKey];
|
|
85
|
+
if (isValueProperty(prop)) {
|
|
86
|
+
const field = fields.get(prop.fieldAlias);
|
|
87
|
+
if (field) {
|
|
88
|
+
let v = row[field.index];
|
|
89
|
+
if (typeof prop.parse === 'function')
|
|
90
|
+
v = prop.parse(v, elKey);
|
|
91
|
+
if (v != null) {
|
|
92
|
+
result = result || {};
|
|
93
|
+
if (prop.dataType === DataType.JSON && typeof v === 'string')
|
|
94
|
+
v = JSON.parse(v);
|
|
95
|
+
result[elKey] = v;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
else if (isNestedProperty(prop)) {
|
|
100
|
+
// One2Many Eager field
|
|
101
|
+
// Keep a list of key field/value pairs to fetch rows for eager relation
|
|
102
|
+
const _params = prop.paramValues;
|
|
103
|
+
const f = fields.get(prop.parentField);
|
|
104
|
+
const v = f && row[f.index];
|
|
105
|
+
if (v != null && !_params.includes(v))
|
|
106
|
+
_params.push(v);
|
|
107
|
+
}
|
|
108
|
+
else if (isObjectProperty(prop)) {
|
|
109
|
+
const v = prop.converter._rowToObject(executor, fields, row);
|
|
110
|
+
if (v != null) {
|
|
111
|
+
result = result || {};
|
|
112
|
+
result[elKey] = v;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (result)
|
|
117
|
+
Object.setPrototypeOf(result, this.resultType.prototype);
|
|
118
|
+
return result;
|
|
119
|
+
}
|
|
120
|
+
async _iterateForNested(node, connection, fields, rows, result) {
|
|
121
|
+
// Fetch one-2-many related rows and merge with result rows
|
|
122
|
+
const keys = node.keys;
|
|
123
|
+
const propertyLen = keys.length;
|
|
124
|
+
const promises = [];
|
|
125
|
+
for (let propIdx = 0; propIdx < propertyLen; propIdx++) {
|
|
126
|
+
const propKey = keys[propIdx];
|
|
127
|
+
const prop = node._properties[propKey];
|
|
128
|
+
if (isNestedProperty(prop)) {
|
|
129
|
+
if (!(prop.paramValues && prop.paramValues.length))
|
|
130
|
+
continue;
|
|
131
|
+
const resultType = this.resultType;
|
|
132
|
+
const promise = async function (p) {
|
|
133
|
+
const findCommand = p.findCommand;
|
|
134
|
+
let fld;
|
|
135
|
+
const map = new Map();
|
|
136
|
+
const r = await findCommand.execute({
|
|
137
|
+
connection,
|
|
138
|
+
limit: findCommand.maxEagerFetch + 1,
|
|
139
|
+
params: { [p.parentField]: p.paramValues },
|
|
140
|
+
onTransformRow: (_fields, row, obj) => {
|
|
141
|
+
fld = fld || _fields.get('' + p.keyField);
|
|
142
|
+
const keyValue = fld && row[fld.index];
|
|
143
|
+
if (keyValue != null) {
|
|
144
|
+
let arr = map.get(keyValue);
|
|
145
|
+
if (!arr) {
|
|
146
|
+
arr = [];
|
|
147
|
+
map.set(keyValue, arr);
|
|
148
|
+
}
|
|
149
|
+
arr.push(obj);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
if (r.length > findCommand.maxEagerFetch)
|
|
154
|
+
throw new Error(`Number of returning rows for "${propKey}" exceeds maxEagerFetch limit`);
|
|
155
|
+
for (let i = 0; i < result.length; i++) {
|
|
156
|
+
const row = rows[i];
|
|
157
|
+
let obj = result[i];
|
|
158
|
+
if (!obj) {
|
|
159
|
+
obj = {};
|
|
160
|
+
Object.setPrototypeOf(result, resultType.prototype);
|
|
161
|
+
}
|
|
162
|
+
const f = fields.get('' + p.parentField);
|
|
163
|
+
const keyValue = f && row[f.index];
|
|
164
|
+
if (keyValue != null) {
|
|
165
|
+
const arr = map.get(keyValue);
|
|
166
|
+
if (arr) {
|
|
167
|
+
obj[propKey] = arr;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}(prop);
|
|
172
|
+
promises.push(promise);
|
|
173
|
+
}
|
|
174
|
+
else if (isObjectProperty(prop)) {
|
|
175
|
+
promises.push(this._iterateForNested(prop.converter, connection, fields, rows, result));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
await Promise.all(promises);
|
|
179
|
+
}
|
|
180
|
+
_checkCircularDep(t) {
|
|
181
|
+
if (this.resultType === t)
|
|
182
|
+
throw new Error('Circular fields requested');
|
|
183
|
+
if (this.parent)
|
|
184
|
+
this.parent._checkCircularDep(t);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { SqbConnection } from '../../client/
|
|
2
|
-
import { EntityMetadata } from '../model/entity-metadata';
|
|
3
|
-
import { Repository } from '../repository.class';
|
|
1
|
+
import { SqbConnection } from '../../client/sqb-connection.js';
|
|
2
|
+
import { EntityMetadata } from '../model/entity-metadata.js';
|
|
3
|
+
import { Repository } from '../repository.class.js';
|
|
4
4
|
export declare type UpdateCommandArgs = {
|
|
5
5
|
entity: EntityMetadata;
|
|
6
6
|
connection: SqbConnection;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { And, Param, Update } from '@sqb/builder';
|
|
2
|
+
import { ColumnFieldMetadata } from '../model/column-field-metadata.js';
|
|
3
|
+
import { EmbeddedFieldMetadata } from '../model/embedded-field-metadata.js';
|
|
4
|
+
import { isColumnField, isEmbeddedField } from '../util/orm.helper.js';
|
|
5
|
+
import { prepareFilter } from './command.helper.js';
|
|
6
|
+
export class UpdateCommand {
|
|
7
|
+
// istanbul ignore next
|
|
8
|
+
constructor() {
|
|
9
|
+
throw new Error('This class is abstract');
|
|
10
|
+
}
|
|
11
|
+
static async execute(args) {
|
|
12
|
+
const { entity } = args;
|
|
13
|
+
const tableName = entity.tableName;
|
|
14
|
+
if (!tableName)
|
|
15
|
+
throw new Error(`${entity.ctor.name} is not decorated with @Entity decorator`);
|
|
16
|
+
// Create a context
|
|
17
|
+
const ctx = {
|
|
18
|
+
entity,
|
|
19
|
+
queryParams: {},
|
|
20
|
+
queryValues: {},
|
|
21
|
+
queryFilter: [],
|
|
22
|
+
colCount: 0,
|
|
23
|
+
};
|
|
24
|
+
// Prepare
|
|
25
|
+
await this._prepareParams(ctx, entity, args.values);
|
|
26
|
+
if (!ctx.colCount)
|
|
27
|
+
return 0;
|
|
28
|
+
if (args.filter)
|
|
29
|
+
await this._prepareFilter(ctx, args.filter);
|
|
30
|
+
const query = Update(tableName + ' as T', ctx.queryValues)
|
|
31
|
+
.where(...ctx.queryFilter);
|
|
32
|
+
const qr = await args.connection.execute(query, {
|
|
33
|
+
params: args.params ? [...args.params, ctx.queryParams] : ctx.queryParams,
|
|
34
|
+
objectRows: false,
|
|
35
|
+
cursor: false
|
|
36
|
+
});
|
|
37
|
+
return qr.rowsAffected || 0;
|
|
38
|
+
}
|
|
39
|
+
static async _prepareFilter(ctx, filter) {
|
|
40
|
+
if (filter) {
|
|
41
|
+
const where = And();
|
|
42
|
+
await prepareFilter(ctx.entity, filter, where);
|
|
43
|
+
ctx.queryFilter.push(...where._items);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
static async _prepareParams(ctx, entity, values, prefix, suffix) {
|
|
47
|
+
let v;
|
|
48
|
+
prefix = prefix || '';
|
|
49
|
+
suffix = suffix || '';
|
|
50
|
+
for (const col of Object.values(entity.fields)) {
|
|
51
|
+
v = values[col.name];
|
|
52
|
+
if (v === undefined)
|
|
53
|
+
continue;
|
|
54
|
+
if (isColumnField(col)) {
|
|
55
|
+
if (col.noUpdate)
|
|
56
|
+
continue;
|
|
57
|
+
if (typeof col.serialize === 'function')
|
|
58
|
+
v = col.serialize(v, col.name);
|
|
59
|
+
if (v === null && col.notNull)
|
|
60
|
+
throw new Error(`${entity.name}.${col.name} is required and can't be null`);
|
|
61
|
+
if (v === undefined)
|
|
62
|
+
continue;
|
|
63
|
+
ColumnFieldMetadata.checkEnumValue(col, v);
|
|
64
|
+
const fieldName = prefix + col.fieldName + suffix;
|
|
65
|
+
const k = '$input_' + fieldName;
|
|
66
|
+
ctx.queryValues[fieldName] = Param({
|
|
67
|
+
name: k,
|
|
68
|
+
dataType: col.dataType,
|
|
69
|
+
isArray: col.isArray
|
|
70
|
+
});
|
|
71
|
+
ctx.queryParams[k] = v;
|
|
72
|
+
ctx.colCount++;
|
|
73
|
+
}
|
|
74
|
+
else if (v != null && isEmbeddedField(col)) {
|
|
75
|
+
const type = await EmbeddedFieldMetadata.resolveType(col);
|
|
76
|
+
await this._prepareParams(ctx, type, v, col.fieldNamePrefix, col.fieldNameSuffix);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { EntityMetadata } from '../model/entity-metadata.js';
|
|
2
|
+
export function Column(arg0) {
|
|
3
|
+
return (target, propertyKey) => {
|
|
4
|
+
if (typeof propertyKey !== 'string')
|
|
5
|
+
throw new Error('Symbol properties are not accepted');
|
|
6
|
+
const options = (typeof arg0 === 'string' ? { dataType: arg0 } : arg0) || {};
|
|
7
|
+
const entity = EntityMetadata.define(target.constructor);
|
|
8
|
+
if (!options.type) {
|
|
9
|
+
const typ = Reflect.getMetadata("design:type", entity.ctor.prototype, propertyKey);
|
|
10
|
+
if (typ === Array) {
|
|
11
|
+
options.type = String;
|
|
12
|
+
options.isArray = true;
|
|
13
|
+
}
|
|
14
|
+
else
|
|
15
|
+
options.type = typ;
|
|
16
|
+
}
|
|
17
|
+
EntityMetadata.defineColumnField(entity, propertyKey, options);
|
|
18
|
+
};
|
|
19
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { EntityMetadata } from '../model/entity-metadata.js';
|
|
2
|
+
export function Embedded(type, options) {
|
|
3
|
+
return (target, propertyKey) => {
|
|
4
|
+
if (typeof propertyKey !== 'string')
|
|
5
|
+
throw new Error('Symbol properties are not accepted');
|
|
6
|
+
type = type || Reflect.getMetadata("design:type", target, propertyKey);
|
|
7
|
+
if (typeof type !== 'function')
|
|
8
|
+
throw new Error('"type" must be defined');
|
|
9
|
+
const entity = EntityMetadata.define(target.constructor);
|
|
10
|
+
EntityMetadata.defineEmbeddedField(entity, propertyKey, type, options);
|
|
11
|
+
};
|
|
12
|
+
}
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
import { Maybe, Type } from 'ts-gems';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { IndexMetadata } from '../model/index-metadata';
|
|
2
|
+
import { AssociationFieldMetadata } from '../model/association-field-metadata.js';
|
|
3
|
+
import { ColumnFieldMetadata } from '../model/column-field-metadata.js';
|
|
4
|
+
import { EmbeddedFieldMetadata } from '../model/embedded-field-metadata.js';
|
|
5
|
+
import { AnyFieldMetadata, EntityMetadata, EntityOptions } from '../model/entity-metadata.js';
|
|
6
|
+
import { IndexMetadata } from '../model/index-metadata.js';
|
|
7
7
|
export declare function Entity(options?: EntityOptions | string): ClassDecorator;
|
|
8
8
|
export declare namespace Entity {
|
|
9
9
|
const getMetadata: typeof EntityMetadata.get;
|
|
10
10
|
const getOwnMetadata: typeof EntityMetadata.getOwn;
|
|
11
|
-
function
|
|
12
|
-
function
|
|
13
|
-
function
|
|
14
|
-
function
|
|
15
|
-
function
|
|
16
|
-
function find(ctor: Type, predicate: (el:
|
|
17
|
-
function
|
|
18
|
-
function
|
|
19
|
-
function
|
|
20
|
-
function
|
|
21
|
-
function
|
|
11
|
+
function getField<T>(ctor: Type<T>, key: keyof T | string): Maybe<AnyFieldMetadata>;
|
|
12
|
+
function getColumnField<T>(ctor: Type<T>, key: keyof T | string): Maybe<ColumnFieldMetadata>;
|
|
13
|
+
function getEmbeddedField<T>(ctor: Type<T>, key: keyof T | string): Maybe<EmbeddedFieldMetadata>;
|
|
14
|
+
function getAssociationField<T>(ctor: Type<T>, key: keyof T | string): Maybe<AssociationFieldMetadata>;
|
|
15
|
+
function getColumnFieldByFieldName(ctor: Type, fieldName: string): Maybe<ColumnFieldMetadata>;
|
|
16
|
+
function find(ctor: Type, predicate: (el: AnyFieldMetadata) => boolean): Maybe<AnyFieldMetadata>;
|
|
17
|
+
function getFieldNames(ctor: Type, filter?: (el: AnyFieldMetadata) => boolean): string[];
|
|
18
|
+
function getColumnFieldNames(ctor: Type): string[];
|
|
19
|
+
function getEmbeddedFieldNames(ctor: Type): string[];
|
|
20
|
+
function getAssociationFieldNames(ctor: Type): string[];
|
|
21
|
+
function getNonAssociationFieldNames(ctor: Type): string[];
|
|
22
22
|
function getInsertColumnNames(ctor: Type): string[];
|
|
23
23
|
function getUpdateColumnNames(ctor: Type): string[];
|
|
24
24
|
function getPrimaryIndex(ctor: Type): Maybe<IndexMetadata>;
|
|
25
|
-
function getPrimaryIndexColumns(ctor: Type):
|
|
25
|
+
function getPrimaryIndexColumns(ctor: Type): ColumnFieldMetadata[];
|
|
26
26
|
function mixin<A, B>(derivedCtor: Type<A>, baseB: Type<B>): Type<A & B>;
|
|
27
27
|
function mixin<A, B, C>(derivedCtor: Type<A>, baseB: Type<B>, baseC: Type<C>): Type<A & B & C>;
|
|
28
28
|
function mixin<A, B, C, D>(derivedCtor: Type<A>, baseB: Type<B>, baseC: Type<C>, baseD: Type<D>): Type<A & B & C & D>;
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { EntityMetadata } from '../model/entity-metadata.js';
|
|
2
|
+
import { applyMixins } from '../util/apply-mixins.js';
|
|
3
|
+
export function Entity(options) {
|
|
4
|
+
return function (target) {
|
|
5
|
+
const opts = typeof options === 'object' ? options : {};
|
|
6
|
+
const tableName = typeof options === 'string' ? options : opts.tableName;
|
|
7
|
+
const entity = EntityMetadata.define(target);
|
|
8
|
+
entity.tableName = tableName || target.name;
|
|
9
|
+
if (opts.schema)
|
|
10
|
+
entity.schema = opts.schema;
|
|
11
|
+
if (opts.comment)
|
|
12
|
+
entity.comment = opts.comment;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
(function (Entity) {
|
|
16
|
+
Entity.getMetadata = EntityMetadata.get;
|
|
17
|
+
Entity.getOwnMetadata = EntityMetadata.getOwn;
|
|
18
|
+
function getField(ctor, key) {
|
|
19
|
+
const model = EntityMetadata.get(ctor);
|
|
20
|
+
return model && EntityMetadata.getField(model, key);
|
|
21
|
+
}
|
|
22
|
+
Entity.getField = getField;
|
|
23
|
+
function getColumnField(ctor, key) {
|
|
24
|
+
const model = EntityMetadata.get(ctor);
|
|
25
|
+
return model && EntityMetadata.getColumnField(model, key);
|
|
26
|
+
}
|
|
27
|
+
Entity.getColumnField = getColumnField;
|
|
28
|
+
function getEmbeddedField(ctor, key) {
|
|
29
|
+
const model = EntityMetadata.get(ctor);
|
|
30
|
+
return model && EntityMetadata.getEmbeddedField(model, key);
|
|
31
|
+
}
|
|
32
|
+
Entity.getEmbeddedField = getEmbeddedField;
|
|
33
|
+
function getAssociationField(ctor, key) {
|
|
34
|
+
const model = EntityMetadata.get(ctor);
|
|
35
|
+
return model && EntityMetadata.getAssociationField(model, key);
|
|
36
|
+
}
|
|
37
|
+
Entity.getAssociationField = getAssociationField;
|
|
38
|
+
function getColumnFieldByFieldName(ctor, fieldName) {
|
|
39
|
+
const model = EntityMetadata.get(ctor);
|
|
40
|
+
return model && EntityMetadata.getColumnFieldByFieldName(model, fieldName);
|
|
41
|
+
}
|
|
42
|
+
Entity.getColumnFieldByFieldName = getColumnFieldByFieldName;
|
|
43
|
+
function find(ctor, predicate) {
|
|
44
|
+
const model = EntityMetadata.get(ctor);
|
|
45
|
+
return model && EntityMetadata.findField(model, predicate);
|
|
46
|
+
}
|
|
47
|
+
Entity.find = find;
|
|
48
|
+
function getFieldNames(ctor, filter) {
|
|
49
|
+
const model = EntityMetadata.get(ctor);
|
|
50
|
+
return (model && EntityMetadata.getFieldNames(model, filter)) || [];
|
|
51
|
+
}
|
|
52
|
+
Entity.getFieldNames = getFieldNames;
|
|
53
|
+
function getColumnFieldNames(ctor) {
|
|
54
|
+
const model = EntityMetadata.get(ctor);
|
|
55
|
+
return (model && EntityMetadata.getColumnFieldNames(model)) || [];
|
|
56
|
+
}
|
|
57
|
+
Entity.getColumnFieldNames = getColumnFieldNames;
|
|
58
|
+
function getEmbeddedFieldNames(ctor) {
|
|
59
|
+
const model = EntityMetadata.get(ctor);
|
|
60
|
+
return (model && EntityMetadata.getEmbeddedFieldNames(model)) || [];
|
|
61
|
+
}
|
|
62
|
+
Entity.getEmbeddedFieldNames = getEmbeddedFieldNames;
|
|
63
|
+
function getAssociationFieldNames(ctor) {
|
|
64
|
+
const model = EntityMetadata.get(ctor);
|
|
65
|
+
return (model && EntityMetadata.getAssociationFieldNames(model)) || [];
|
|
66
|
+
}
|
|
67
|
+
Entity.getAssociationFieldNames = getAssociationFieldNames;
|
|
68
|
+
function getNonAssociationFieldNames(ctor) {
|
|
69
|
+
const model = EntityMetadata.get(ctor);
|
|
70
|
+
return (model && EntityMetadata.getNonAssociationFieldNames(model)) || [];
|
|
71
|
+
}
|
|
72
|
+
Entity.getNonAssociationFieldNames = getNonAssociationFieldNames;
|
|
73
|
+
function getInsertColumnNames(ctor) {
|
|
74
|
+
const model = EntityMetadata.get(ctor);
|
|
75
|
+
return (model && EntityMetadata.getInsertColumnNames(model)) || [];
|
|
76
|
+
}
|
|
77
|
+
Entity.getInsertColumnNames = getInsertColumnNames;
|
|
78
|
+
function getUpdateColumnNames(ctor) {
|
|
79
|
+
const model = EntityMetadata.get(ctor);
|
|
80
|
+
return (model && EntityMetadata.getUpdateColumnNames(model)) || [];
|
|
81
|
+
}
|
|
82
|
+
Entity.getUpdateColumnNames = getUpdateColumnNames;
|
|
83
|
+
function getPrimaryIndex(ctor) {
|
|
84
|
+
const model = EntityMetadata.define(ctor);
|
|
85
|
+
return EntityMetadata.getPrimaryIndex(model);
|
|
86
|
+
}
|
|
87
|
+
Entity.getPrimaryIndex = getPrimaryIndex;
|
|
88
|
+
function getPrimaryIndexColumns(ctor) {
|
|
89
|
+
const model = EntityMetadata.define(ctor);
|
|
90
|
+
return EntityMetadata.getPrimaryIndexColumns(model);
|
|
91
|
+
}
|
|
92
|
+
Entity.getPrimaryIndexColumns = getPrimaryIndexColumns;
|
|
93
|
+
function mixin(derivedCtor, ...bases) {
|
|
94
|
+
for (const base of bases) {
|
|
95
|
+
if (!base)
|
|
96
|
+
continue;
|
|
97
|
+
applyMixins(derivedCtor, base);
|
|
98
|
+
const srcMeta = EntityMetadata.get(base);
|
|
99
|
+
if (srcMeta) {
|
|
100
|
+
const trgMeta = EntityMetadata.define(derivedCtor);
|
|
101
|
+
EntityMetadata.mixin(trgMeta, srcMeta);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return derivedCtor;
|
|
105
|
+
}
|
|
106
|
+
Entity.mixin = mixin;
|
|
107
|
+
function Pick(classRef, keys) {
|
|
108
|
+
const PickEntityClass = class {
|
|
109
|
+
constructor(...args) {
|
|
110
|
+
applyConstructorProperties(this, classRef, args);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
const pickKeys = keys.map(x => x.toLowerCase());
|
|
114
|
+
const filter = (k) => pickKeys.includes(k.toLowerCase());
|
|
115
|
+
applyMixins(PickEntityClass, classRef, filter);
|
|
116
|
+
const srcMeta = EntityMetadata.get(classRef);
|
|
117
|
+
if (srcMeta) {
|
|
118
|
+
const trgMeta = EntityMetadata.define(PickEntityClass);
|
|
119
|
+
EntityMetadata.mixin(trgMeta, srcMeta, filter);
|
|
120
|
+
}
|
|
121
|
+
return PickEntityClass;
|
|
122
|
+
}
|
|
123
|
+
Entity.Pick = Pick;
|
|
124
|
+
function Omit(classRef, keys) {
|
|
125
|
+
const OmitEntityClass = class {
|
|
126
|
+
constructor(...args) {
|
|
127
|
+
applyConstructorProperties(this, classRef, args);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
const omitKeys = keys.map(x => x.toLowerCase());
|
|
131
|
+
const filter = (k) => !omitKeys.includes(k.toLowerCase());
|
|
132
|
+
applyMixins(OmitEntityClass, classRef, filter);
|
|
133
|
+
const srcMeta = EntityMetadata.get(classRef);
|
|
134
|
+
if (srcMeta) {
|
|
135
|
+
const trgMeta = EntityMetadata.define(OmitEntityClass);
|
|
136
|
+
EntityMetadata.mixin(trgMeta, srcMeta, filter);
|
|
137
|
+
}
|
|
138
|
+
return OmitEntityClass;
|
|
139
|
+
}
|
|
140
|
+
Entity.Omit = Omit;
|
|
141
|
+
function Union(...bases) {
|
|
142
|
+
const UnionClass = class {
|
|
143
|
+
constructor(...args) {
|
|
144
|
+
for (const c of bases)
|
|
145
|
+
applyConstructorProperties(this, c, args);
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
for (const base of bases) {
|
|
149
|
+
applyMixins(UnionClass, base);
|
|
150
|
+
const srcMeta = EntityMetadata.get(base);
|
|
151
|
+
if (srcMeta) {
|
|
152
|
+
const trgMeta = EntityMetadata.define(UnionClass);
|
|
153
|
+
EntityMetadata.mixin(trgMeta, srcMeta);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return UnionClass;
|
|
157
|
+
}
|
|
158
|
+
Entity.Union = Union;
|
|
159
|
+
})(Entity || (Entity = {}));
|
|
160
|
+
function applyConstructorProperties(target, sourceClass, constructorArgs, isPropertyInherited) {
|
|
161
|
+
try {
|
|
162
|
+
const tempInstance = new sourceClass(...constructorArgs);
|
|
163
|
+
const keys = Object.getOwnPropertyNames(tempInstance);
|
|
164
|
+
for (const key of keys) {
|
|
165
|
+
const srcDesc = Object.getOwnPropertyDescriptor(tempInstance, key);
|
|
166
|
+
const trgDesc = Object.getOwnPropertyDescriptor(target, key);
|
|
167
|
+
if (!srcDesc || trgDesc || (isPropertyInherited && !isPropertyInherited(key)))
|
|
168
|
+
continue;
|
|
169
|
+
Object.defineProperty(target, key, srcDesc);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
//
|
|
174
|
+
}
|
|
175
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { EntityMetadata } from '../model/entity-metadata.js';
|
|
2
|
+
export function BeforeInsert() {
|
|
3
|
+
return (target, propertyKey) => {
|
|
4
|
+
if (typeof propertyKey !== 'string')
|
|
5
|
+
throw new Error('You can define a Column for only string properties');
|
|
6
|
+
const model = EntityMetadata.define(target.constructor);
|
|
7
|
+
const fn = target.constructor.prototype[propertyKey];
|
|
8
|
+
EntityMetadata.addEventListener(model, 'before-insert', fn);
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export function BeforeUpdate() {
|
|
12
|
+
return (target, propertyKey) => {
|
|
13
|
+
if (typeof propertyKey !== 'string')
|
|
14
|
+
throw new Error('You can define a Column for only string properties');
|
|
15
|
+
const model = EntityMetadata.define(target.constructor);
|
|
16
|
+
const fn = target.constructor.prototype[propertyKey];
|
|
17
|
+
EntityMetadata.addEventListener(model, 'before-update', fn);
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export function BeforeDestroy() {
|
|
21
|
+
return (target, propertyKey) => {
|
|
22
|
+
if (typeof propertyKey !== 'string')
|
|
23
|
+
throw new Error('You can define a Column for only string properties');
|
|
24
|
+
const model = EntityMetadata.define(target.constructor);
|
|
25
|
+
const fn = target.constructor.prototype[propertyKey];
|
|
26
|
+
EntityMetadata.addEventListener(model, 'before-destroy', fn);
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export function AfterInsert() {
|
|
30
|
+
return (target, propertyKey) => {
|
|
31
|
+
if (typeof propertyKey !== 'string')
|
|
32
|
+
throw new Error('You can define a Column for only string properties');
|
|
33
|
+
const model = EntityMetadata.define(target.constructor);
|
|
34
|
+
const fn = target.constructor.prototype[propertyKey];
|
|
35
|
+
EntityMetadata.addEventListener(model, 'after-insert', fn);
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export function AfterUpdate() {
|
|
39
|
+
return (target, propertyKey) => {
|
|
40
|
+
if (typeof propertyKey !== 'string')
|
|
41
|
+
throw new Error('You can define a Column for only string properties');
|
|
42
|
+
const model = EntityMetadata.define(target.constructor);
|
|
43
|
+
const fn = target.constructor.prototype[propertyKey];
|
|
44
|
+
EntityMetadata.addEventListener(model, 'after-update', fn);
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export function AfterDestroy() {
|
|
48
|
+
return (target, propertyKey) => {
|
|
49
|
+
if (typeof propertyKey !== 'string')
|
|
50
|
+
throw new Error('You can define a Column for only string properties');
|
|
51
|
+
const model = EntityMetadata.define(target.constructor);
|
|
52
|
+
const fn = target.constructor.prototype[propertyKey];
|
|
53
|
+
EntityMetadata.addEventListener(model, 'after-destroy', fn);
|
|
54
|
+
};
|
|
55
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { TypeThunk } from '../orm.type';
|
|
1
|
+
import { TypeThunk } from '../orm.type.js';
|
|
2
2
|
export declare function ForeignKey(type: TypeThunk, targetKey?: string): PropertyDecorator;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { EntityMetadata } from '../model/entity-metadata.js';
|
|
2
|
+
export function ForeignKey(type, targetKey) {
|
|
3
|
+
return function (target, propertyKey) {
|
|
4
|
+
if (typeof propertyKey !== 'string')
|
|
5
|
+
throw new Error('Symbol properties are not accepted');
|
|
6
|
+
const entity = EntityMetadata.define(target.constructor);
|
|
7
|
+
EntityMetadata.addForeignKey(entity, propertyKey, type, targetKey);
|
|
8
|
+
};
|
|
9
|
+
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { IndexMetadata } from '../model/index-metadata';
|
|
1
|
+
import { IndexMetadata } from '../model/index-metadata.js';
|
|
2
2
|
export declare function Index(fields: string | string[], options?: Omit<IndexMetadata, 'columns'>): ClassDecorator;
|
|
3
3
|
export declare function Index(options?: Omit<IndexMetadata, 'columns'>): PropertyDecorator;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { EntityMetadata } from '../model/entity-metadata.js';
|
|
2
|
+
export function Index(arg0, arg1) {
|
|
3
|
+
return function (target, propertyKey) {
|
|
4
|
+
if (typeof target === 'function') {
|
|
5
|
+
if (!(typeof arg0 === 'string' || Array.isArray(arg0)))
|
|
6
|
+
throw new Error(`You must specify index column(s)`);
|
|
7
|
+
const model = EntityMetadata.define(target);
|
|
8
|
+
return EntityMetadata.addIndex(model, { ...arg1, columns: arg0 });
|
|
9
|
+
}
|
|
10
|
+
if (!target.constructor)
|
|
11
|
+
throw new Error('Property decorators can be used for class properties only');
|
|
12
|
+
if (typeof propertyKey !== 'string')
|
|
13
|
+
throw new Error('Index() decorator can be used for string property keys only');
|
|
14
|
+
const model = EntityMetadata.define(target.constructor);
|
|
15
|
+
EntityMetadata.addIndex(model, { ...arg0, columns: [propertyKey] });
|
|
16
|
+
};
|
|
17
|
+
}
|