@uql/core 3.1.0 → 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 -176
- package/README.md +413 -0
- package/package.json +31 -26
- 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
|
@@ -1,256 +0,0 @@
|
|
|
1
|
-
import type { ClientSession, Document, MongoClient, OptionalUnlessRequiredId, UpdateFilter } from 'mongodb';
|
|
2
|
-
import { getMeta } from '../entity/index.js';
|
|
3
|
-
import { AbstractQuerier, Serialized } from '../querier/index.js';
|
|
4
|
-
import type {
|
|
5
|
-
ExtraOptions,
|
|
6
|
-
IdValue,
|
|
7
|
-
Query,
|
|
8
|
-
QueryConflictPaths,
|
|
9
|
-
QueryOptions,
|
|
10
|
-
QuerySearch,
|
|
11
|
-
QueryWhere,
|
|
12
|
-
Type,
|
|
13
|
-
} from '../type/index.js';
|
|
14
|
-
import { clone, getFieldCallbackValue, getKeys, hasKeys, isSelectingRelations } from '../util/index.js';
|
|
15
|
-
|
|
16
|
-
import type { MongoDialect } from './mongoDialect.js';
|
|
17
|
-
|
|
18
|
-
export class MongodbQuerier extends AbstractQuerier {
|
|
19
|
-
private session: ClientSession;
|
|
20
|
-
|
|
21
|
-
constructor(
|
|
22
|
-
readonly dialect: MongoDialect,
|
|
23
|
-
readonly conn: MongoClient,
|
|
24
|
-
readonly extra?: ExtraOptions,
|
|
25
|
-
) {
|
|
26
|
-
super();
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
@Serialized()
|
|
30
|
-
private async execute<T>(task: (session: ClientSession) => Promise<T>): Promise<T> {
|
|
31
|
-
return task(this.session);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
override async findMany<E extends Document>(entity: Type<E>, q: Query<E>) {
|
|
35
|
-
const meta = getMeta(entity);
|
|
36
|
-
|
|
37
|
-
let documents: E[];
|
|
38
|
-
const hasSelectedRelations = isSelectingRelations(meta, q.$select);
|
|
39
|
-
|
|
40
|
-
if (hasSelectedRelations) {
|
|
41
|
-
const pipeline = this.dialect.aggregationPipeline(entity, q);
|
|
42
|
-
this.extra?.logger('findMany', entity.name, JSON.stringify(pipeline, null, 2));
|
|
43
|
-
documents = await this.execute((session) =>
|
|
44
|
-
this.collection(entity).aggregate<E>(pipeline, { session }).toArray(),
|
|
45
|
-
);
|
|
46
|
-
documents = this.dialect.normalizeIds(meta, documents) as E[];
|
|
47
|
-
await this.fillToManyRelations(entity, documents, q.$select);
|
|
48
|
-
} else {
|
|
49
|
-
const cursor = this.collection(entity).find<E>({}, { session: this.session });
|
|
50
|
-
|
|
51
|
-
const filter = this.dialect.where(entity, q.$where);
|
|
52
|
-
if (hasKeys(filter)) {
|
|
53
|
-
cursor.filter(filter);
|
|
54
|
-
}
|
|
55
|
-
const select = this.dialect.select(entity, q.$select);
|
|
56
|
-
if (hasKeys(select)) {
|
|
57
|
-
cursor.project(select);
|
|
58
|
-
}
|
|
59
|
-
const sort = this.dialect.sort(entity, q.$sort);
|
|
60
|
-
if (hasKeys(sort)) {
|
|
61
|
-
cursor.sort(sort);
|
|
62
|
-
}
|
|
63
|
-
if (q.$skip) {
|
|
64
|
-
cursor.skip(q.$skip);
|
|
65
|
-
}
|
|
66
|
-
if (q.$limit) {
|
|
67
|
-
cursor.limit(q.$limit);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
this.extra?.logger?.('findMany', entity.name, q);
|
|
71
|
-
|
|
72
|
-
documents = await this.execute(() => cursor.toArray() as Promise<E[]>);
|
|
73
|
-
documents = this.dialect.normalizeIds(meta, documents) as E[];
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return documents;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
override count<E extends Document>(entity: Type<E>, qm: QuerySearch<E> = {}) {
|
|
80
|
-
const filter = this.dialect.where(entity, qm.$where);
|
|
81
|
-
this.extra?.logger?.('count', entity.name, filter);
|
|
82
|
-
return this.execute((session) =>
|
|
83
|
-
this.collection(entity).countDocuments(filter, {
|
|
84
|
-
session,
|
|
85
|
-
}),
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
override async insertMany<E extends Document>(entity: Type<E>, payloads: E[]) {
|
|
90
|
-
if (!payloads?.length) {
|
|
91
|
-
return [];
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
payloads = clone(payloads);
|
|
95
|
-
|
|
96
|
-
const meta = getMeta(entity);
|
|
97
|
-
const persistables = this.dialect.getPersistables(meta, payloads, 'onInsert') as OptionalUnlessRequiredId<E>[];
|
|
98
|
-
|
|
99
|
-
this.extra?.logger?.('insertMany', entity.name, persistables);
|
|
100
|
-
|
|
101
|
-
const { insertedIds } = await this.execute((session) =>
|
|
102
|
-
this.collection(entity).insertMany(persistables, { session }),
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
const ids = Object.values(insertedIds) as unknown as IdValue<E>[];
|
|
106
|
-
|
|
107
|
-
for (const [index, it] of payloads.entries()) {
|
|
108
|
-
it[meta.id] = ids[index];
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
await this.insertRelations(entity, payloads);
|
|
112
|
-
|
|
113
|
-
return ids;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
override async updateMany<E extends Document>(entity: Type<E>, qm: QuerySearch<E>, payload: E) {
|
|
117
|
-
payload = clone(payload);
|
|
118
|
-
const meta = getMeta(entity);
|
|
119
|
-
const persistable = this.dialect.getPersistable(meta, payload, 'onUpdate');
|
|
120
|
-
const where = this.dialect.where(entity, qm.$where);
|
|
121
|
-
const update = { $set: persistable } satisfies UpdateFilter<E>;
|
|
122
|
-
|
|
123
|
-
this.extra?.logger?.('updateMany', entity.name, where, update);
|
|
124
|
-
|
|
125
|
-
const { matchedCount } = await this.execute((session) =>
|
|
126
|
-
this.collection(entity).updateMany(where, update, {
|
|
127
|
-
session,
|
|
128
|
-
}),
|
|
129
|
-
);
|
|
130
|
-
|
|
131
|
-
await this.updateRelations(entity, qm, payload);
|
|
132
|
-
|
|
133
|
-
return matchedCount;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
override async upsertOne<E extends Document>(entity: Type<E>, conflictPaths: QueryConflictPaths<E>, payload: E) {
|
|
137
|
-
payload = clone(payload);
|
|
138
|
-
|
|
139
|
-
const meta = getMeta(entity);
|
|
140
|
-
const persistable = this.dialect.getPersistable(meta, payload, 'onInsert') as OptionalUnlessRequiredId<E>;
|
|
141
|
-
|
|
142
|
-
this.extra?.logger?.('upsertOne', entity.name, persistable);
|
|
143
|
-
|
|
144
|
-
const where = getKeys(conflictPaths).reduce(
|
|
145
|
-
(acc, key) => {
|
|
146
|
-
acc[key] = payload[key];
|
|
147
|
-
return acc;
|
|
148
|
-
},
|
|
149
|
-
{} as QueryWhere<E>,
|
|
150
|
-
);
|
|
151
|
-
|
|
152
|
-
const filter = this.dialect.where(entity, where);
|
|
153
|
-
|
|
154
|
-
const update = { $set: persistable } as UpdateFilter<E>;
|
|
155
|
-
|
|
156
|
-
const res = await this.execute((session) =>
|
|
157
|
-
this.collection(entity).findOneAndUpdate(filter, update, {
|
|
158
|
-
upsert: true,
|
|
159
|
-
session,
|
|
160
|
-
}),
|
|
161
|
-
);
|
|
162
|
-
|
|
163
|
-
const firstId = res?._id as unknown as string;
|
|
164
|
-
|
|
165
|
-
return { firstId, changes: firstId ? 1 : 0 };
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
override async deleteMany<E extends Document>(entity: Type<E>, qm: QuerySearch<E>, opts: QueryOptions = {}) {
|
|
169
|
-
const meta = getMeta(entity);
|
|
170
|
-
const where = this.dialect.where(entity, qm.$where);
|
|
171
|
-
this.extra?.logger?.('deleteMany', entity.name, where, opts);
|
|
172
|
-
const founds = await this.execute((session) =>
|
|
173
|
-
this.collection(entity)
|
|
174
|
-
.find(where, {
|
|
175
|
-
projection: { _id: true },
|
|
176
|
-
session,
|
|
177
|
-
})
|
|
178
|
-
.toArray(),
|
|
179
|
-
);
|
|
180
|
-
if (!founds.length) {
|
|
181
|
-
return 0;
|
|
182
|
-
}
|
|
183
|
-
const ids = this.dialect.normalizeIds(meta, founds as unknown as E[]).map((found) => found[meta.id]);
|
|
184
|
-
let changes: number;
|
|
185
|
-
if (meta.softDelete && !opts.softDelete) {
|
|
186
|
-
const onDeleteValue = getFieldCallbackValue(meta.fields[meta.softDelete].onDelete);
|
|
187
|
-
const updateResult = await this.execute((session) =>
|
|
188
|
-
this.collection(entity).updateMany(
|
|
189
|
-
{ _id: { $in: ids } },
|
|
190
|
-
{ $set: { [meta.softDelete]: onDeleteValue } } as UpdateFilter<E>,
|
|
191
|
-
{
|
|
192
|
-
session,
|
|
193
|
-
},
|
|
194
|
-
),
|
|
195
|
-
);
|
|
196
|
-
changes = updateResult.matchedCount;
|
|
197
|
-
} else {
|
|
198
|
-
const deleteResult = await this.execute((session) =>
|
|
199
|
-
this.collection(entity).deleteMany({ _id: { $in: ids } }, { session }),
|
|
200
|
-
);
|
|
201
|
-
changes = deleteResult.deletedCount;
|
|
202
|
-
}
|
|
203
|
-
await this.deleteRelations(entity, ids, opts);
|
|
204
|
-
return changes;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
override get hasOpenTransaction() {
|
|
208
|
-
return this.session?.inTransaction();
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
collection<E extends Document>(entity: Type<E>) {
|
|
212
|
-
const { name } = getMeta(entity);
|
|
213
|
-
return this.db.collection<E>(name);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
get db() {
|
|
217
|
-
return this.conn.db();
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
@Serialized()
|
|
221
|
-
override async beginTransaction() {
|
|
222
|
-
if (this.hasOpenTransaction) {
|
|
223
|
-
throw TypeError('pending transaction');
|
|
224
|
-
}
|
|
225
|
-
this.extra?.logger?.('beginTransaction');
|
|
226
|
-
await this.session?.endSession();
|
|
227
|
-
this.session = this.conn.startSession();
|
|
228
|
-
this.session.startTransaction();
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
@Serialized()
|
|
232
|
-
override async commitTransaction() {
|
|
233
|
-
if (!this.hasOpenTransaction) {
|
|
234
|
-
throw TypeError('not a pending transaction');
|
|
235
|
-
}
|
|
236
|
-
this.extra?.logger?.('commitTransaction');
|
|
237
|
-
await this.session.commitTransaction();
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
@Serialized()
|
|
241
|
-
override async rollbackTransaction() {
|
|
242
|
-
if (!this.hasOpenTransaction) {
|
|
243
|
-
throw TypeError('not a pending transaction');
|
|
244
|
-
}
|
|
245
|
-
this.extra?.logger?.('rollbackTransaction');
|
|
246
|
-
await this.session.abortTransaction();
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
override async internalRelease() {
|
|
250
|
-
if (this.hasOpenTransaction) {
|
|
251
|
-
throw TypeError('pending transaction');
|
|
252
|
-
}
|
|
253
|
-
await this.session?.endSession();
|
|
254
|
-
this.session = undefined;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { MongoMemoryReplSet } from 'mongodb-memory-server';
|
|
2
|
-
import { AbstractQuerierPoolIt } from '../querier/abstractQuerierPool-test.js';
|
|
3
|
-
import { createSpec } from '../test/index.js';
|
|
4
|
-
import type { MongodbQuerier } from './mongodbQuerier.js';
|
|
5
|
-
import { MongodbQuerierPool } from './mongodbQuerierPool.js';
|
|
6
|
-
|
|
7
|
-
class MongodbQuerierPoolIt extends AbstractQuerierPoolIt<MongodbQuerier> {
|
|
8
|
-
static replSet: MongoMemoryReplSet;
|
|
9
|
-
|
|
10
|
-
async beforeAll() {
|
|
11
|
-
MongodbQuerierPoolIt.replSet = await MongoMemoryReplSet.create({
|
|
12
|
-
replSet: { count: 1, storageEngine: 'wiredTiger' },
|
|
13
|
-
});
|
|
14
|
-
const uri = MongodbQuerierPoolIt.replSet.getUri();
|
|
15
|
-
this.pool = new MongodbQuerierPool(uri);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
override async afterAll() {
|
|
19
|
-
await super.afterAll();
|
|
20
|
-
await this.pool.end();
|
|
21
|
-
await MongodbQuerierPoolIt.replSet.stop();
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
createSpec(new MongodbQuerierPoolIt(new MongodbQuerierPool('mongodb://127.0.0.1:27017/test')));
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { MongoClient, type MongoClientOptions } from 'mongodb';
|
|
2
|
-
import { AbstractQuerierPool } from '../querier/index.js';
|
|
3
|
-
import type { ExtraOptions } from '../type/index.js';
|
|
4
|
-
import { MongoDialect } from './mongoDialect.js';
|
|
5
|
-
import { MongodbQuerier } from './mongodbQuerier.js';
|
|
6
|
-
|
|
7
|
-
export class MongodbQuerierPool extends AbstractQuerierPool<MongodbQuerier> {
|
|
8
|
-
private readonly client: MongoClient;
|
|
9
|
-
|
|
10
|
-
constructor(uri: string, opts?: MongoClientOptions, extra?: ExtraOptions) {
|
|
11
|
-
super('mongodb', extra);
|
|
12
|
-
this.client = new MongoClient(uri, opts);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
async getQuerier() {
|
|
16
|
-
const conn = await this.client.connect();
|
|
17
|
-
const querier = new MongodbQuerier(new MongoDialect(), conn, this.extra);
|
|
18
|
-
return querier;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async end() {
|
|
22
|
-
await this.client.close();
|
|
23
|
-
}
|
|
24
|
-
}
|
package/src/mysql/index.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { AbstractSqlQuerierIt } from '../querier/abstractSqlQuerier-test.js';
|
|
2
|
-
import { createSpec } from '../test/index.js';
|
|
3
|
-
import { MySql2QuerierPool } from './mysql2QuerierPool.js';
|
|
4
|
-
|
|
5
|
-
export class MySql2QuerierIt extends AbstractSqlQuerierIt {
|
|
6
|
-
constructor() {
|
|
7
|
-
super(
|
|
8
|
-
new MySql2QuerierPool({
|
|
9
|
-
host: '0.0.0.0',
|
|
10
|
-
port: 3316,
|
|
11
|
-
user: 'test',
|
|
12
|
-
password: 'test',
|
|
13
|
-
database: 'test',
|
|
14
|
-
}),
|
|
15
|
-
'INT AUTO_INCREMENT PRIMARY KEY',
|
|
16
|
-
);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
createSpec(new MySql2QuerierIt());
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import type { PoolConnection } from 'mysql2/promise';
|
|
2
|
-
import { AbstractSqlQuerier } from '../querier/index.js';
|
|
3
|
-
import type { ExtraOptions, QueryUpdateResult } from '../type/index.js';
|
|
4
|
-
import { MySqlDialect } from './mysqlDialect.js';
|
|
5
|
-
|
|
6
|
-
export class MySql2Querier extends AbstractSqlQuerier {
|
|
7
|
-
conn: PoolConnection;
|
|
8
|
-
|
|
9
|
-
constructor(
|
|
10
|
-
readonly connect: () => Promise<PoolConnection>,
|
|
11
|
-
readonly extra?: ExtraOptions,
|
|
12
|
-
) {
|
|
13
|
-
super(new MySqlDialect(extra?.namingStrategy));
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
override async internalAll<T>(query: string, values?: unknown[]) {
|
|
17
|
-
this.extra?.logger?.(query, values);
|
|
18
|
-
await this.lazyConnect();
|
|
19
|
-
const [res] = await this.conn.query(query, values);
|
|
20
|
-
return res as T[];
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
override async internalRun(query: string, values?: unknown[]) {
|
|
24
|
-
this.extra?.logger?.(query, values);
|
|
25
|
-
await this.lazyConnect();
|
|
26
|
-
const [res]: any = await this.conn.query(query, values);
|
|
27
|
-
const ids = res.insertId
|
|
28
|
-
? Array(res.affectedRows)
|
|
29
|
-
.fill(res.insertId)
|
|
30
|
-
.map((i, index) => i + index)
|
|
31
|
-
: [];
|
|
32
|
-
return { changes: res.affectedRows, ids, firstId: ids[0] } satisfies QueryUpdateResult;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async lazyConnect() {
|
|
36
|
-
this.conn ??= await this.connect();
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
override async internalRelease() {
|
|
40
|
-
if (this.hasOpenTransaction) {
|
|
41
|
-
throw TypeError('pending transaction');
|
|
42
|
-
}
|
|
43
|
-
if (!this.conn) {
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
await this.conn.release();
|
|
47
|
-
this.conn = undefined;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { AbstractQuerierPoolIt } from '../querier/abstractQuerierPool-test.js';
|
|
2
|
-
import { createSpec } from '../test/index.js';
|
|
3
|
-
import type { MySql2Querier } from './mysql2Querier.js';
|
|
4
|
-
import { MySql2QuerierPool } from './mysql2QuerierPool.js';
|
|
5
|
-
|
|
6
|
-
export class MySql2QuerierPoolIt extends AbstractQuerierPoolIt<MySql2Querier> {
|
|
7
|
-
constructor() {
|
|
8
|
-
super(
|
|
9
|
-
new MySql2QuerierPool({
|
|
10
|
-
host: '0.0.0.0',
|
|
11
|
-
port: 3316,
|
|
12
|
-
user: 'test',
|
|
13
|
-
password: 'test',
|
|
14
|
-
database: 'test',
|
|
15
|
-
}),
|
|
16
|
-
);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
createSpec(new MySql2QuerierPoolIt());
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { createPool, type Pool, type PoolOptions } from 'mysql2/promise';
|
|
2
|
-
import { AbstractQuerierPool } from '../querier/index.js';
|
|
3
|
-
import type { ExtraOptions } from '../type/index.js';
|
|
4
|
-
import { MySql2Querier } from './mysql2Querier.js';
|
|
5
|
-
|
|
6
|
-
export class MySql2QuerierPool extends AbstractQuerierPool<MySql2Querier> {
|
|
7
|
-
readonly pool: Pool;
|
|
8
|
-
|
|
9
|
-
constructor(opts: PoolOptions, extra?: ExtraOptions) {
|
|
10
|
-
super('mysql', extra);
|
|
11
|
-
this.pool = createPool(opts);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
async getQuerier() {
|
|
15
|
-
return new MySql2Querier(() => this.pool.getConnection(), this.extra);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
async end() {
|
|
19
|
-
await this.pool.end();
|
|
20
|
-
}
|
|
21
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { expect } from 'bun:test';
|
|
2
|
-
import { AbstractSqlDialectSpec } from '../dialect/abstractSqlDialect-spec.js';
|
|
3
|
-
import { createSpec } from '../test/index.js';
|
|
4
|
-
import { MySqlDialect } from './mysqlDialect.js';
|
|
5
|
-
|
|
6
|
-
export class MySqlDialectSpec extends AbstractSqlDialectSpec {
|
|
7
|
-
constructor() {
|
|
8
|
-
super(new MySqlDialect());
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
shouldHandleDate() {
|
|
12
|
-
const dialect = new MySqlDialect();
|
|
13
|
-
const values: unknown[] = [];
|
|
14
|
-
expect(dialect.addValue(values, new Date())).toBe('?');
|
|
15
|
-
expect(values).toHaveLength(1);
|
|
16
|
-
expect(values[0]).toBeInstanceOf(Date);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
createSpec(new MySqlDialectSpec());
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import SqlString from 'sqlstring';
|
|
2
|
-
import { AbstractSqlDialect } from '../dialect/index.js';
|
|
3
|
-
|
|
4
|
-
export class MySqlDialect extends AbstractSqlDialect {
|
|
5
|
-
override addValue(values: unknown[], value: unknown): string {
|
|
6
|
-
if (value instanceof Date) {
|
|
7
|
-
values.push(value);
|
|
8
|
-
return '?';
|
|
9
|
-
}
|
|
10
|
-
return super.addValue(values, value);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
override escape(value: unknown): string {
|
|
14
|
-
return SqlString.escape(value);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { NamingStrategy } from '../type/index.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Default naming strategy that returns identifiers as-is.
|
|
5
|
-
*/
|
|
6
|
-
export class DefaultNamingStrategy implements NamingStrategy {
|
|
7
|
-
tableName(className: string): string {
|
|
8
|
-
return className;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
columnName(propertyName: string): string {
|
|
12
|
-
return propertyName;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
joinTableName(source: string, target: string, _propertyName?: string): string {
|
|
16
|
-
return `${source}_${target}`;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'bun:test';
|
|
2
|
-
import { DefaultNamingStrategy, SnakeCaseNamingStrategy } from './index.js';
|
|
3
|
-
|
|
4
|
-
describe('NamingStrategy', () => {
|
|
5
|
-
describe('DefaultNamingStrategy', () => {
|
|
6
|
-
const strategy = new DefaultNamingStrategy();
|
|
7
|
-
|
|
8
|
-
it('tableName', () => {
|
|
9
|
-
expect(strategy.tableName('UserProfile')).toBe('UserProfile');
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it('columnName', () => {
|
|
13
|
-
expect(strategy.columnName('firstName')).toBe('firstName');
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it('joinTableName', () => {
|
|
17
|
-
expect(strategy.joinTableName('User', 'Role')).toBe('User_Role');
|
|
18
|
-
});
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
describe('SnakeCaseNamingStrategy', () => {
|
|
22
|
-
const strategy = new SnakeCaseNamingStrategy();
|
|
23
|
-
|
|
24
|
-
it('tableName', () => {
|
|
25
|
-
expect(strategy.tableName('UserProfile')).toBe('user_profile');
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('columnName', () => {
|
|
29
|
-
expect(strategy.columnName('firstName')).toBe('first_name');
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('joinTableName', () => {
|
|
33
|
-
expect(strategy.joinTableName('User', 'Role')).toBe('User_Role'); // Base implementation
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
});
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { snakeCase } from '../util/index.js';
|
|
2
|
-
import { DefaultNamingStrategy } from './defaultNamingStrategy.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Naming strategy that converts identifiers to snake_case.
|
|
6
|
-
*/
|
|
7
|
-
export class SnakeCaseNamingStrategy extends DefaultNamingStrategy {
|
|
8
|
-
override tableName(className: string): string {
|
|
9
|
-
return snakeCase(className);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
override columnName(propertyName: string): string {
|
|
13
|
-
return snakeCase(propertyName);
|
|
14
|
-
}
|
|
15
|
-
}
|
package/src/options.spec.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it, jest } from 'bun:test';
|
|
2
|
-
import { getQuerier, getQuerierPool, setQuerierPool } from './options.js';
|
|
3
|
-
import { User } from './test/index.js';
|
|
4
|
-
import type { Querier, Repository } from './type/index.js';
|
|
5
|
-
|
|
6
|
-
describe('options', () => {
|
|
7
|
-
beforeEach(() => {
|
|
8
|
-
jest.spyOn(console, 'log');
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
it('getQuerierPool unset', () => {
|
|
12
|
-
expect(() => getQuerierPool()).toThrow('A default querier-pool has to be set first');
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it('getQuerier', async () => {
|
|
16
|
-
const repositoryMock = {} as Repository<User>;
|
|
17
|
-
|
|
18
|
-
const querierMock = {
|
|
19
|
-
getRepository<T>(entity: T) {
|
|
20
|
-
return repositoryMock;
|
|
21
|
-
},
|
|
22
|
-
} as Querier;
|
|
23
|
-
|
|
24
|
-
setQuerierPool({
|
|
25
|
-
getQuerier: async () => querierMock,
|
|
26
|
-
end: async () => {},
|
|
27
|
-
dialect: 'postgres',
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
const querier1 = await getQuerierPool().getQuerier();
|
|
31
|
-
expect(querier1).toBe(querierMock);
|
|
32
|
-
|
|
33
|
-
const querier2 = await getQuerier();
|
|
34
|
-
expect(querier2).toBe(querierMock);
|
|
35
|
-
|
|
36
|
-
const repository1 = await querier2.getRepository(User);
|
|
37
|
-
expect(repository1).toBe(repositoryMock);
|
|
38
|
-
|
|
39
|
-
expect(getQuerierPool()).toBe(getQuerierPool());
|
|
40
|
-
});
|
|
41
|
-
});
|
package/src/options.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { Querier, QuerierPool } from './type/index.js';
|
|
2
|
-
|
|
3
|
-
let defaultPool: QuerierPool;
|
|
4
|
-
|
|
5
|
-
export function setQuerierPool<T extends QuerierPool = QuerierPool>(pool: T): void {
|
|
6
|
-
defaultPool = pool;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function getQuerierPool(): QuerierPool {
|
|
10
|
-
if (!defaultPool) {
|
|
11
|
-
throw new TypeError('A default querier-pool has to be set first');
|
|
12
|
-
}
|
|
13
|
-
return defaultPool;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function getQuerier(): Promise<Querier> {
|
|
17
|
-
return defaultPool.getQuerier();
|
|
18
|
-
}
|
package/src/postgres/index.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { types } from 'pg';
|
|
2
|
-
import { AbstractSqlQuerierIt } from '../querier/abstractSqlQuerier-test.js';
|
|
3
|
-
import { createSpec } from '../test/index.js';
|
|
4
|
-
import { PgQuerierPool } from './pgQuerierPool.js';
|
|
5
|
-
|
|
6
|
-
types.setTypeParser(types.builtins.INT8, (value: string) => Number.parseInt(value, 10));
|
|
7
|
-
types.setTypeParser(types.builtins.FLOAT8, (value: string) => Number.parseFloat(value));
|
|
8
|
-
types.setTypeParser(types.builtins.NUMERIC, (value: string) => Number.parseFloat(value));
|
|
9
|
-
|
|
10
|
-
export class PostgresQuerierIt extends AbstractSqlQuerierIt {
|
|
11
|
-
constructor() {
|
|
12
|
-
super(
|
|
13
|
-
new PgQuerierPool({
|
|
14
|
-
host: '0.0.0.0',
|
|
15
|
-
port: 5442,
|
|
16
|
-
user: 'test',
|
|
17
|
-
password: 'test',
|
|
18
|
-
database: 'test',
|
|
19
|
-
}),
|
|
20
|
-
'SERIAL PRIMARY KEY',
|
|
21
|
-
);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
createSpec(new PostgresQuerierIt());
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import type { PoolClient } from 'pg';
|
|
2
|
-
import { AbstractSqlQuerier } from '../querier/index.js';
|
|
3
|
-
import type { ExtraOptions, QueryUpdateResult } from '../type/index.js';
|
|
4
|
-
import { PostgresDialect } from './postgresDialect.js';
|
|
5
|
-
|
|
6
|
-
export class PgQuerier extends AbstractSqlQuerier {
|
|
7
|
-
conn: PoolClient;
|
|
8
|
-
|
|
9
|
-
constructor(
|
|
10
|
-
readonly connect: () => Promise<PoolClient>,
|
|
11
|
-
readonly extra?: ExtraOptions,
|
|
12
|
-
) {
|
|
13
|
-
super(new PostgresDialect(extra?.namingStrategy));
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
override async internalAll<T>(query: string, values?: unknown[]) {
|
|
17
|
-
this.extra?.logger?.(query, values);
|
|
18
|
-
await this.lazyConnect();
|
|
19
|
-
const res = await this.conn.query<T>(query, values);
|
|
20
|
-
return res.rows;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
override async internalRun(query: string, values?: unknown[]) {
|
|
24
|
-
this.extra?.logger?.(query, values);
|
|
25
|
-
await this.lazyConnect();
|
|
26
|
-
const { rowCount: changes, rows = [] }: any = await this.conn.query(query, values);
|
|
27
|
-
const ids = rows.map((r: any) => r.id);
|
|
28
|
-
return { changes, ids, firstId: ids[0] } satisfies QueryUpdateResult;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async lazyConnect() {
|
|
32
|
-
this.conn ??= await this.connect();
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
override async internalRelease() {
|
|
36
|
-
if (this.hasOpenTransaction) {
|
|
37
|
-
throw TypeError('pending transaction');
|
|
38
|
-
}
|
|
39
|
-
if (!this.conn) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
await this.conn.release();
|
|
43
|
-
this.conn = undefined;
|
|
44
|
-
}
|
|
45
|
-
}
|