@uql/core 3.1.1 → 3.1.2
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/CHANGELOG.md +134 -187
- package/package.json +31 -26
- package/dist/CHANGELOG.md +0 -186
- package/dist/package.json +0 -131
- package/src/@types/index.d.ts +0 -1
- package/src/@types/jest.d.ts +0 -6
- package/src/browser/http/bus.spec.ts +0 -22
- package/src/browser/http/bus.ts +0 -17
- package/src/browser/http/http.spec.ts +0 -70
- package/src/browser/http/http.ts +0 -55
- package/src/browser/http/index.ts +0 -2
- package/src/browser/index.ts +0 -4
- package/src/browser/options.spec.ts +0 -37
- package/src/browser/options.ts +0 -18
- package/src/browser/querier/genericClientRepository.spec.ts +0 -105
- package/src/browser/querier/genericClientRepository.ts +0 -49
- package/src/browser/querier/httpQuerier.ts +0 -82
- package/src/browser/querier/index.ts +0 -3
- package/src/browser/querier/querier.util.spec.ts +0 -35
- package/src/browser/querier/querier.util.ts +0 -18
- package/src/browser/type/clientQuerier.ts +0 -45
- package/src/browser/type/clientQuerierPool.ts +0 -5
- package/src/browser/type/clientRepository.ts +0 -22
- package/src/browser/type/index.ts +0 -4
- package/src/browser/type/request.ts +0 -25
- package/src/dialect/abstractDialect.ts +0 -28
- package/src/dialect/abstractSqlDialect-spec.ts +0 -1309
- package/src/dialect/abstractSqlDialect.ts +0 -805
- package/src/dialect/index.ts +0 -3
- package/src/dialect/namingStrategy.spec.ts +0 -52
- package/src/dialect/queryContext.ts +0 -69
- package/src/entity/decorator/definition.spec.ts +0 -736
- package/src/entity/decorator/definition.ts +0 -265
- package/src/entity/decorator/entity.ts +0 -8
- package/src/entity/decorator/field.ts +0 -9
- package/src/entity/decorator/id.ts +0 -9
- package/src/entity/decorator/index.ts +0 -5
- package/src/entity/decorator/relation.spec.ts +0 -41
- package/src/entity/decorator/relation.ts +0 -34
- package/src/entity/index.ts +0 -1
- package/src/express/@types/express.d.ts +0 -8
- package/src/express/@types/index.d.ts +0 -1
- package/src/express/index.ts +0 -2
- package/src/express/querierMiddleware.ts +0 -217
- package/src/express/query.util.spec.ts +0 -40
- package/src/express/query.util.ts +0 -21
- package/src/index.ts +0 -9
- package/src/maria/index.ts +0 -3
- package/src/maria/mariaDialect.spec.ts +0 -207
- package/src/maria/mariaDialect.ts +0 -42
- package/src/maria/mariaQuerierPool.test.ts +0 -23
- package/src/maria/mariadbQuerier.test.ts +0 -23
- package/src/maria/mariadbQuerier.ts +0 -45
- package/src/maria/mariadbQuerierPool.ts +0 -21
- package/src/migrate/cli.ts +0 -301
- package/src/migrate/generator/index.ts +0 -4
- package/src/migrate/generator/mongoSchemaGenerator.spec.ts +0 -112
- package/src/migrate/generator/mongoSchemaGenerator.ts +0 -115
- package/src/migrate/generator/mysqlSchemaGenerator.spec.ts +0 -34
- package/src/migrate/generator/mysqlSchemaGenerator.ts +0 -92
- package/src/migrate/generator/postgresSchemaGenerator.spec.ts +0 -44
- package/src/migrate/generator/postgresSchemaGenerator.ts +0 -127
- package/src/migrate/generator/sqliteSchemaGenerator.spec.ts +0 -33
- package/src/migrate/generator/sqliteSchemaGenerator.ts +0 -81
- package/src/migrate/index.ts +0 -41
- package/src/migrate/introspection/index.ts +0 -4
- package/src/migrate/introspection/mongoIntrospector.spec.ts +0 -75
- package/src/migrate/introspection/mongoIntrospector.ts +0 -47
- package/src/migrate/introspection/mysqlIntrospector.spec.ts +0 -113
- package/src/migrate/introspection/mysqlIntrospector.ts +0 -278
- package/src/migrate/introspection/postgresIntrospector.spec.ts +0 -112
- package/src/migrate/introspection/postgresIntrospector.ts +0 -329
- package/src/migrate/introspection/sqliteIntrospector.spec.ts +0 -112
- package/src/migrate/introspection/sqliteIntrospector.ts +0 -296
- package/src/migrate/migrator-mongo.test.ts +0 -54
- package/src/migrate/migrator.spec.ts +0 -255
- package/src/migrate/migrator.test.ts +0 -94
- package/src/migrate/migrator.ts +0 -719
- package/src/migrate/namingStrategy.spec.ts +0 -22
- package/src/migrate/schemaGenerator-advanced.spec.ts +0 -138
- package/src/migrate/schemaGenerator.spec.ts +0 -190
- package/src/migrate/schemaGenerator.ts +0 -478
- package/src/migrate/storage/databaseStorage.spec.ts +0 -69
- package/src/migrate/storage/databaseStorage.ts +0 -100
- package/src/migrate/storage/index.ts +0 -2
- package/src/migrate/storage/jsonStorage.ts +0 -58
- package/src/migrate/type.ts +0 -1
- package/src/mongo/index.ts +0 -3
- package/src/mongo/mongoDialect.spec.ts +0 -251
- package/src/mongo/mongoDialect.ts +0 -238
- package/src/mongo/mongodbQuerier.test.ts +0 -45
- package/src/mongo/mongodbQuerier.ts +0 -256
- package/src/mongo/mongodbQuerierPool.test.ts +0 -25
- package/src/mongo/mongodbQuerierPool.ts +0 -24
- package/src/mysql/index.ts +0 -3
- package/src/mysql/mysql2Querier.test.ts +0 -20
- package/src/mysql/mysql2Querier.ts +0 -49
- package/src/mysql/mysql2QuerierPool.test.ts +0 -20
- package/src/mysql/mysql2QuerierPool.ts +0 -21
- package/src/mysql/mysqlDialect.spec.ts +0 -20
- package/src/mysql/mysqlDialect.ts +0 -16
- package/src/namingStrategy/defaultNamingStrategy.ts +0 -18
- package/src/namingStrategy/index.spec.ts +0 -36
- package/src/namingStrategy/index.ts +0 -2
- package/src/namingStrategy/snakeCaseNamingStrategy.ts +0 -15
- package/src/options.spec.ts +0 -41
- package/src/options.ts +0 -18
- package/src/postgres/index.ts +0 -3
- package/src/postgres/manual-types.d.ts +0 -4
- package/src/postgres/pgQuerier.test.ts +0 -25
- package/src/postgres/pgQuerier.ts +0 -45
- package/src/postgres/pgQuerierPool.test.ts +0 -28
- package/src/postgres/pgQuerierPool.ts +0 -21
- package/src/postgres/postgresDialect.spec.ts +0 -428
- package/src/postgres/postgresDialect.ts +0 -144
- package/src/querier/abstractQuerier-test.ts +0 -584
- package/src/querier/abstractQuerier.ts +0 -353
- package/src/querier/abstractQuerierPool-test.ts +0 -20
- package/src/querier/abstractQuerierPool.ts +0 -18
- package/src/querier/abstractSqlQuerier-spec.ts +0 -979
- package/src/querier/abstractSqlQuerier-test.ts +0 -21
- package/src/querier/abstractSqlQuerier.ts +0 -138
- package/src/querier/decorator/index.ts +0 -3
- package/src/querier/decorator/injectQuerier.spec.ts +0 -74
- package/src/querier/decorator/injectQuerier.ts +0 -45
- package/src/querier/decorator/serialized.spec.ts +0 -98
- package/src/querier/decorator/serialized.ts +0 -13
- package/src/querier/decorator/transactional.spec.ts +0 -240
- package/src/querier/decorator/transactional.ts +0 -56
- package/src/querier/index.ts +0 -4
- package/src/repository/genericRepository.spec.ts +0 -111
- package/src/repository/genericRepository.ts +0 -74
- package/src/repository/index.ts +0 -1
- package/src/sqlite/index.ts +0 -3
- package/src/sqlite/manual-types.d.ts +0 -4
- package/src/sqlite/sqliteDialect.spec.ts +0 -155
- package/src/sqlite/sqliteDialect.ts +0 -76
- package/src/sqlite/sqliteQuerier.spec.ts +0 -36
- package/src/sqlite/sqliteQuerier.test.ts +0 -21
- package/src/sqlite/sqliteQuerier.ts +0 -37
- package/src/sqlite/sqliteQuerierPool.test.ts +0 -12
- package/src/sqlite/sqliteQuerierPool.ts +0 -38
- package/src/test/entityMock.ts +0 -375
- package/src/test/index.ts +0 -3
- package/src/test/it.util.ts +0 -69
- package/src/test/spec.util.ts +0 -57
- package/src/type/entity.ts +0 -218
- package/src/type/index.ts +0 -9
- package/src/type/migration.ts +0 -241
- package/src/type/namingStrategy.ts +0 -17
- package/src/type/querier.ts +0 -143
- package/src/type/querierPool.ts +0 -26
- package/src/type/query.ts +0 -506
- package/src/type/repository.ts +0 -142
- package/src/type/universalQuerier.ts +0 -133
- package/src/type/utility.ts +0 -21
- package/src/util/dialect.util-extra.spec.ts +0 -96
- package/src/util/dialect.util.spec.ts +0 -23
- package/src/util/dialect.util.ts +0 -134
- package/src/util/index.ts +0 -5
- package/src/util/object.util.spec.ts +0 -29
- package/src/util/object.util.ts +0 -27
- package/src/util/raw.ts +0 -11
- package/src/util/sql.util-extra.spec.ts +0 -17
- package/src/util/sql.util.spec.ts +0 -208
- package/src/util/sql.util.ts +0 -104
- package/src/util/string.util.spec.ts +0 -46
- package/src/util/string.util.ts +0 -35
- package/tsconfig.build.json +0 -5
- package/tsconfig.json +0 -8
- /package/{dist/README.md → README.md} +0 -0
|
@@ -1,265 +0,0 @@
|
|
|
1
|
-
import 'reflect-metadata';
|
|
2
|
-
import type {
|
|
3
|
-
EntityMeta,
|
|
4
|
-
EntityOptions,
|
|
5
|
-
FieldKey,
|
|
6
|
-
FieldOptions,
|
|
7
|
-
IdKey,
|
|
8
|
-
Key,
|
|
9
|
-
RelationKey,
|
|
10
|
-
RelationKeyMap,
|
|
11
|
-
RelationOptions,
|
|
12
|
-
Type,
|
|
13
|
-
} from '../../type/index.js';
|
|
14
|
-
import { getKeys, hasKeys, lowerFirst, upperFirst } from '../../util/index.js';
|
|
15
|
-
|
|
16
|
-
const holder = globalThis;
|
|
17
|
-
const metaKey = '@uql/core/entity/decorator';
|
|
18
|
-
const metas: Map<Type<unknown>, EntityMeta<any>> = holder[metaKey] ?? new Map();
|
|
19
|
-
holder[metaKey] = metas;
|
|
20
|
-
|
|
21
|
-
export function defineField<E>(entity: Type<E>, key: string, opts: FieldOptions = {}): EntityMeta<E> {
|
|
22
|
-
const meta = ensureMeta(entity);
|
|
23
|
-
if (!opts.type) {
|
|
24
|
-
const type = inferType(entity, key);
|
|
25
|
-
opts = { ...opts, type };
|
|
26
|
-
}
|
|
27
|
-
meta.fields[key] = { ...meta.fields[key], ...{ name: key, ...opts } };
|
|
28
|
-
return meta;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function defineId<E>(entity: Type<E>, key: string, opts: FieldOptions): EntityMeta<E> {
|
|
32
|
-
const meta = ensureMeta(entity);
|
|
33
|
-
const id = getIdKey(meta);
|
|
34
|
-
if (id) {
|
|
35
|
-
console.info(`Overriding ID property for '${entity.name}' from '${id}' to '${key}'`);
|
|
36
|
-
delete meta.fields[id];
|
|
37
|
-
}
|
|
38
|
-
return defineField(entity, key, { ...opts, isId: true });
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function defineRelation<E>(entity: Type<E>, key: string, opts: RelationOptions<E>): EntityMeta<E> {
|
|
42
|
-
if (!opts.entity) {
|
|
43
|
-
const inferredType = inferEntityType(entity, key);
|
|
44
|
-
opts.entity = () => inferredType;
|
|
45
|
-
}
|
|
46
|
-
const meta = ensureMeta(entity);
|
|
47
|
-
meta.relations[key] = { ...meta.relations[key], ...opts };
|
|
48
|
-
return meta;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export function defineEntity<E>(entity: Type<E>, opts: EntityOptions = {}): EntityMeta<E> {
|
|
52
|
-
const meta = ensureMeta(entity);
|
|
53
|
-
|
|
54
|
-
if (!hasKeys(meta.fields)) {
|
|
55
|
-
throw TypeError(`'${entity.name}' must have fields`);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const onDeleteKeys = getKeys(meta.fields).filter((key) => meta.fields[key].onDelete) as FieldKey<E>[];
|
|
59
|
-
|
|
60
|
-
if (onDeleteKeys.length > 1) {
|
|
61
|
-
throw TypeError(`'${entity.name}' must have one field with 'onDelete' as maximum`);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (opts.softDelete) {
|
|
65
|
-
if (!onDeleteKeys.length) {
|
|
66
|
-
throw TypeError(`'${entity.name}' must have one field with 'onDelete' to enable 'softDelete'`);
|
|
67
|
-
}
|
|
68
|
-
meta.softDelete = onDeleteKeys[0];
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
meta.name = opts.name ?? entity.name;
|
|
72
|
-
let proto: FunctionConstructor = Object.getPrototypeOf(entity.prototype);
|
|
73
|
-
|
|
74
|
-
while (proto.constructor !== Object) {
|
|
75
|
-
const parentMeta = ensureMeta(proto.constructor as Type<E>);
|
|
76
|
-
extendMeta(meta, parentMeta);
|
|
77
|
-
proto = Object.getPrototypeOf(proto);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const id = getIdKey(meta);
|
|
81
|
-
if (!id) {
|
|
82
|
-
throw TypeError(`'${entity.name}' must have one field decorated with @Id`);
|
|
83
|
-
}
|
|
84
|
-
meta.id = id;
|
|
85
|
-
|
|
86
|
-
return meta;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export function getEntities(): Type<unknown>[] {
|
|
90
|
-
return [...metas.entries()].reduce((acc, [key, val]) => {
|
|
91
|
-
if (val.id) {
|
|
92
|
-
acc.push(key);
|
|
93
|
-
}
|
|
94
|
-
return acc;
|
|
95
|
-
}, []);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function ensureMeta<E>(entity: Type<E>): EntityMeta<E> {
|
|
99
|
-
let meta = metas.get(entity);
|
|
100
|
-
if (meta) {
|
|
101
|
-
return meta;
|
|
102
|
-
}
|
|
103
|
-
meta = { entity, fields: {}, relations: {} };
|
|
104
|
-
metas.set(entity, meta);
|
|
105
|
-
return meta;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export function getMeta<E>(entity: Type<E>): EntityMeta<E> {
|
|
109
|
-
const meta = metas.get(entity);
|
|
110
|
-
if (!meta) {
|
|
111
|
-
throw TypeError(`'${entity.name}' is not an entity`);
|
|
112
|
-
}
|
|
113
|
-
if (meta.processed) {
|
|
114
|
-
return meta;
|
|
115
|
-
}
|
|
116
|
-
meta.processed = true;
|
|
117
|
-
return fillRelations(meta);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function fillRelations<E>(meta: EntityMeta<E>): EntityMeta<E> {
|
|
121
|
-
for (const relKey in meta.relations) {
|
|
122
|
-
const relOpts = meta.relations[relKey as RelationKey<E>];
|
|
123
|
-
|
|
124
|
-
if (relOpts.references) {
|
|
125
|
-
// references were manually specified
|
|
126
|
-
continue;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
if (relOpts.mappedBy) {
|
|
130
|
-
fillInverseSideRelations(relOpts);
|
|
131
|
-
continue;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const relEntity = relOpts.entity();
|
|
135
|
-
const relMeta = ensureMeta(relEntity);
|
|
136
|
-
|
|
137
|
-
if (relOpts.cardinality === 'mm') {
|
|
138
|
-
const idName = meta.fields[meta.id].name;
|
|
139
|
-
const relIdName = relMeta.fields[relMeta.id].name;
|
|
140
|
-
const source = lowerFirst(meta.name) + upperFirst(idName);
|
|
141
|
-
const target = lowerFirst(relMeta.name) + upperFirst(relIdName);
|
|
142
|
-
relOpts.references = [
|
|
143
|
-
{ local: source, foreign: meta.id },
|
|
144
|
-
{ local: target, foreign: relMeta.id },
|
|
145
|
-
];
|
|
146
|
-
} else {
|
|
147
|
-
relOpts.references = [{ local: `${relKey}Id`, foreign: relMeta.id }];
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
if (relOpts.through) {
|
|
151
|
-
fillThroughRelations(relOpts.through());
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return meta;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
function fillInverseSideRelations<E>(relOpts: RelationOptions<E>): void {
|
|
159
|
-
const relEntity = relOpts.entity();
|
|
160
|
-
const relMeta = getMeta(relEntity);
|
|
161
|
-
relOpts.mappedBy = getMappedByRelationKey(relOpts);
|
|
162
|
-
|
|
163
|
-
if (relMeta.fields[relOpts.mappedBy as FieldKey<E>]) {
|
|
164
|
-
relOpts.references = [{ local: relMeta.id, foreign: relOpts.mappedBy }];
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const mappedByRelation = relMeta.relations[relOpts.mappedBy as RelationKey<E>];
|
|
169
|
-
|
|
170
|
-
if (relOpts.cardinality === 'm1' || relOpts.cardinality === 'mm') {
|
|
171
|
-
relOpts.references = mappedByRelation.references.slice().reverse();
|
|
172
|
-
relOpts.through = mappedByRelation.through;
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
relOpts.references = mappedByRelation.references.map(({ local, foreign }) => ({
|
|
177
|
-
local: foreign,
|
|
178
|
-
foreign: local,
|
|
179
|
-
}));
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
function fillThroughRelations<E>(entity: Type<E>): void {
|
|
183
|
-
const meta = ensureMeta(entity);
|
|
184
|
-
meta.relations = getKeys(meta.fields).reduce((relations, key) => {
|
|
185
|
-
const { reference } = meta.fields[key as FieldKey<E>];
|
|
186
|
-
if (reference) {
|
|
187
|
-
const relEntity = reference();
|
|
188
|
-
const relMeta = ensureMeta(relEntity);
|
|
189
|
-
const relKey = key.slice(0, -relMeta.id.length);
|
|
190
|
-
const relOpts: RelationOptions = {
|
|
191
|
-
entity: reference,
|
|
192
|
-
cardinality: 'm1',
|
|
193
|
-
references: [{ local: key, foreign: relMeta.id }],
|
|
194
|
-
};
|
|
195
|
-
relations[relKey] = relOpts;
|
|
196
|
-
}
|
|
197
|
-
return relations;
|
|
198
|
-
}, {});
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
function getMappedByRelationKey<E>(relOpts: RelationOptions<E>): Key<E> {
|
|
202
|
-
if (typeof relOpts.mappedBy === 'function') {
|
|
203
|
-
const relEntity = relOpts.entity();
|
|
204
|
-
const relMeta = ensureMeta(relEntity);
|
|
205
|
-
const keyMap = getRelationKeyMap(relMeta);
|
|
206
|
-
return relOpts.mappedBy(keyMap);
|
|
207
|
-
}
|
|
208
|
-
return relOpts.mappedBy;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
function getRelationKeyMap<E>(meta: EntityMeta<E>): RelationKeyMap<E> {
|
|
212
|
-
return getKeys(meta.fields)
|
|
213
|
-
.concat(getKeys(meta.relations))
|
|
214
|
-
.reduce(
|
|
215
|
-
(acc, key) => {
|
|
216
|
-
acc[key] = key;
|
|
217
|
-
return acc;
|
|
218
|
-
},
|
|
219
|
-
{} as RelationKeyMap<E>,
|
|
220
|
-
);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
function getIdKey<E>(meta: EntityMeta<E>): IdKey<E> {
|
|
224
|
-
const id = getKeys(meta.fields).find((key) => meta.fields[key]?.isId);
|
|
225
|
-
return id as IdKey<E>;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
function extendMeta<E>(target: EntityMeta<E>, source: EntityMeta<E>): void {
|
|
229
|
-
const sourceFields = { ...source.fields };
|
|
230
|
-
const targetId = getIdKey(target);
|
|
231
|
-
if (targetId) {
|
|
232
|
-
const sourceId = getIdKey(source);
|
|
233
|
-
if (sourceId) {
|
|
234
|
-
delete sourceFields[sourceId];
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
target.fields = { ...sourceFields, ...target.fields };
|
|
238
|
-
target.relations = { ...source.relations, ...target.relations };
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
function inferType<E>(entity: Type<E>, key: string): any {
|
|
242
|
-
return Reflect.getMetadata('design:type', entity.prototype, key);
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
function inferEntityType<E>(entity: Type<E>, key: string): Type<any> {
|
|
246
|
-
const inferredType = inferType(entity, key);
|
|
247
|
-
const isValidType = isValidEntityType(inferredType);
|
|
248
|
-
if (!isValidType) {
|
|
249
|
-
console.log('****', entity, key, inferredType);
|
|
250
|
-
throw TypeError(`'${entity.name}.${key}' type was auto-inferred with invalid type '${inferredType?.name}'`);
|
|
251
|
-
}
|
|
252
|
-
return inferredType;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
export function isValidEntityType(type: unknown): type is Type<unknown> {
|
|
256
|
-
return (
|
|
257
|
-
typeof type === 'function' &&
|
|
258
|
-
type !== Boolean &&
|
|
259
|
-
type !== String &&
|
|
260
|
-
type !== Number &&
|
|
261
|
-
type !== BigInt &&
|
|
262
|
-
type !== Date &&
|
|
263
|
-
type !== Symbol
|
|
264
|
-
);
|
|
265
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { FieldOptions, Type } from '../../type/index.js';
|
|
2
|
-
import { defineField } from './definition.js';
|
|
3
|
-
|
|
4
|
-
export function Field<E>(opts?: FieldOptions) {
|
|
5
|
-
return (target: object, key: string): void => {
|
|
6
|
-
const entity = target.constructor as Type<E>;
|
|
7
|
-
defineField(entity, key, opts);
|
|
8
|
-
};
|
|
9
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { FieldOptions, Type } from '../../type/index.js';
|
|
2
|
-
import { defineId } from './definition.js';
|
|
3
|
-
|
|
4
|
-
export function Id<E>(opts?: Omit<FieldOptions, 'isId'>) {
|
|
5
|
-
return (target: object, key: string): void => {
|
|
6
|
-
const entity = target.constructor as Type<E>;
|
|
7
|
-
defineId(entity, key, opts);
|
|
8
|
-
};
|
|
9
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { expect, it } from 'bun:test';
|
|
2
|
-
import { ManyToOne } from './relation.js';
|
|
3
|
-
|
|
4
|
-
it('invalid auto-inferred type', () => {
|
|
5
|
-
expect(() => {
|
|
6
|
-
class SomeEntity {
|
|
7
|
-
@ManyToOne()
|
|
8
|
-
idTwo: number;
|
|
9
|
-
}
|
|
10
|
-
}).toThrow(`'SomeEntity.idTwo' type was auto-inferred with invalid type 'Number'`);
|
|
11
|
-
expect(() => {
|
|
12
|
-
class SomeEntity {
|
|
13
|
-
@ManyToOne()
|
|
14
|
-
idTwo: string;
|
|
15
|
-
}
|
|
16
|
-
}).toThrow(`'SomeEntity.idTwo' type was auto-inferred with invalid type 'String'`);
|
|
17
|
-
expect(() => {
|
|
18
|
-
class SomeEntity {
|
|
19
|
-
@ManyToOne()
|
|
20
|
-
idTwo: boolean;
|
|
21
|
-
}
|
|
22
|
-
}).toThrow(`'SomeEntity.idTwo' type was auto-inferred with invalid type 'Boolean'`);
|
|
23
|
-
expect(() => {
|
|
24
|
-
class SomeEntity {
|
|
25
|
-
@ManyToOne()
|
|
26
|
-
idTwo: object;
|
|
27
|
-
}
|
|
28
|
-
}).not.toThrow();
|
|
29
|
-
expect(() => {
|
|
30
|
-
class SomeEntity {
|
|
31
|
-
@ManyToOne()
|
|
32
|
-
idTwo: null;
|
|
33
|
-
}
|
|
34
|
-
}).toThrow(`'SomeEntity.idTwo' type was auto-inferred with invalid type 'undefined'`);
|
|
35
|
-
expect(() => {
|
|
36
|
-
class SomeEntity {
|
|
37
|
-
@ManyToOne()
|
|
38
|
-
idTwo: undefined;
|
|
39
|
-
}
|
|
40
|
-
}).toThrow(`'SomeEntity.idTwo' type was auto-inferred with invalid type 'undefined'`);
|
|
41
|
-
});
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
RelationManyToManyOptions,
|
|
3
|
-
RelationManyToOneOptions,
|
|
4
|
-
RelationOneToManyOptions,
|
|
5
|
-
RelationOneToOneOptions,
|
|
6
|
-
RelationOptions,
|
|
7
|
-
Type,
|
|
8
|
-
} from '../../type/index.js';
|
|
9
|
-
import { defineRelation } from './definition.js';
|
|
10
|
-
|
|
11
|
-
function Relation<E>(opts: RelationOptions<E>) {
|
|
12
|
-
return (target: object, key: string) => {
|
|
13
|
-
const entity = target.constructor as Type<E>;
|
|
14
|
-
defineRelation(entity, key, opts);
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
type RelationReturn = ReturnType<typeof Relation>;
|
|
19
|
-
|
|
20
|
-
export function OneToOne<E>(opts?: RelationOneToOneOptions<E>): RelationReturn {
|
|
21
|
-
return Relation({ cardinality: '11', ...opts });
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function ManyToOne<E>(opts?: RelationManyToOneOptions<E>): RelationReturn {
|
|
25
|
-
return Relation({ cardinality: 'm1', ...opts });
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function OneToMany<E>(opts: RelationOneToManyOptions<E>): RelationReturn {
|
|
29
|
-
return Relation({ cardinality: '1m', ...opts });
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function ManyToMany<E>(opts: RelationManyToManyOptions<E>): RelationReturn {
|
|
33
|
-
return Relation({ cardinality: 'mm', ...opts });
|
|
34
|
-
}
|
package/src/entity/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './decorator/index.js';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import './express';
|
package/src/express/index.ts
DELETED
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
import { Router as expressRouter, type Request, type Router } from 'express';
|
|
2
|
-
import { getEntities, getMeta } from '../entity/index.js';
|
|
3
|
-
import { getQuerier } from '../index.js';
|
|
4
|
-
import type { EntityMeta, IdValue, Query, Type } from '../type/index.js';
|
|
5
|
-
import { kebabCase } from '../util/index.js';
|
|
6
|
-
import { parseQuery } from './query.util.js';
|
|
7
|
-
|
|
8
|
-
export function querierMiddleware(opts: MiddlewareOptions = {}): Router {
|
|
9
|
-
const router = expressRouter();
|
|
10
|
-
|
|
11
|
-
const { include, exclude, ...extra } = opts;
|
|
12
|
-
|
|
13
|
-
let entities = include ?? getEntities();
|
|
14
|
-
|
|
15
|
-
if (exclude) {
|
|
16
|
-
entities = entities.filter((entity) => !opts.exclude.includes(entity));
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
if (!entities.length) {
|
|
20
|
-
throw new TypeError('no entities for the uql express middleware');
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
for (const entity of entities) {
|
|
24
|
-
const path = kebabCase(entity.name);
|
|
25
|
-
const subRouter = buildQuerierRouter(entity, extra);
|
|
26
|
-
router.use('/' + path, subRouter);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return router;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function buildQuerierRouter<E>(entity: Type<E>, opts: ExtraOptions): Router {
|
|
33
|
-
const meta = getMeta(entity);
|
|
34
|
-
const router = expressRouter();
|
|
35
|
-
|
|
36
|
-
router.use((req, res, next) => {
|
|
37
|
-
pre(req, meta, opts);
|
|
38
|
-
next();
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
router.get('/one', async (req, res, next) => {
|
|
42
|
-
const q = req.query as Query<E>;
|
|
43
|
-
const querier = await getQuerier();
|
|
44
|
-
try {
|
|
45
|
-
const data = await querier.findOne(entity, q);
|
|
46
|
-
res.json({ data, count: data ? 1 : 0 });
|
|
47
|
-
} catch (err: any) {
|
|
48
|
-
next(err);
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
router.get('/:id', async (req, res, next) => {
|
|
53
|
-
const id = req.params.id as IdValue<E>;
|
|
54
|
-
const q = req.query as Query<E>;
|
|
55
|
-
q.$where ??= {};
|
|
56
|
-
if (Array.isArray(q.$where)) {
|
|
57
|
-
q.$where.push(id);
|
|
58
|
-
} else {
|
|
59
|
-
q.$where[meta.id as string] = id;
|
|
60
|
-
}
|
|
61
|
-
const querier = await getQuerier();
|
|
62
|
-
try {
|
|
63
|
-
const data = await querier.findOne(entity, q);
|
|
64
|
-
res.json({ data, count: data ? 1 : 0 });
|
|
65
|
-
} catch (err: any) {
|
|
66
|
-
next(err);
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
router.get('/', async (req, res, next) => {
|
|
71
|
-
const q = req.query as Query<E>;
|
|
72
|
-
const querier = await getQuerier();
|
|
73
|
-
try {
|
|
74
|
-
const findManyPromise = querier.findMany(entity, q);
|
|
75
|
-
const countPromise = req.query.count ? querier.count(entity, q) : undefined;
|
|
76
|
-
const [data, count] = await Promise.all([findManyPromise, countPromise]);
|
|
77
|
-
res.json({ data, count });
|
|
78
|
-
} catch (err: any) {
|
|
79
|
-
next(err);
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
router.get('/count', async (req, res, next) => {
|
|
84
|
-
const q = req.query as Query<E>;
|
|
85
|
-
const querier = await getQuerier();
|
|
86
|
-
try {
|
|
87
|
-
const count = await querier.count(entity, q);
|
|
88
|
-
res.json({ data: count, count });
|
|
89
|
-
} catch (err: any) {
|
|
90
|
-
next(err);
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
router.post('/', async (req, res, next) => {
|
|
95
|
-
const payload = req.body as E;
|
|
96
|
-
const querier = await getQuerier();
|
|
97
|
-
try {
|
|
98
|
-
await querier.beginTransaction();
|
|
99
|
-
const id = await querier.insertOne(entity, payload);
|
|
100
|
-
await querier.commitTransaction();
|
|
101
|
-
res.json({ data: id, count: id ? 1 : 0 });
|
|
102
|
-
} catch (err: any) {
|
|
103
|
-
await querier.rollbackTransaction();
|
|
104
|
-
next(err);
|
|
105
|
-
} finally {
|
|
106
|
-
await querier.release();
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
router.patch('/:id', async (req, res, next) => {
|
|
111
|
-
const payload = req.body as E;
|
|
112
|
-
const id = req.params.id as IdValue<E>;
|
|
113
|
-
const q = req.query as Query<E>;
|
|
114
|
-
q.$where ??= {};
|
|
115
|
-
if (Array.isArray(q.$where)) {
|
|
116
|
-
q.$where.push(id);
|
|
117
|
-
} else {
|
|
118
|
-
q.$where[meta.id as string] = id;
|
|
119
|
-
}
|
|
120
|
-
const querier = await getQuerier();
|
|
121
|
-
try {
|
|
122
|
-
await querier.beginTransaction();
|
|
123
|
-
const count = await querier.updateMany(entity, q, payload);
|
|
124
|
-
await querier.commitTransaction();
|
|
125
|
-
res.json({ data: req.params.id, count });
|
|
126
|
-
} catch (err: any) {
|
|
127
|
-
await querier.rollbackTransaction();
|
|
128
|
-
next(err);
|
|
129
|
-
} finally {
|
|
130
|
-
await querier.release();
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
router.delete('/:id', async (req, res, next) => {
|
|
135
|
-
const id = req.params.id as IdValue<E>;
|
|
136
|
-
const q = req.query as Query<E>;
|
|
137
|
-
q.$where ??= {};
|
|
138
|
-
if (Array.isArray(q.$where)) {
|
|
139
|
-
q.$where.push(id);
|
|
140
|
-
} else {
|
|
141
|
-
q.$where[meta.id as string] = id;
|
|
142
|
-
}
|
|
143
|
-
const querier = await getQuerier();
|
|
144
|
-
try {
|
|
145
|
-
await querier.beginTransaction();
|
|
146
|
-
const count = await querier.deleteMany(entity, q, {
|
|
147
|
-
softDelete: !!req.query.softDelete,
|
|
148
|
-
});
|
|
149
|
-
await querier.commitTransaction();
|
|
150
|
-
res.json({ data: req.params.id, count });
|
|
151
|
-
} catch (err: any) {
|
|
152
|
-
await querier.rollbackTransaction();
|
|
153
|
-
next(err);
|
|
154
|
-
} finally {
|
|
155
|
-
await querier.release();
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
router.delete('/', async (req, res, next) => {
|
|
160
|
-
const q = req.query as Query<E>;
|
|
161
|
-
const querier = await getQuerier();
|
|
162
|
-
let ids: IdValue<E>[] = [];
|
|
163
|
-
let count = 0;
|
|
164
|
-
try {
|
|
165
|
-
await querier.beginTransaction();
|
|
166
|
-
const founds = await querier.findMany(entity, q);
|
|
167
|
-
if (founds.length) {
|
|
168
|
-
ids = founds.map((found) => found[meta.id]);
|
|
169
|
-
count = await querier.deleteMany(entity, { $where: ids }, { softDelete: !!req.query.softDelete });
|
|
170
|
-
}
|
|
171
|
-
await querier.commitTransaction();
|
|
172
|
-
res.json({ data: ids, count });
|
|
173
|
-
} catch (err: any) {
|
|
174
|
-
await querier.rollbackTransaction();
|
|
175
|
-
next(err);
|
|
176
|
-
} finally {
|
|
177
|
-
await querier.release();
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
return router;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
function pre(req: Request, meta: EntityMeta<any>, extra: ExtraOptions) {
|
|
185
|
-
const method = req.method;
|
|
186
|
-
parseQuery(req);
|
|
187
|
-
extra.pre?.(req, meta);
|
|
188
|
-
if (method === 'POST' || method === 'PATCH' || method === 'PUT') {
|
|
189
|
-
extra.preSave?.(req, meta);
|
|
190
|
-
} else if (method === 'GET' || method === 'DELETE') {
|
|
191
|
-
extra.preFilter?.(req, meta);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
type ExtraOptions = {
|
|
196
|
-
/**
|
|
197
|
-
* Allow augment any kind of request before it runs
|
|
198
|
-
*/
|
|
199
|
-
readonly pre?: Pre;
|
|
200
|
-
/**
|
|
201
|
-
* Allow augment a saving request (POST, PATCH, PUT) before it runs
|
|
202
|
-
*/
|
|
203
|
-
readonly preSave?: PreSave;
|
|
204
|
-
/**
|
|
205
|
-
* Allow augment a filtering request (GET, PUT, DELETE) before it runs
|
|
206
|
-
*/
|
|
207
|
-
readonly preFilter?: PreFilter;
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
type MiddlewareOptions = {
|
|
211
|
-
readonly include?: Type<unknown>[];
|
|
212
|
-
readonly exclude?: Type<unknown>[];
|
|
213
|
-
} & ExtraOptions;
|
|
214
|
-
|
|
215
|
-
type Pre = <E = unknown>(req: Request, meta: EntityMeta<E>) => void;
|
|
216
|
-
type PreSave = <E = unknown>(req: Request, meta: EntityMeta<E>) => void;
|
|
217
|
-
type PreFilter = <E = unknown>(req: Request, meta: EntityMeta<E>) => void;
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { expect, it } from 'bun:test';
|
|
2
|
-
import type { Request } from 'express';
|
|
3
|
-
import type { Item } from '../test/index.js';
|
|
4
|
-
import type { Query, QueryStringified } from '../type/index.js';
|
|
5
|
-
import { parseQuery } from './query.util.js';
|
|
6
|
-
|
|
7
|
-
it('parseQuery -- empty', () => {
|
|
8
|
-
const req1 = {} as Request;
|
|
9
|
-
parseQuery(req1);
|
|
10
|
-
expect(req1).toMatchObject({ query: { $where: {} } });
|
|
11
|
-
const req2 = { query: undefined as object } as Request;
|
|
12
|
-
parseQuery(req2);
|
|
13
|
-
expect(req2).toMatchObject({ query: { $where: {} } });
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it('parseQuery stringified', () => {
|
|
17
|
-
const queryStr = {
|
|
18
|
-
$select:
|
|
19
|
-
'{ "id": true, "name": true, "measureUnit": {"$select":{"id":true, "name":true}}, "tax": {"$select":{"id":true, "name":true}} }',
|
|
20
|
-
$where: '{ "name": "lorem", "companyId": 40 }',
|
|
21
|
-
$sort: '{ "name": -1, "companyId": 1 }',
|
|
22
|
-
$skip: '200',
|
|
23
|
-
$limit: '100',
|
|
24
|
-
} satisfies QueryStringified;
|
|
25
|
-
const query = {
|
|
26
|
-
$select: {
|
|
27
|
-
id: true,
|
|
28
|
-
name: true,
|
|
29
|
-
measureUnit: { $select: { id: true, name: true } },
|
|
30
|
-
tax: { $select: { id: true, name: true } },
|
|
31
|
-
},
|
|
32
|
-
$where: { name: 'lorem', companyId: 40 },
|
|
33
|
-
$sort: { name: -1, companyId: 1 },
|
|
34
|
-
$skip: 200,
|
|
35
|
-
$limit: 100,
|
|
36
|
-
} satisfies Query<Item>;
|
|
37
|
-
const req = { query: queryStr } as unknown as Request;
|
|
38
|
-
parseQuery(req);
|
|
39
|
-
expect(req).toMatchObject({ query });
|
|
40
|
-
});
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type { Request } from 'express';
|
|
2
|
-
import type { Query, QueryStringified } from '../type/index.js';
|
|
3
|
-
|
|
4
|
-
export function parseQuery(req: Request) {
|
|
5
|
-
req.query ??= {};
|
|
6
|
-
const qmsSrc: QueryStringified = req.query;
|
|
7
|
-
const qm = qmsSrc as unknown as Query<unknown>;
|
|
8
|
-
if (qmsSrc.$select) {
|
|
9
|
-
qm.$select = JSON.parse(qmsSrc.$select);
|
|
10
|
-
}
|
|
11
|
-
qm.$where = qmsSrc.$where ? JSON.parse(qmsSrc.$where) : {};
|
|
12
|
-
if (qmsSrc.$sort) {
|
|
13
|
-
qm.$sort = JSON.parse(qmsSrc.$sort);
|
|
14
|
-
}
|
|
15
|
-
if (qmsSrc.$skip) {
|
|
16
|
-
qm.$skip = Number(qmsSrc.$skip);
|
|
17
|
-
}
|
|
18
|
-
if (qmsSrc.$limit) {
|
|
19
|
-
qm.$limit = Number(qmsSrc.$limit);
|
|
20
|
-
}
|
|
21
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export * from './dialect/index.js';
|
|
2
|
-
export * from './entity/index.js';
|
|
3
|
-
export * from './migrate/index.js';
|
|
4
|
-
export * from './namingStrategy/index.js';
|
|
5
|
-
export * from './options.js';
|
|
6
|
-
export * from './querier/index.js';
|
|
7
|
-
export * from './repository/index.js';
|
|
8
|
-
export * from './type/index.js';
|
|
9
|
-
export * from './util/index.js';
|
package/src/maria/index.ts
DELETED