Skip to content

Commit 71a8f06

Browse files
committed
Fixed ts errors,
Added types to with(), .withCount(), .withExists()
1 parent 8dbbdf8 commit 71a8f06

File tree

5 files changed

+71
-58
lines changed

5 files changed

+71
-58
lines changed

src/drivers/default/builders/queryBuilder.ts

Lines changed: 43 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
1-
import {HttpMethod} from '../enums/httpMethod';
2-
import {Model} from '../../../model';
3-
import {ModelConstructor} from '../../../contracts/modelConstructor';
4-
import {Scope} from '../scope';
5-
import {Filter} from '../filter';
6-
import {FilterOperator} from '../enums/filterOperator';
7-
import {FilterType} from '../enums/filterType';
8-
import {Sorter} from '../sorter';
9-
import {SortDirection} from '../enums/sortDirection';
10-
import {UrlBuilder} from '../../../builders/urlBuilder';
11-
import {ExtractModelAttributesType} from '../../../types/extractModelAttributesType';
1+
import { HttpMethod } from '../enums/httpMethod';
2+
import { Model } from '../../../model';
3+
import { ModelConstructor } from '../../../contracts/modelConstructor';
4+
import { Scope } from '../scope';
5+
import { Filter } from '../filter';
6+
import { FilterOperator } from '../enums/filterOperator';
7+
import { FilterType } from '../enums/filterType';
8+
import { Sorter } from '../sorter';
9+
import { SortDirection } from '../enums/sortDirection';
10+
import { UrlBuilder } from '../../../builders/urlBuilder';
11+
import { ExtractModelAttributesType } from '../../../types/extractModelAttributesType';
1212
import {
1313
ExtractModelPersistedAttributesType
1414
} from '../../../types/extractModelPersistedAttributesType';
15-
import {ExtractModelRelationsType} from '../../../types/extractModelRelationsType';
16-
import {HttpClient} from '../../../httpClient';
17-
import {AxiosResponse} from 'axios';
18-
import {Orion} from '../../../orion';
19-
import {ExtractModelKeyType} from '../../../types/extractModelKeyType';
15+
import { ExtractModelRelationsType } from '../../../types/extractModelRelationsType';
16+
import { HttpClient } from '../../../httpClient';
17+
import { AxiosResponse } from 'axios';
18+
import { Orion } from '../../../orion';
19+
import { ExtractModelKeyType } from '../../../types/extractModelKeyType';
2020
import { AggregateItem } from '../../../types/AggregateItem';
21+
import { ModelRelations } from '../../../types/ModelRelations';
2122

2223
export class QueryBuilder<
2324
M extends Model,
@@ -31,11 +32,11 @@ export class QueryBuilder<
3132
protected modelConstructor: ModelConstructor<M, Attributes, PersistedAttributes, Relations, Key>;
3233
protected httpClient: HttpClient;
3334

34-
protected includes: string[] = [];
35+
protected includes: ModelRelations<Relations>[] = [];
3536
protected fetchTrashed: boolean = false;
3637
protected fetchOnlyTrashed: boolean = false;
37-
protected withCountRelations: string[] = [];
38-
protected withExistsRelations: string[] = [];
38+
protected withCountRelations: ModelRelations<Relations>[] = [];
39+
protected withExistsRelations: ModelRelations<Relations>[] = [];
3940
protected withAvgRelations: AggregateItem<Relations>[] = [];
4041
protected withSumRelations: AggregateItem<Relations>[] = [];
4142
protected withMinRelations: AggregateItem<Relations>[] = [];
@@ -64,7 +65,7 @@ export class QueryBuilder<
6465
const response = await this.httpClient.request<{ data: Array<AllAttributes & Relations> }>(
6566
'',
6667
HttpMethod.GET,
67-
this.prepareQueryParams({limit, page})
68+
this.prepareQueryParams({ limit, page })
6869
);
6970

7071
return response.data.data.map((attributes: AllAttributes & Relations) => {
@@ -76,12 +77,12 @@ export class QueryBuilder<
7677
const response = await this.httpClient.request<{ data: Array<AllAttributes & Relations> }>(
7778
'/search',
7879
HttpMethod.POST,
79-
this.prepareQueryParams({limit, page}),
80+
this.prepareQueryParams({ limit, page }),
8081
{
8182
scopes: this.scopes,
8283
filters: this.filters,
83-
search: {value: this.searchValue},
84-
sort: this.sorters,
84+
search: { value: this.searchValue },
85+
sort: this.sorters
8586
}
8687
);
8788

@@ -116,7 +117,7 @@ export class QueryBuilder<
116117
resources: items.map(x => x.$attributes)
117118
};
118119

119-
const response = await this.httpClient.request<{data: Array<AllAttributes & Relations> }>(
120+
const response = await this.httpClient.request<{ data: Array<AllAttributes & Relations> }>(
120121
`/batch`,
121122
HttpMethod.POST,
122123
null,
@@ -125,7 +126,7 @@ export class QueryBuilder<
125126

126127
return response.data.data.map((attributes) => {
127128
return this.hydrate(attributes, response);
128-
})
129+
});
129130
}
130131

131132
public async update(key: Key, attributes: Attributes): Promise<M> {
@@ -145,12 +146,12 @@ export class QueryBuilder<
145146
};
146147
items.forEach((v) => data.resources[v.$getKey()] = v.$attributes);
147148

148-
const response = await this.httpClient.request<{ data: Array< AllAttributes & Relations > }>(
149+
const response = await this.httpClient.request<{ data: Array<AllAttributes & Relations> }>(
149150
`batch`,
150151
HttpMethod.PATCH,
151152
null,
152153
data
153-
)
154+
);
154155

155156
return response.data.data.map((attributes: AllAttributes & Relations) => {
156157
return this.hydrate(attributes, response);
@@ -161,22 +162,21 @@ export class QueryBuilder<
161162
const response = await this.httpClient.request<{ data: AllAttributes & Relations }>(
162163
`/${key}`,
163164
HttpMethod.DELETE,
164-
this.prepareQueryParams({force})
165+
this.prepareQueryParams({ force })
165166
);
166167

167168
return this.hydrate(response.data.data, response);
168169
}
169170

170-
public async batchDelete(items: Key[]): Promise<M[]>
171-
{
171+
public async batchDelete(items: Key[]): Promise<M[]> {
172172
if (!items.length)
173173
return [];
174174

175175
const data = {
176176
resources: items
177177
};
178178

179-
const response = await this.httpClient.request<{ data: Array< AllAttributes & Relations > }>(
179+
const response = await this.httpClient.request<{ data: Array<AllAttributes & Relations> }>(
180180
`/batch`,
181181
HttpMethod.DELETE,
182182
null,
@@ -203,7 +203,7 @@ export class QueryBuilder<
203203
resources: items
204204
};
205205

206-
const response = await this.httpClient.request<{ data: Array< AllAttributes & Relations > }>(
206+
const response = await this.httpClient.request<{ data: Array<AllAttributes & Relations> }>(
207207
`/batch/restore`,
208208
HttpMethod.POST,
209209
null,
@@ -216,7 +216,7 @@ export class QueryBuilder<
216216
}
217217

218218

219-
public with(relations: string[]): this {
219+
public with(relations: ModelRelations<Relations>[]): this {
220220
this.includes = relations;
221221

222222
return this;
@@ -261,7 +261,7 @@ export class QueryBuilder<
261261
public hydrate(raw: AllAttributes & Relations, response?: AxiosResponse): M {
262262
const model = new this.modelConstructor();
263263

264-
for (const field of Object.keys(raw)) {
264+
for (const field of Object.keys(raw as Record<string, unknown>)) {
265265
const rawValue = raw[field];
266266

267267
if (typeof model[field] === 'function') {
@@ -293,14 +293,14 @@ export class QueryBuilder<
293293
* The relations need to be whitelisted in the controller.
294294
* @link https://tailflow.github.io/laravel-orion-docs/v2.x/guide/search.html#aggregates
295295
*/
296-
public withCount(relations: string[] | string): this {
296+
public withCount(relations: ModelRelations<Relations>[] | ModelRelations<Relations>): this {
297297
if (!Array.isArray(relations)) {
298298
relations = [relations];
299299
}
300300

301301
this.withCountRelations.push(...relations);
302302

303-
return this
303+
return this;
304304
}
305305

306306
/**
@@ -309,14 +309,14 @@ export class QueryBuilder<
309309
* @link https://tailflow.github.io/laravel-orion-docs/v2.x/guide/search.html#aggregates
310310
* @param relations
311311
*/
312-
public withExists(relations: string[] | string): this {
312+
public withExists(relations: ModelRelations<Relations>[] | ModelRelations<Relations>): this {
313313
if (!Array.isArray(relations)) {
314314
relations = [relations];
315315
}
316316

317317
this.withExistsRelations.push(...relations);
318318

319-
return this
319+
return this;
320320
}
321321

322322
/**
@@ -332,7 +332,7 @@ export class QueryBuilder<
332332

333333
this.withAvgRelations.push(...relations);
334334

335-
return this
335+
return this;
336336
}
337337

338338
/**
@@ -348,7 +348,7 @@ export class QueryBuilder<
348348

349349
this.withSumRelations.push(...relations);
350350

351-
return this
351+
return this;
352352
}
353353

354354
/**
@@ -364,7 +364,7 @@ export class QueryBuilder<
364364

365365
this.withMinRelations.push(...relations);
366366

367-
return this
367+
return this;
368368
}
369369

370370
/**
@@ -380,7 +380,7 @@ export class QueryBuilder<
380380

381381
this.withMaxRelations.push(...relations);
382382

383-
return this
383+
return this;
384384
}
385385

386386
public getHttpClient(): HttpClient {
@@ -422,6 +422,7 @@ export class QueryBuilder<
422422

423423
if (this.withMinRelations.length > 0) {
424424
operationParams.with_min = this.withMinRelations.map((item) => {
425+
item.relation;
425426
return `${item.relation}.${item.column}`;
426427
}).join(',');
427428
}

src/types/AggregateItem.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import { ModelRelations } from './ModelRelations';
2+
13
export type AggregateItem<Relations> = {
2-
relation: keyof Relations;
4+
relation: string & ModelRelations<Relations>;
35
column: string;
46
}

src/types/ModelRelations.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { ExtractModelRelationsType } from './extractModelRelationsType';
2+
3+
export type DirectModelRelations<Relations> = string & (keyof Relations)
4+
export type ChildModelRelations<Relations> = `${DirectModelRelations<Relations>}.${DirectModelRelations<ExtractModelRelationsType<Relations[keyof Relations]>>}`
5+
6+
7+
export type ModelRelations<Relations> =
8+
DirectModelRelations<Relations>
9+
| ChildModelRelations<Relations>

tests/integration/drivers/default/builders/queryBuilder.test.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@ describe('QueryBuilder tests', () => {
5959

6060
test('retrieving a paginated list resources with included relations', async () => {
6161
const queryBuilder = new QueryBuilder<Post, PostAttributes>(Post);
62-
await queryBuilder.with(['user', 'profile']).get();
62+
await queryBuilder.with(['user']).get();
6363
const requests = server.pretender.handledRequests;
6464
expect(requests[0].queryParams).toStrictEqual({
6565
limit: '15',
6666
page: '1',
67-
include: 'user,profile'
67+
include: 'user'
6868
});
6969
});
7070

@@ -158,13 +158,13 @@ describe('QueryBuilder tests', () => {
158158

159159
test('searching for resources with included relations', async () => {
160160
const queryBuilder = new QueryBuilder<Post, PostAttributes>(Post);
161-
await queryBuilder.with(['user', 'profile']).search();
161+
await queryBuilder.with(['user']).search();
162162

163163
const requests = server.pretender.handledRequests;
164164
expect(requests[0].queryParams).toStrictEqual({
165165
limit: '15',
166166
page: '1',
167-
include: 'user,profile'
167+
include: 'user'
168168
});
169169
});
170170

@@ -181,7 +181,7 @@ describe('QueryBuilder tests', () => {
181181

182182
test('storing a resource and getting its relations', async () => {
183183
const queryBuilder = new QueryBuilder<Post, PostAttributes>(Post);
184-
const post = await queryBuilder.with(['user', 'profile']).store({
184+
const post = await queryBuilder.with(['user']).store({
185185
title: 'Test Post'
186186
});
187187

@@ -190,7 +190,7 @@ describe('QueryBuilder tests', () => {
190190
expect(server.schema.posts.find('1').attrs.title).toBe('Test Post');
191191

192192
const requests = server.pretender.handledRequests;
193-
expect(requests[0].queryParams).toStrictEqual({ include: 'user,profile' });
193+
expect(requests[0].queryParams).toStrictEqual({ include: 'user' });
194194
});
195195

196196
test('retrieving a resource', async () => {
@@ -217,13 +217,13 @@ describe('QueryBuilder tests', () => {
217217
server.schema.posts.create({ title: 'Test Post' });
218218

219219
const queryBuilder = new QueryBuilder<Post, PostAttributes>(Post);
220-
const post = await queryBuilder.with(['user', 'profile']).find('1');
220+
const post = await queryBuilder.with(['user']).find('1');
221221

222222
expect(post).toBeInstanceOf(Post);
223223
expect(post.$attributes).toStrictEqual({ id: '1', title: 'Test Post' });
224224

225225
const requests = server.pretender.handledRequests;
226-
expect(requests[0].queryParams).toStrictEqual({ include: 'user,profile' });
226+
expect(requests[0].queryParams).toStrictEqual({ include: 'user' });
227227
});
228228

229229
test('updating a resource', async () => {
@@ -243,7 +243,7 @@ describe('QueryBuilder tests', () => {
243243
server.schema.posts.create({ title: 'Test Post' });
244244

245245
const queryBuilder = new QueryBuilder<Post, PostAttributes>(Post);
246-
const post = await queryBuilder.with(['user', 'profile']).update('1', {
246+
const post = await queryBuilder.with(['user']).update('1', {
247247
title: 'Updated Post'
248248
});
249249

@@ -252,7 +252,7 @@ describe('QueryBuilder tests', () => {
252252
expect(server.schema.posts.find('1').attrs.title).toBe('Updated Post');
253253

254254
const requests = server.pretender.handledRequests;
255-
expect(requests[0].queryParams).toStrictEqual({ include: 'user,profile' });
255+
expect(requests[0].queryParams).toStrictEqual({ include: 'user' });
256256
});
257257

258258
test('updating a soft deleted resource', async () => {
@@ -290,7 +290,7 @@ describe('QueryBuilder tests', () => {
290290
server.schema.posts.create({ title: 'Test Post' });
291291

292292
const queryBuilder = new QueryBuilder<Post, PostAttributes>(Post);
293-
const post = await queryBuilder.with(['user', 'profile']).destroy('1');
293+
const post = await queryBuilder.with(['user']).destroy('1');
294294

295295
expect(post).toBeInstanceOf(Post);
296296
expect(post.$attributes).toStrictEqual({
@@ -301,7 +301,7 @@ describe('QueryBuilder tests', () => {
301301
expect(server.schema.posts.find('1').attrs.deleted_at).toBeDefined();
302302

303303
const requests = server.pretender.handledRequests;
304-
expect(requests[0].queryParams).toStrictEqual({ force: 'false', include: 'user,profile' });
304+
expect(requests[0].queryParams).toStrictEqual({ force: 'false', include: 'user' });
305305
});
306306

307307
test('restoring a resource', async () => {
@@ -319,14 +319,14 @@ describe('QueryBuilder tests', () => {
319319
server.schema.posts.create({ title: 'Test Post', deleted_at: Date.now() });
320320

321321
const queryBuilder = new QueryBuilder<Post, PostAttributes>(Post);
322-
const post = await queryBuilder.with(['user', 'profile']).restore('1');
322+
const post = await queryBuilder.with(['user']).restore('1');
323323

324324
expect(post).toBeInstanceOf(Post);
325325
expect(post.$attributes).toStrictEqual({ id: '1', title: 'Test Post', deleted_at: null });
326326
expect(server.schema.posts.find('1').attrs.deleted_at).toBeNull();
327327

328328
const requests = server.pretender.handledRequests;
329-
expect(requests[0].queryParams).toStrictEqual({ include: 'user,profile' });
329+
expect(requests[0].queryParams).toStrictEqual({ include: 'user' });
330330
});
331331

332332
test('force deleting a resource', async () => {

tests/integration/orion.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ describe('Orion tests', () => {
2929
await Orion.csrf();
3030
expect(false).toBeTruthy();
3131
} catch (error) {
32-
expect(error.message).toBe(
32+
33+
expect((error as Error).message).toBe(
3334
`Current auth driver is set to "${AuthDriver.Passport}". Fetching CSRF cookie can only be used with "sanctum" driver.`
3435
);
3536
}

0 commit comments

Comments
 (0)