@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,70 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it, jest } from 'bun:test';
|
|
2
|
-
import { get, patch, post, put, remove } from './http.js';
|
|
3
|
-
|
|
4
|
-
describe('http', () => {
|
|
5
|
-
beforeEach(() => {
|
|
6
|
-
globalThis.fetch = jest.fn() as any;
|
|
7
|
-
(globalThis.fetch as unknown as jest.Mock).mockImplementation(setupFetchStub({}));
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
afterEach(() => {
|
|
11
|
-
delete globalThis.fetch;
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
it('post', async () => {
|
|
15
|
-
const body = {};
|
|
16
|
-
await post('/', body);
|
|
17
|
-
expect(globalThis.fetch).toHaveBeenCalledWith(
|
|
18
|
-
'/',
|
|
19
|
-
expect.objectContaining({ body: JSON.stringify(body), method: 'post' }),
|
|
20
|
-
);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('patch', async () => {
|
|
24
|
-
const body = {};
|
|
25
|
-
await patch('/', body);
|
|
26
|
-
expect(globalThis.fetch).toHaveBeenCalledWith(
|
|
27
|
-
'/',
|
|
28
|
-
expect.objectContaining({ body: JSON.stringify(body), method: 'patch' }),
|
|
29
|
-
);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('put', async () => {
|
|
33
|
-
const body = {};
|
|
34
|
-
await put('/', body);
|
|
35
|
-
expect(globalThis.fetch).toHaveBeenCalledWith(
|
|
36
|
-
'/',
|
|
37
|
-
expect.objectContaining({ body: JSON.stringify(body), method: 'put' }),
|
|
38
|
-
);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('get', async () => {
|
|
42
|
-
await get('/?a=1');
|
|
43
|
-
expect(globalThis.fetch).toHaveBeenCalledWith('/?a=1', expect.objectContaining({ method: 'get' }));
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it('remove', async () => {
|
|
47
|
-
await remove('/?a=1');
|
|
48
|
-
expect(globalThis.fetch).toHaveBeenCalledWith('/?a=1', expect.objectContaining({ method: 'delete' }));
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('error', async () => {
|
|
52
|
-
globalThis.fetch = jest.fn() as any;
|
|
53
|
-
(globalThis.fetch as unknown as jest.Mock).mockImplementation(setupFetchStubError(new Error('some error')));
|
|
54
|
-
await expect(remove('/?a=1')).rejects.toThrow('some error');
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
function setupFetchStub(data: object) {
|
|
59
|
-
return async (_url: any) => ({
|
|
60
|
-
status: 200,
|
|
61
|
-
json: async () => ({ data }),
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function setupFetchStubError(error: Error) {
|
|
66
|
-
return async (_url: any) => ({
|
|
67
|
-
status: 500,
|
|
68
|
-
json: async () => ({ error }),
|
|
69
|
-
});
|
|
70
|
-
}
|
package/src/browser/http/http.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import type { RequestErrorResponse, RequestOptions, RequestSuccessResponse } from '../type/index.js';
|
|
2
|
-
import { notify } from './bus.js';
|
|
3
|
-
|
|
4
|
-
export function get<T>(url: string, opts?: RequestOptions) {
|
|
5
|
-
return request<T>(url, { method: 'get' }, opts);
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export function post<T>(url: string, payload: unknown, opts?: RequestOptions) {
|
|
9
|
-
const body = JSON.stringify(payload);
|
|
10
|
-
return request<T>(url, { method: 'post', body }, opts);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function patch<T>(url: string, payload: unknown, opts?: RequestOptions) {
|
|
14
|
-
const body = JSON.stringify(payload);
|
|
15
|
-
return request<T>(url, { method: 'patch', body }, opts);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function put<T>(url: string, payload: unknown, opts?: RequestOptions) {
|
|
19
|
-
const body = JSON.stringify(payload);
|
|
20
|
-
return request<T>(url, { method: 'put', body }, opts);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function remove<T>(url: string, opts?: RequestOptions) {
|
|
24
|
-
return request<T>(url, { method: 'delete' }, opts);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function request<T>(url: string, init: RequestInit, opts?: RequestOptions) {
|
|
28
|
-
notify({ phase: 'start', opts });
|
|
29
|
-
|
|
30
|
-
init.headers = {
|
|
31
|
-
accept: 'application/json',
|
|
32
|
-
'content-type': 'application/json',
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
return fetch(url, init)
|
|
36
|
-
.then((rawResp) =>
|
|
37
|
-
rawResp.json().then((resp: unknown) => {
|
|
38
|
-
const isSuccess = rawResp.status >= 200 && rawResp.status < 300;
|
|
39
|
-
if (isSuccess) {
|
|
40
|
-
notify({ phase: 'success', opts });
|
|
41
|
-
return resp as RequestSuccessResponse<T>;
|
|
42
|
-
}
|
|
43
|
-
const errorResp = resp as RequestErrorResponse;
|
|
44
|
-
notify({
|
|
45
|
-
phase: 'error',
|
|
46
|
-
error: errorResp.error,
|
|
47
|
-
opts,
|
|
48
|
-
});
|
|
49
|
-
throw Error(errorResp.error.message);
|
|
50
|
-
}),
|
|
51
|
-
)
|
|
52
|
-
.finally(() => {
|
|
53
|
-
notify({ phase: 'complete', opts });
|
|
54
|
-
});
|
|
55
|
-
}
|
package/src/browser/index.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'bun:test';
|
|
2
|
-
import { User } from '../test/index.js';
|
|
3
|
-
import { getQuerier, getQuerierPool, setQuerierPool } from './options.js';
|
|
4
|
-
import { GenericClientRepository, HttpQuerier } from './querier/index.js';
|
|
5
|
-
import type { ClientQuerierPool } from './type/clientQuerierPool.js';
|
|
6
|
-
|
|
7
|
-
describe('options', () => {
|
|
8
|
-
it('default getQuerier', () => {
|
|
9
|
-
const querier = getQuerier();
|
|
10
|
-
expect(querier).toBeInstanceOf(HttpQuerier);
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it('default querierPool', () => {
|
|
14
|
-
expect(getQuerierPool()).toBeDefined();
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it('custom querierPool', () => {
|
|
18
|
-
const querierMock = new HttpQuerier('/');
|
|
19
|
-
|
|
20
|
-
const querierPool: ClientQuerierPool = {
|
|
21
|
-
getQuerier: () => querierMock,
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
setQuerierPool(querierPool);
|
|
25
|
-
|
|
26
|
-
const querier1 = getQuerierPool().getQuerier();
|
|
27
|
-
expect(querier1).toBe(querierMock);
|
|
28
|
-
|
|
29
|
-
const querier2 = getQuerier();
|
|
30
|
-
expect(querier2).toBe(querierMock);
|
|
31
|
-
|
|
32
|
-
const repository1 = querier2.getRepository(User);
|
|
33
|
-
expect(repository1).toBeInstanceOf(GenericClientRepository);
|
|
34
|
-
|
|
35
|
-
expect(getQuerierPool()).toBe(getQuerierPool());
|
|
36
|
-
});
|
|
37
|
-
});
|
package/src/browser/options.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { HttpQuerier } from './querier/httpQuerier.js';
|
|
2
|
-
import type { ClientQuerier, ClientQuerierPool } from './type/index.js';
|
|
3
|
-
|
|
4
|
-
let defaultPool: ClientQuerierPool = {
|
|
5
|
-
getQuerier: () => new HttpQuerier('/api'),
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
export function setQuerierPool<T extends ClientQuerierPool>(pool: T) {
|
|
9
|
-
defaultPool = pool;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function getQuerierPool(): ClientQuerierPool {
|
|
13
|
-
return defaultPool;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function getQuerier(): ClientQuerier {
|
|
17
|
-
return getQuerierPool().getQuerier();
|
|
18
|
-
}
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it, jest } from 'bun:test';
|
|
2
|
-
import { User } from '../../test/index.js';
|
|
3
|
-
import { GenericClientRepository } from './genericClientRepository.js';
|
|
4
|
-
import { HttpQuerier } from './httpQuerier.js';
|
|
5
|
-
|
|
6
|
-
describe('repository', () => {
|
|
7
|
-
let repository: GenericClientRepository<User>;
|
|
8
|
-
const querier = new HttpQuerier('');
|
|
9
|
-
|
|
10
|
-
beforeEach(() => {
|
|
11
|
-
globalThis.fetch = jest.fn() as any;
|
|
12
|
-
(globalThis.fetch as unknown as jest.Mock).mockImplementation(setupFetchStub({}));
|
|
13
|
-
repository = new GenericClientRepository(User, querier);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
afterEach(() => {
|
|
17
|
-
delete globalThis.fetch;
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('count', async () => {
|
|
21
|
-
await repository.count({});
|
|
22
|
-
expect(globalThis.fetch).toHaveBeenCalledWith('/user/count', expect.objectContaining({ method: 'get' }));
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('findOneById', async () => {
|
|
26
|
-
await repository.findOneById(1);
|
|
27
|
-
expect(globalThis.fetch).toHaveBeenCalledWith('/user/1', expect.objectContaining({ method: 'get' }));
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('findOne', async () => {
|
|
31
|
-
await repository.findOne({});
|
|
32
|
-
expect(globalThis.fetch).toHaveBeenCalledWith('/user/one', expect.objectContaining({ method: 'get' }));
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it('findMany', async () => {
|
|
36
|
-
await repository.findMany({});
|
|
37
|
-
expect(globalThis.fetch).toHaveBeenCalledWith('/user', expect.objectContaining({ method: 'get' }));
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('findManyAndCount', async () => {
|
|
41
|
-
await repository.findManyAndCount({});
|
|
42
|
-
expect(globalThis.fetch).toHaveBeenCalledWith('/user?count=true', expect.objectContaining({ method: 'get' }));
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('insertOne', async () => {
|
|
46
|
-
await repository.insertOne({});
|
|
47
|
-
expect(globalThis.fetch).toHaveBeenCalledWith('/user', expect.objectContaining({ method: 'post' }));
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('updateOneById', async () => {
|
|
51
|
-
await repository.updateOneById(1, {});
|
|
52
|
-
expect(globalThis.fetch).toHaveBeenCalledWith('/user/1', expect.objectContaining({ method: 'patch' }));
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('saveOne', async () => {
|
|
56
|
-
await repository.saveOne({});
|
|
57
|
-
expect(globalThis.fetch).toHaveBeenCalledWith('/user', expect.objectContaining({ method: 'post' }));
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('saveOne id', async () => {
|
|
61
|
-
await repository.saveOne({ id: 2 });
|
|
62
|
-
expect(globalThis.fetch).toHaveBeenCalledWith('/user/2', expect.objectContaining({ method: 'patch' }));
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it('deleteOneById', async () => {
|
|
66
|
-
await repository.deleteOneById(1);
|
|
67
|
-
expect(globalThis.fetch).toHaveBeenCalledWith('/user/1', expect.objectContaining({ method: 'delete' }));
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it('deleteOneById soft', async () => {
|
|
71
|
-
await repository.deleteOneById(1, { softDelete: true });
|
|
72
|
-
expect(globalThis.fetch).toHaveBeenCalledWith(
|
|
73
|
-
'/user/1?softDelete=true',
|
|
74
|
-
expect.objectContaining({ method: 'delete' }),
|
|
75
|
-
);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it('deleteMany', async () => {
|
|
79
|
-
await repository.deleteMany({});
|
|
80
|
-
expect(globalThis.fetch).toHaveBeenCalledWith('/user', expect.objectContaining({ method: 'delete' }));
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it('deleteMany soft', async () => {
|
|
84
|
-
await repository.deleteMany({}, { softDelete: true });
|
|
85
|
-
expect(globalThis.fetch).toHaveBeenCalledWith(
|
|
86
|
-
'/user?softDelete=true',
|
|
87
|
-
expect.objectContaining({ method: 'delete' }),
|
|
88
|
-
);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it('entity property', () => {
|
|
92
|
-
expect(repository.entity).toBe(User);
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it('repository property', () => {
|
|
96
|
-
expect(repository.querier).toBe(querier);
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
function setupFetchStub(data: object) {
|
|
101
|
-
return async (_url: any) => ({
|
|
102
|
-
status: 200,
|
|
103
|
-
json: async () => ({ data }),
|
|
104
|
-
});
|
|
105
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import type { IdValue, Query, QueryOne, QueryOptions, QuerySearch, Type } from '../../type/index.js';
|
|
2
|
-
import type { ClientQuerier, ClientRepository, RequestOptions } from '../type/index.js';
|
|
3
|
-
|
|
4
|
-
export class GenericClientRepository<E> implements ClientRepository<E> {
|
|
5
|
-
constructor(
|
|
6
|
-
readonly entity: Type<E>,
|
|
7
|
-
readonly querier: ClientQuerier,
|
|
8
|
-
) {}
|
|
9
|
-
|
|
10
|
-
findOneById(id: IdValue<E>, q?: QueryOne<E>, opts?: RequestOptions) {
|
|
11
|
-
return this.querier.findOneById(this.entity, id, q, opts);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
findOne(q: QueryOne<E>, opts?: RequestOptions) {
|
|
15
|
-
return this.querier.findOne(this.entity, q, opts);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
findMany(q: Query<E>, opts?: RequestOptions) {
|
|
19
|
-
return this.querier.findMany(this.entity, q, opts);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
findManyAndCount(q: Query<E>, opts?: RequestOptions) {
|
|
23
|
-
return this.querier.findManyAndCount(this.entity, q, opts);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
count(qm?: QuerySearch<E>, opts?: RequestOptions) {
|
|
27
|
-
return this.querier.count(this.entity, qm, opts);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
insertOne(payload: E, opts?: RequestOptions) {
|
|
31
|
-
return this.querier.insertOne(this.entity, payload, opts);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
updateOneById(id: IdValue<E>, payload: E, opts?: RequestOptions) {
|
|
35
|
-
return this.querier.updateOneById(this.entity, id, payload, opts);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
saveOne(payload: E, opts?: RequestOptions) {
|
|
39
|
-
return this.querier.saveOne(this.entity, payload, opts);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
deleteOneById(id: IdValue<E>, opts?: QueryOptions) {
|
|
43
|
-
return this.querier.deleteOneById(this.entity, id, opts);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
deleteMany(qm: QuerySearch<E>, opts?: QueryOptions) {
|
|
47
|
-
return this.querier.deleteMany(this.entity, qm, opts);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { getMeta } from '../../entity/index.js';
|
|
2
|
-
import type { IdValue, Query, QueryOne, QueryOptions, QuerySearch, Type } from '../../type/index.js';
|
|
3
|
-
import { kebabCase } from '../../util/index.js';
|
|
4
|
-
import { get, patch, post, remove } from '../http/index.js';
|
|
5
|
-
import type { ClientQuerier, ClientRepository, RequestFindOptions, RequestOptions } from '../type/index.js';
|
|
6
|
-
import { GenericClientRepository } from './genericClientRepository.js';
|
|
7
|
-
import { stringifyQuery } from './querier.util.js';
|
|
8
|
-
|
|
9
|
-
export class HttpQuerier implements ClientQuerier {
|
|
10
|
-
constructor(readonly basePath: string) {}
|
|
11
|
-
|
|
12
|
-
findOneById<E>(entity: Type<E>, id: IdValue<E>, q?: QueryOne<E>, opts?: RequestOptions) {
|
|
13
|
-
const basePath = this.getBasePath(entity);
|
|
14
|
-
const qs = stringifyQuery(q);
|
|
15
|
-
return get<E>(`${basePath}/${id}${qs}`, opts);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
findOne<E>(entity: Type<E>, q: QueryOne<E>, opts?: RequestOptions) {
|
|
19
|
-
const basePath = this.getBasePath(entity);
|
|
20
|
-
const qs = stringifyQuery(q);
|
|
21
|
-
return get<E>(`${basePath}/one${qs}`, opts);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
findMany<E>(entity: Type<E>, q: Query<E>, opts?: RequestFindOptions) {
|
|
25
|
-
const data: Query<E> & Pick<typeof opts, 'count'> = { ...q };
|
|
26
|
-
if (opts?.count) {
|
|
27
|
-
data.count = true;
|
|
28
|
-
}
|
|
29
|
-
const basePath = this.getBasePath(entity);
|
|
30
|
-
const qs = stringifyQuery(data);
|
|
31
|
-
return get<E[]>(`${basePath}${qs}`, opts);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
findManyAndCount<E>(entity: Type<E>, q: Query<E>, opts?: RequestFindOptions) {
|
|
35
|
-
return this.findMany(entity, q, { ...opts, count: true });
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
count<E>(entity: Type<E>, q: QuerySearch<E>, opts?: RequestOptions) {
|
|
39
|
-
const basePath = this.getBasePath(entity);
|
|
40
|
-
const qs = stringifyQuery(q);
|
|
41
|
-
return get<number>(`${basePath}/count${qs}`, opts);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
insertOne<E>(entity: Type<E>, payload: E, opts?: RequestOptions) {
|
|
45
|
-
const basePath = this.getBasePath(entity);
|
|
46
|
-
return post<any>(basePath, payload, opts);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
updateOneById<E>(entity: Type<E>, id: IdValue<E>, payload: E, opts?: RequestOptions) {
|
|
50
|
-
const basePath = this.getBasePath(entity);
|
|
51
|
-
return patch<typeof id>(`${basePath}/${id}`, payload, opts);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
saveOne<E>(entity: Type<E>, payload: E, opts?: RequestOptions) {
|
|
55
|
-
const meta = getMeta(entity);
|
|
56
|
-
const id = payload[meta.id];
|
|
57
|
-
if (id) {
|
|
58
|
-
return this.updateOneById(entity, id, payload, opts).then(() => ({ data: id }));
|
|
59
|
-
}
|
|
60
|
-
return this.insertOne(entity, payload, opts);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
deleteOneById<E>(entity: Type<E>, id: IdValue<E>, opts: QueryOptions & RequestOptions = {}) {
|
|
64
|
-
const basePath = this.getBasePath(entity);
|
|
65
|
-
const qs = opts.softDelete ? stringifyQuery({ softDelete: opts.softDelete }) : '';
|
|
66
|
-
return remove<typeof id>(`${basePath}/${id}${qs}`, opts);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
deleteMany<E>(entity: Type<E>, q: QuerySearch<E>, opts: QueryOptions & RequestOptions = {}) {
|
|
70
|
-
const basePath = this.getBasePath(entity);
|
|
71
|
-
const qs = stringifyQuery(opts.softDelete ? { ...q, softDelete: opts.softDelete } : q);
|
|
72
|
-
return remove<IdValue<E>[]>(`${basePath}${qs}`, opts);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
getRepository<E>(entity: Type<E>): ClientRepository<E> {
|
|
76
|
-
return new GenericClientRepository(entity, this);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
getBasePath<E>(entity: Type<E>) {
|
|
80
|
-
return this.basePath + '/' + kebabCase(entity.name);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { expect, it } from 'bun:test';
|
|
2
|
-
import type { Item, User } from '../../test/index.js';
|
|
3
|
-
import type { Query } from '../../type/index.js';
|
|
4
|
-
import { stringifyQuery, stringifyQueryParameter } from './querier.util.js';
|
|
5
|
-
|
|
6
|
-
it('stringifyQuery -- empty', () => {
|
|
7
|
-
const source: Query<User> = {};
|
|
8
|
-
const result = stringifyQuery(source);
|
|
9
|
-
const expected = '';
|
|
10
|
-
expect(result).toBe(expected);
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it('stringifyQueryParameter', () => {
|
|
14
|
-
expect(stringifyQueryParameter('select', undefined)).toBe('select=undefined');
|
|
15
|
-
expect(stringifyQueryParameter('limit', 10, true)).toBe('?limit=10');
|
|
16
|
-
expect(stringifyQueryParameter('limit', 10)).toBe('limit=10');
|
|
17
|
-
expect(stringifyQueryParameter('limit', null, true)).toBe('?limit=null');
|
|
18
|
-
expect(stringifyQueryParameter('sort', { createdAt: -1 })).toBe('sort={"createdAt":-1}');
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it('stringifyQuery', () => {
|
|
22
|
-
expect(stringifyQuery(undefined)).toBe('');
|
|
23
|
-
expect(stringifyQuery({})).toBe('');
|
|
24
|
-
expect(stringifyQuery({ $sort: undefined })).toBe('');
|
|
25
|
-
const source: Query<Item> = {
|
|
26
|
-
$select: { id: 1, name: 1, tax: true, measureUnit: { $select: { id: 1, name: 1, categoryId: 1 } } },
|
|
27
|
-
$where: { name: 'Batman', companyId: 38 },
|
|
28
|
-
$sort: { companyId: 1, name: -1 },
|
|
29
|
-
$limit: 5,
|
|
30
|
-
};
|
|
31
|
-
const result = stringifyQuery(source);
|
|
32
|
-
const expected =
|
|
33
|
-
'?$select={"id":1,"name":1,"tax":true,"measureUnit":{"$select":{"id":1,"name":1,"categoryId":1}}}&$where={"name":"Batman","companyId":38}&$sort={"companyId":1,"name":-1}&$limit=5';
|
|
34
|
-
expect(result).toBe(expected);
|
|
35
|
-
});
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { getKeys } from '../../util/index.js';
|
|
2
|
-
|
|
3
|
-
export function stringifyQueryParameter(key: string, value?: unknown, useQuestionMark?: boolean): string {
|
|
4
|
-
const valStr = typeof value === 'object' && value !== null ? JSON.stringify(value) : value;
|
|
5
|
-
return (useQuestionMark ? '?' : '') + `${key}=${valStr}`;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export function stringifyQuery(query: object): string {
|
|
9
|
-
if (!query) {
|
|
10
|
-
return '';
|
|
11
|
-
}
|
|
12
|
-
const keys = getKeys(query);
|
|
13
|
-
if (keys.length === 0) {
|
|
14
|
-
return '';
|
|
15
|
-
}
|
|
16
|
-
const qsArr = keys.filter((key) => query[key] !== undefined).map((key) => stringifyQueryParameter(key, query[key]));
|
|
17
|
-
return qsArr.length ? '?' + qsArr.join('&') : '';
|
|
18
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import type { IdValue, Query, QueryOne, QueryOptions, QuerySearch, Type, UniversalQuerier } from '../../type/index.js';
|
|
2
|
-
import type { ClientRepository } from './clientRepository.js';
|
|
3
|
-
import type { RequestOptions, RequestSuccessResponse } from './request.js';
|
|
4
|
-
|
|
5
|
-
export interface ClientQuerier extends UniversalQuerier {
|
|
6
|
-
findOneById<E>(
|
|
7
|
-
entity: Type<E>,
|
|
8
|
-
id: IdValue<E>,
|
|
9
|
-
q?: QueryOne<E>,
|
|
10
|
-
opts?: RequestOptions,
|
|
11
|
-
): Promise<RequestSuccessResponse<E>>;
|
|
12
|
-
|
|
13
|
-
findOne<E>(entity: Type<E>, q: QueryOne<E>, opts?: RequestOptions): Promise<RequestSuccessResponse<E>>;
|
|
14
|
-
|
|
15
|
-
findMany<E>(entity: Type<E>, q: Query<E>, opts?: RequestOptions): Promise<RequestSuccessResponse<E[]>>;
|
|
16
|
-
|
|
17
|
-
findManyAndCount<E>(entity: Type<E>, q: Query<E>, opts?: RequestOptions): Promise<RequestSuccessResponse<E[]>>;
|
|
18
|
-
|
|
19
|
-
count<E>(entity: Type<E>, q?: QuerySearch<E>, opts?: RequestOptions): Promise<RequestSuccessResponse<number>>;
|
|
20
|
-
|
|
21
|
-
insertOne<E>(entity: Type<E>, payload: E, opts?: RequestOptions): Promise<RequestSuccessResponse<IdValue<E>>>;
|
|
22
|
-
|
|
23
|
-
updateOneById<E>(
|
|
24
|
-
entity: Type<E>,
|
|
25
|
-
id: IdValue<E>,
|
|
26
|
-
payload: E,
|
|
27
|
-
opts?: RequestOptions,
|
|
28
|
-
): Promise<RequestSuccessResponse<IdValue<E>>>;
|
|
29
|
-
|
|
30
|
-
saveOne<E>(entity: Type<E>, payload: E, opts?: RequestOptions): Promise<RequestSuccessResponse<IdValue<E>>>;
|
|
31
|
-
|
|
32
|
-
deleteOneById<E>(
|
|
33
|
-
entity: Type<E>,
|
|
34
|
-
id: IdValue<E>,
|
|
35
|
-
opts?: QueryOptions & RequestOptions,
|
|
36
|
-
): Promise<RequestSuccessResponse<IdValue<E>>>;
|
|
37
|
-
|
|
38
|
-
deleteMany<E>(
|
|
39
|
-
entity: Type<E>,
|
|
40
|
-
qm: QuerySearch<E>,
|
|
41
|
-
opts?: QueryOptions & RequestOptions,
|
|
42
|
-
): Promise<RequestSuccessResponse<IdValue<E>[]>>;
|
|
43
|
-
|
|
44
|
-
getRepository<E>(entity: Type<E>): ClientRepository<E>;
|
|
45
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { IdValue, Query, QueryOne, QueryOptions, QuerySearch, UniversalRepository } from '../../type/index.js';
|
|
2
|
-
import type { RequestOptions, RequestSuccessResponse } from './request.js';
|
|
3
|
-
|
|
4
|
-
export interface ClientRepository<E> extends UniversalRepository<E> {
|
|
5
|
-
findOneById(id: IdValue<E>, q?: QueryOne<E>, opts?: RequestOptions): Promise<RequestSuccessResponse<E>>;
|
|
6
|
-
|
|
7
|
-
findOne(qm: QueryOne<E>, opts?: RequestOptions): Promise<RequestSuccessResponse<E>>;
|
|
8
|
-
|
|
9
|
-
findMany(qm: Query<E>, opts?: RequestOptions): Promise<RequestSuccessResponse<E[]>>;
|
|
10
|
-
|
|
11
|
-
findManyAndCount(qm: Query<E>, opts?: RequestOptions): Promise<RequestSuccessResponse<E[]>>;
|
|
12
|
-
|
|
13
|
-
count(qm?: QuerySearch<E>, opts?: RequestOptions): Promise<RequestSuccessResponse<number>>;
|
|
14
|
-
|
|
15
|
-
insertOne(payload: E, opts?: RequestOptions): Promise<RequestSuccessResponse<IdValue<E>>>;
|
|
16
|
-
|
|
17
|
-
saveOne(payload: E, opts?: RequestOptions): Promise<RequestSuccessResponse<IdValue<E>>>;
|
|
18
|
-
|
|
19
|
-
deleteOneById(id: IdValue<E>, opts?: QueryOptions & RequestOptions): Promise<RequestSuccessResponse<IdValue<E>>>;
|
|
20
|
-
|
|
21
|
-
deleteMany(qm: QuerySearch<E>, opts?: QueryOptions & RequestOptions): Promise<RequestSuccessResponse<IdValue<E>[]>>;
|
|
22
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
export type RequestSuccessResponse<E> = {
|
|
2
|
-
data: E;
|
|
3
|
-
count?: number;
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
export type RequestErrorResponse = {
|
|
7
|
-
readonly error: {
|
|
8
|
-
readonly message: string;
|
|
9
|
-
readonly code: number;
|
|
10
|
-
};
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export type RequestOptions = {
|
|
14
|
-
silent?: boolean;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export type RequestFindOptions = RequestOptions & {
|
|
18
|
-
count?: boolean;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
type RequestBaseNotification = { readonly opts?: RequestOptions };
|
|
22
|
-
type RequestSuccessNotification = { readonly phase: 'start' | 'success' | 'complete' } & RequestBaseNotification;
|
|
23
|
-
type RequestErrorNotification = { readonly phase: 'error' } & RequestErrorResponse & RequestBaseNotification;
|
|
24
|
-
export type RequestNotification = RequestSuccessNotification | RequestErrorNotification;
|
|
25
|
-
export type RequestCallback = (msg: RequestNotification) => any;
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import type { EntityMeta, FieldOptions, NamingStrategy, Type } from '../type/index.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Base abstract class for all database dialects (SQL and NoSQL).
|
|
5
|
-
*/
|
|
6
|
-
export abstract class AbstractDialect {
|
|
7
|
-
constructor(readonly namingStrategy?: NamingStrategy) {}
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Resolve the table name for an entity, applying naming strategy if necessary.
|
|
11
|
-
*/
|
|
12
|
-
resolveTableName<E>(entity: Type<E>, meta: EntityMeta<E>): string {
|
|
13
|
-
if (meta.name !== entity.name || !this.namingStrategy) {
|
|
14
|
-
return meta.name;
|
|
15
|
-
}
|
|
16
|
-
return this.namingStrategy.tableName(meta.name);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Resolve the column/field name for a property, applying naming strategy if necessary.
|
|
21
|
-
*/
|
|
22
|
-
resolveColumnName(key: string, field: FieldOptions): string {
|
|
23
|
-
if (!field || field.name !== key || !this.namingStrategy) {
|
|
24
|
-
return field?.name ?? key;
|
|
25
|
-
}
|
|
26
|
-
return this.namingStrategy.columnName(field.name);
|
|
27
|
-
}
|
|
28
|
-
}
|