@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.
Files changed (171) hide show
  1. package/CHANGELOG.md +134 -187
  2. package/package.json +31 -26
  3. package/dist/CHANGELOG.md +0 -186
  4. package/dist/package.json +0 -131
  5. package/src/@types/index.d.ts +0 -1
  6. package/src/@types/jest.d.ts +0 -6
  7. package/src/browser/http/bus.spec.ts +0 -22
  8. package/src/browser/http/bus.ts +0 -17
  9. package/src/browser/http/http.spec.ts +0 -70
  10. package/src/browser/http/http.ts +0 -55
  11. package/src/browser/http/index.ts +0 -2
  12. package/src/browser/index.ts +0 -4
  13. package/src/browser/options.spec.ts +0 -37
  14. package/src/browser/options.ts +0 -18
  15. package/src/browser/querier/genericClientRepository.spec.ts +0 -105
  16. package/src/browser/querier/genericClientRepository.ts +0 -49
  17. package/src/browser/querier/httpQuerier.ts +0 -82
  18. package/src/browser/querier/index.ts +0 -3
  19. package/src/browser/querier/querier.util.spec.ts +0 -35
  20. package/src/browser/querier/querier.util.ts +0 -18
  21. package/src/browser/type/clientQuerier.ts +0 -45
  22. package/src/browser/type/clientQuerierPool.ts +0 -5
  23. package/src/browser/type/clientRepository.ts +0 -22
  24. package/src/browser/type/index.ts +0 -4
  25. package/src/browser/type/request.ts +0 -25
  26. package/src/dialect/abstractDialect.ts +0 -28
  27. package/src/dialect/abstractSqlDialect-spec.ts +0 -1309
  28. package/src/dialect/abstractSqlDialect.ts +0 -805
  29. package/src/dialect/index.ts +0 -3
  30. package/src/dialect/namingStrategy.spec.ts +0 -52
  31. package/src/dialect/queryContext.ts +0 -69
  32. package/src/entity/decorator/definition.spec.ts +0 -736
  33. package/src/entity/decorator/definition.ts +0 -265
  34. package/src/entity/decorator/entity.ts +0 -8
  35. package/src/entity/decorator/field.ts +0 -9
  36. package/src/entity/decorator/id.ts +0 -9
  37. package/src/entity/decorator/index.ts +0 -5
  38. package/src/entity/decorator/relation.spec.ts +0 -41
  39. package/src/entity/decorator/relation.ts +0 -34
  40. package/src/entity/index.ts +0 -1
  41. package/src/express/@types/express.d.ts +0 -8
  42. package/src/express/@types/index.d.ts +0 -1
  43. package/src/express/index.ts +0 -2
  44. package/src/express/querierMiddleware.ts +0 -217
  45. package/src/express/query.util.spec.ts +0 -40
  46. package/src/express/query.util.ts +0 -21
  47. package/src/index.ts +0 -9
  48. package/src/maria/index.ts +0 -3
  49. package/src/maria/mariaDialect.spec.ts +0 -207
  50. package/src/maria/mariaDialect.ts +0 -42
  51. package/src/maria/mariaQuerierPool.test.ts +0 -23
  52. package/src/maria/mariadbQuerier.test.ts +0 -23
  53. package/src/maria/mariadbQuerier.ts +0 -45
  54. package/src/maria/mariadbQuerierPool.ts +0 -21
  55. package/src/migrate/cli.ts +0 -301
  56. package/src/migrate/generator/index.ts +0 -4
  57. package/src/migrate/generator/mongoSchemaGenerator.spec.ts +0 -112
  58. package/src/migrate/generator/mongoSchemaGenerator.ts +0 -115
  59. package/src/migrate/generator/mysqlSchemaGenerator.spec.ts +0 -34
  60. package/src/migrate/generator/mysqlSchemaGenerator.ts +0 -92
  61. package/src/migrate/generator/postgresSchemaGenerator.spec.ts +0 -44
  62. package/src/migrate/generator/postgresSchemaGenerator.ts +0 -127
  63. package/src/migrate/generator/sqliteSchemaGenerator.spec.ts +0 -33
  64. package/src/migrate/generator/sqliteSchemaGenerator.ts +0 -81
  65. package/src/migrate/index.ts +0 -41
  66. package/src/migrate/introspection/index.ts +0 -4
  67. package/src/migrate/introspection/mongoIntrospector.spec.ts +0 -75
  68. package/src/migrate/introspection/mongoIntrospector.ts +0 -47
  69. package/src/migrate/introspection/mysqlIntrospector.spec.ts +0 -113
  70. package/src/migrate/introspection/mysqlIntrospector.ts +0 -278
  71. package/src/migrate/introspection/postgresIntrospector.spec.ts +0 -112
  72. package/src/migrate/introspection/postgresIntrospector.ts +0 -329
  73. package/src/migrate/introspection/sqliteIntrospector.spec.ts +0 -112
  74. package/src/migrate/introspection/sqliteIntrospector.ts +0 -296
  75. package/src/migrate/migrator-mongo.test.ts +0 -54
  76. package/src/migrate/migrator.spec.ts +0 -255
  77. package/src/migrate/migrator.test.ts +0 -94
  78. package/src/migrate/migrator.ts +0 -719
  79. package/src/migrate/namingStrategy.spec.ts +0 -22
  80. package/src/migrate/schemaGenerator-advanced.spec.ts +0 -138
  81. package/src/migrate/schemaGenerator.spec.ts +0 -190
  82. package/src/migrate/schemaGenerator.ts +0 -478
  83. package/src/migrate/storage/databaseStorage.spec.ts +0 -69
  84. package/src/migrate/storage/databaseStorage.ts +0 -100
  85. package/src/migrate/storage/index.ts +0 -2
  86. package/src/migrate/storage/jsonStorage.ts +0 -58
  87. package/src/migrate/type.ts +0 -1
  88. package/src/mongo/index.ts +0 -3
  89. package/src/mongo/mongoDialect.spec.ts +0 -251
  90. package/src/mongo/mongoDialect.ts +0 -238
  91. package/src/mongo/mongodbQuerier.test.ts +0 -45
  92. package/src/mongo/mongodbQuerier.ts +0 -256
  93. package/src/mongo/mongodbQuerierPool.test.ts +0 -25
  94. package/src/mongo/mongodbQuerierPool.ts +0 -24
  95. package/src/mysql/index.ts +0 -3
  96. package/src/mysql/mysql2Querier.test.ts +0 -20
  97. package/src/mysql/mysql2Querier.ts +0 -49
  98. package/src/mysql/mysql2QuerierPool.test.ts +0 -20
  99. package/src/mysql/mysql2QuerierPool.ts +0 -21
  100. package/src/mysql/mysqlDialect.spec.ts +0 -20
  101. package/src/mysql/mysqlDialect.ts +0 -16
  102. package/src/namingStrategy/defaultNamingStrategy.ts +0 -18
  103. package/src/namingStrategy/index.spec.ts +0 -36
  104. package/src/namingStrategy/index.ts +0 -2
  105. package/src/namingStrategy/snakeCaseNamingStrategy.ts +0 -15
  106. package/src/options.spec.ts +0 -41
  107. package/src/options.ts +0 -18
  108. package/src/postgres/index.ts +0 -3
  109. package/src/postgres/manual-types.d.ts +0 -4
  110. package/src/postgres/pgQuerier.test.ts +0 -25
  111. package/src/postgres/pgQuerier.ts +0 -45
  112. package/src/postgres/pgQuerierPool.test.ts +0 -28
  113. package/src/postgres/pgQuerierPool.ts +0 -21
  114. package/src/postgres/postgresDialect.spec.ts +0 -428
  115. package/src/postgres/postgresDialect.ts +0 -144
  116. package/src/querier/abstractQuerier-test.ts +0 -584
  117. package/src/querier/abstractQuerier.ts +0 -353
  118. package/src/querier/abstractQuerierPool-test.ts +0 -20
  119. package/src/querier/abstractQuerierPool.ts +0 -18
  120. package/src/querier/abstractSqlQuerier-spec.ts +0 -979
  121. package/src/querier/abstractSqlQuerier-test.ts +0 -21
  122. package/src/querier/abstractSqlQuerier.ts +0 -138
  123. package/src/querier/decorator/index.ts +0 -3
  124. package/src/querier/decorator/injectQuerier.spec.ts +0 -74
  125. package/src/querier/decorator/injectQuerier.ts +0 -45
  126. package/src/querier/decorator/serialized.spec.ts +0 -98
  127. package/src/querier/decorator/serialized.ts +0 -13
  128. package/src/querier/decorator/transactional.spec.ts +0 -240
  129. package/src/querier/decorator/transactional.ts +0 -56
  130. package/src/querier/index.ts +0 -4
  131. package/src/repository/genericRepository.spec.ts +0 -111
  132. package/src/repository/genericRepository.ts +0 -74
  133. package/src/repository/index.ts +0 -1
  134. package/src/sqlite/index.ts +0 -3
  135. package/src/sqlite/manual-types.d.ts +0 -4
  136. package/src/sqlite/sqliteDialect.spec.ts +0 -155
  137. package/src/sqlite/sqliteDialect.ts +0 -76
  138. package/src/sqlite/sqliteQuerier.spec.ts +0 -36
  139. package/src/sqlite/sqliteQuerier.test.ts +0 -21
  140. package/src/sqlite/sqliteQuerier.ts +0 -37
  141. package/src/sqlite/sqliteQuerierPool.test.ts +0 -12
  142. package/src/sqlite/sqliteQuerierPool.ts +0 -38
  143. package/src/test/entityMock.ts +0 -375
  144. package/src/test/index.ts +0 -3
  145. package/src/test/it.util.ts +0 -69
  146. package/src/test/spec.util.ts +0 -57
  147. package/src/type/entity.ts +0 -218
  148. package/src/type/index.ts +0 -9
  149. package/src/type/migration.ts +0 -241
  150. package/src/type/namingStrategy.ts +0 -17
  151. package/src/type/querier.ts +0 -143
  152. package/src/type/querierPool.ts +0 -26
  153. package/src/type/query.ts +0 -506
  154. package/src/type/repository.ts +0 -142
  155. package/src/type/universalQuerier.ts +0 -133
  156. package/src/type/utility.ts +0 -21
  157. package/src/util/dialect.util-extra.spec.ts +0 -96
  158. package/src/util/dialect.util.spec.ts +0 -23
  159. package/src/util/dialect.util.ts +0 -134
  160. package/src/util/index.ts +0 -5
  161. package/src/util/object.util.spec.ts +0 -29
  162. package/src/util/object.util.ts +0 -27
  163. package/src/util/raw.ts +0 -11
  164. package/src/util/sql.util-extra.spec.ts +0 -17
  165. package/src/util/sql.util.spec.ts +0 -208
  166. package/src/util/sql.util.ts +0 -104
  167. package/src/util/string.util.spec.ts +0 -46
  168. package/src/util/string.util.ts +0 -35
  169. package/tsconfig.build.json +0 -5
  170. package/tsconfig.json +0 -8
  171. /package/{dist/README.md → README.md} +0 -0
package/dist/package.json DELETED
@@ -1,131 +0,0 @@
1
- {
2
- "name": "@uql/core",
3
- "homepage": "https://uql.app",
4
- "description": "One Language. Frontend to Backend.",
5
- "license": "MIT",
6
- "version": "3.1.0",
7
- "type": "module",
8
- "main": "./index.js",
9
- "types": "./index.d.ts",
10
- "bin": {
11
- "uql-migrate": "./migrate/cli.js"
12
- },
13
- "exports": {
14
- ".": "./index.js",
15
- "./dialect": "./dialect/index.js",
16
- "./entity": "./entity/index.js",
17
- "./querier": "./querier/index.js",
18
- "./repository": "./repository/index.js",
19
- "./type": "./type/index.js",
20
- "./util": "./util/index.js",
21
- "./namingStrategy": "./namingStrategy/index.js",
22
- "./migrate": "./migrate/index.js",
23
- "./options": "./options.js",
24
- "./test": "./test/index.js",
25
- "./mysql": "./mysql/index.js",
26
- "./postgres": "./postgres/index.js",
27
- "./maria": "./maria/index.js",
28
- "./sqlite": "./sqlite/index.js",
29
- "./mongo": "./mongo/index.js",
30
- "./express": "./express/index.js",
31
- "./browser": {
32
- "types": "./browser/index.d.ts",
33
- "import": "./browser/index.js",
34
- "default": "./browser/uql-browser.min.js"
35
- }
36
- },
37
- "sideEffects": false,
38
- "scripts": {
39
- "copyfiles": "copyfiles -f package.json ../../README.md ../../CHANGELOG.md dist",
40
- "compile.browser": "bunchee --clean false --no-dts ./src/browser/index.ts --sourcemap -o ./dist/browser/uql-browser.min.js",
41
- "build": "bun run clean && tsc -b tsconfig.build.json && bun run compile.browser && bun run copyfiles",
42
- "start": "tsc --watch",
43
- "clean": "rimraf dist *.tsbuildinfo"
44
- },
45
- "dependencies": {
46
- "reflect-metadata": "^0.2.2",
47
- "sqlstring": "^2.3.3",
48
- "sqlstring-sqlite": "^0.1.1",
49
- "tslib": "^2.8.1"
50
- },
51
- "peerDependencies": {
52
- "better-sqlite3": ">=9.0.0",
53
- "express": ">=5.0.0",
54
- "mariadb": ">=3.0.0",
55
- "mongodb": ">=6.0.0",
56
- "mysql2": ">=3.0.0",
57
- "pg": ">=8.0.0"
58
- },
59
- "peerDependenciesMeta": {
60
- "express": {
61
- "optional": true
62
- },
63
- "mariadb": {
64
- "optional": true
65
- },
66
- "mongodb": {
67
- "optional": true
68
- },
69
- "mysql2": {
70
- "optional": true
71
- },
72
- "pg": {
73
- "optional": true
74
- },
75
- "better-sqlite3": {
76
- "optional": true
77
- }
78
- },
79
- "devDependencies": {
80
- "@types/better-sqlite3": "^7.6.13",
81
- "@types/express": "^5.0.6",
82
- "@types/node": "^25.0.3",
83
- "@types/pg": "^8.16.0",
84
- "@types/sqlstring": "^2.3.2",
85
- "better-sqlite3": "^12.5.0",
86
- "bunchee": "^6.9.1",
87
- "copyfiles": "^2.4.1",
88
- "express": "^5.2.1",
89
- "mariadb": "^3.4.5",
90
- "mongodb": "^7.0.0",
91
- "mysql2": "^3.16.0",
92
- "pg": "^8.16.3",
93
- "rimraf": "^6.1.2",
94
- "typescript": "~5.4.5"
95
- },
96
- "author": "Roger Padilla",
97
- "repository": {
98
- "type": "git",
99
- "url": "https://github.com/rogerpadilla/uql.git"
100
- },
101
- "bugs": {
102
- "url": "https://github.com/rogerpadilla/uql/issues"
103
- },
104
- "keywords": [
105
- "orm",
106
- "data-mapper",
107
- "persistence",
108
- "typescript-orm",
109
- "javascript-orm",
110
- "mariadb",
111
- "mariadb-orm",
112
- "mysql",
113
- "mysql-orm",
114
- "postgresql",
115
- "postgresql-orm",
116
- "sqlite",
117
- "sqlite-orm",
118
- "mongodb",
119
- "mongodb-orm",
120
- "entity",
121
- "dao",
122
- "transaction",
123
- "repository",
124
- "service",
125
- "migrations"
126
- ],
127
- "publishConfig": {
128
- "access": "public"
129
- },
130
- "gitHead": "e866a829b6d8c55457c2708e53aa758c08280a37"
131
- }
@@ -1 +0,0 @@
1
- import './jest';
@@ -1,6 +0,0 @@
1
- /** biome-ignore-all lint/style/noNamespace: compat */
2
- declare namespace jest {
3
- export interface Expect {
4
- toMatch: (received: RegExp) => any;
5
- }
6
- }
@@ -1,22 +0,0 @@
1
- import { expect, it } from 'bun:test';
2
- import type { RequestNotification } from '../type/index.js';
3
- import { notify, on } from './bus.js';
4
-
5
- it('bus', () => {
6
- const off = on((msg) => {
7
- const expected: RequestNotification = {
8
- phase: 'start',
9
- opts: {
10
- silent: true,
11
- },
12
- };
13
- expect(msg).toEqual(expected);
14
- off();
15
- });
16
- notify({
17
- phase: 'start',
18
- opts: {
19
- silent: true,
20
- },
21
- });
22
- });
@@ -1,17 +0,0 @@
1
- import type { RequestCallback, RequestNotification } from '../type/index.js';
2
-
3
- const subscriptors: RequestCallback[] = [];
4
-
5
- export function notify(notification: RequestNotification): void {
6
- for (const subscriptor of subscriptors) {
7
- subscriptor(notification);
8
- }
9
- }
10
-
11
- export function on(cb: RequestCallback): () => void {
12
- subscriptors.push(cb);
13
- const index = subscriptors.length - 1;
14
- return (): void => {
15
- subscriptors.splice(index, 1);
16
- };
17
- }
@@ -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
- }
@@ -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
- }
@@ -1,2 +0,0 @@
1
- export * from './bus.js';
2
- export * from './http.js';
@@ -1,4 +0,0 @@
1
- export * from './http/index.js';
2
- export * from './options.js';
3
- export * from './querier/index.js';
4
- export * from './type/index.js';
@@ -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
- });
@@ -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,3 +0,0 @@
1
- export * from './genericClientRepository.js';
2
- export * from './httpQuerier.js';
3
- export * from './querier.util.js';
@@ -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
- }