laravel-query-gate-sdk 1.0.0 → 1.0.1

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/README.md CHANGED
@@ -221,8 +221,6 @@ const posts = await queryGate<PostContract>('posts')
221
221
  .filter('status', 'eq', 'published')
222
222
  .filter('author_id', 'eq', 1)
223
223
  .sort('created_at', 'desc')
224
- .page(1)
225
- .perPage(10)
226
224
  .get()
227
225
  ```
228
226
 
@@ -358,11 +356,56 @@ queryGate<PostContract>('posts')
358
356
 
359
357
  ### Pagination
360
358
 
359
+ The SDK supports both Laravel pagination methods. The backend controls items per page.
360
+
361
+ #### Standard Pagination (Laravel `paginate()`)
362
+
361
363
  ```typescript
362
- queryGate<PostContract>('posts')
363
- .page(2)
364
- .perPage(25)
365
- .get()
364
+ import type { PaginateResponse } from 'laravel-query-gate-sdk'
365
+
366
+ // First page
367
+ const posts = await queryGate<PostContract>('posts')
368
+ .paginate()
369
+ .get() as PaginateResponse<Post>
370
+
371
+ // Specific page
372
+ const page2 = await queryGate<PostContract>('posts')
373
+ .paginate(2)
374
+ .get() as PaginateResponse<Post>
375
+
376
+ // Response includes: current_page, data, first_page_url, last_page, total, etc.
377
+ console.log(posts.data) // Post[]
378
+ console.log(posts.current_page) // 1
379
+ console.log(posts.last_page) // 10
380
+ console.log(posts.total) // 100
381
+ ```
382
+
383
+ #### Cursor Pagination (Laravel `cursorPaginate()`)
384
+
385
+ ```typescript
386
+ import type { CursorPaginateResponse } from 'laravel-query-gate-sdk'
387
+
388
+ // First page
389
+ const posts = await queryGate<PostContract>('posts')
390
+ .cursor()
391
+ .get() as CursorPaginateResponse<Post>
392
+
393
+ // Next page using cursor from previous response
394
+ const nextPage = await queryGate<PostContract>('posts')
395
+ .cursor(posts.next_cursor)
396
+ .get() as CursorPaginateResponse<Post>
397
+
398
+ // Response includes: data, next_cursor, prev_cursor, next_page_url, prev_page_url
399
+ console.log(posts.data) // Post[]
400
+ console.log(posts.next_cursor) // "eyJjcmVhdGVkX2F0Ijoi..."
401
+ ```
402
+
403
+ #### No Pagination (Fetch All)
404
+
405
+ ```typescript
406
+ // Without .paginate() or .cursor(), fetches all records
407
+ const allPosts = await queryGate<PostContract>('posts').get()
408
+ // allPosts: Post[]
366
409
  ```
367
410
 
368
411
  ## Versioning
@@ -628,8 +671,8 @@ Create an isolated SDK instance with its own configuration.
628
671
  | `.id(id)` | Set resource ID for single resource operations |
629
672
  | `.filter(field, operator, value)` | Add a filter |
630
673
  | `.sort(field, direction?)` | Add sorting (default: 'asc') |
631
- | `.page(page)` | Set page number |
632
- | `.perPage(count)` | Set items per page |
674
+ | `.paginate(page?)` | Use standard pagination (Laravel `paginate()`) |
675
+ | `.cursor(cursor?)` | Use cursor pagination (Laravel `cursorPaginate()`) |
633
676
  | `.version(version)` | Set API version header |
634
677
  | `.header(key, value)` | Add a single header |
635
678
  | `.headers(record)` | Add multiple headers |
@@ -659,6 +702,9 @@ import type {
659
702
  SortDirection,
660
703
  QueryGateConfig,
661
704
  ValidationErrors,
705
+ // Pagination response types
706
+ PaginateResponse,
707
+ CursorPaginateResponse,
662
708
  } from 'laravel-query-gate-sdk'
663
709
  ```
664
710
 
package/dist/index.d.mts CHANGED
@@ -48,6 +48,62 @@ interface RequestConfig {
48
48
  headers: Record<string, string>;
49
49
  fetchOptions: RequestInit;
50
50
  }
51
+ /**
52
+ * Pagination type
53
+ */
54
+ type PaginationType = 'paginate' | 'cursor';
55
+ /**
56
+ * Paginate pagination state (Laravel paginate())
57
+ */
58
+ interface PaginatePaginationState {
59
+ type: 'paginate';
60
+ page?: number;
61
+ }
62
+ /**
63
+ * Cursor pagination state (Laravel cursorPaginate())
64
+ */
65
+ interface CursorPaginationState {
66
+ type: 'cursor';
67
+ cursor?: string | null;
68
+ }
69
+ /**
70
+ * Union of pagination states
71
+ */
72
+ type PaginationState = PaginatePaginationState | CursorPaginationState | null;
73
+ /**
74
+ * Laravel paginate response shape
75
+ */
76
+ interface PaginateResponse<T> {
77
+ current_page: number;
78
+ data: T[];
79
+ first_page_url: string;
80
+ from: number | null;
81
+ last_page: number;
82
+ last_page_url: string;
83
+ links: Array<{
84
+ url: string | null;
85
+ label: string;
86
+ active: boolean;
87
+ }>;
88
+ next_page_url: string | null;
89
+ path: string;
90
+ per_page: number;
91
+ prev_page_url: string | null;
92
+ to: number | null;
93
+ total: number;
94
+ }
95
+ /**
96
+ * Laravel cursor paginate response shape
97
+ */
98
+ interface CursorPaginateResponse<T> {
99
+ data: T[];
100
+ path: string;
101
+ per_page: number;
102
+ next_cursor: string | null;
103
+ next_page_url: string | null;
104
+ prev_cursor: string | null;
105
+ prev_page_url: string | null;
106
+ }
51
107
  /**
52
108
  * Internal request state
53
109
  */
@@ -56,10 +112,7 @@ interface RequestState {
56
112
  id?: string | number;
57
113
  filters: FilterDefinition[];
58
114
  sorts: SortDefinition[];
59
- pagination: {
60
- page?: number;
61
- perPage?: number;
62
- };
115
+ pagination: PaginationState;
63
116
  version?: string;
64
117
  action?: string;
65
118
  headers: Record<string, string>;
@@ -199,13 +252,15 @@ declare class QueryGateBuilder<TContract extends ResourceContract> {
199
252
  */
200
253
  sort(field: string, direction?: SortDirection): QueryGateBuilder<TContract>;
201
254
  /**
202
- * Set pagination page
255
+ * Set standard pagination (Laravel paginate())
256
+ * @param page - Page number (optional)
203
257
  */
204
- page(page: number): QueryGateBuilder<TContract>;
258
+ paginate(page?: number): QueryGateBuilder<TContract>;
205
259
  /**
206
- * Set items per page
260
+ * Set cursor pagination (Laravel cursorPaginate())
261
+ * @param cursor - Cursor string (optional, null for first page)
207
262
  */
208
- perPage(perPage: number): QueryGateBuilder<TContract>;
263
+ cursor(cursor?: string | null): QueryGateBuilder<TContract>;
209
264
  /**
210
265
  * Set API version header
211
266
  */
@@ -490,4 +545,4 @@ declare function isServerError(error: unknown): error is QueryGateServerError;
490
545
  */
491
546
  declare function isServiceUnavailableError(error: unknown): error is QueryGateServiceUnavailableError;
492
547
 
493
- export { ActionBuilderNoPayload, ActionBuilderWithPayload, type ActionContract, type FilterDefinition, type FilterOperator, QueryGateBuilder, QueryGateBuilderWithId, type QueryGateConfig, QueryGateCsrfMismatchError, QueryGateError, QueryGateForbiddenError, QueryGateHttpError, QueryGateNetworkError, QueryGateNotFoundError, QueryGateRateLimitError, QueryGateServerError, QueryGateServiceUnavailableError, QueryGateUnauthorizedError, QueryGateValidationError, type RequestConfig, type RequestState, type ResourceContract, type SortDefinition, type SortDirection, type ValidationErrors, configureQueryGate, createQueryGate, getQueryGateConfig, isCsrfMismatchError, isForbiddenError, isHttpError, isNetworkError, isNotFoundError, isQueryGateError, isRateLimitError, isServerError, isServiceUnavailableError, isUnauthorizedError, isValidationError, queryGate, resetQueryGateConfig };
548
+ export { ActionBuilderNoPayload, ActionBuilderWithPayload, type ActionContract, type CursorPaginateResponse, type CursorPaginationState, type FilterDefinition, type FilterOperator, type PaginatePaginationState, type PaginateResponse, type PaginationState, type PaginationType, QueryGateBuilder, QueryGateBuilderWithId, type QueryGateConfig, QueryGateCsrfMismatchError, QueryGateError, QueryGateForbiddenError, QueryGateHttpError, QueryGateNetworkError, QueryGateNotFoundError, QueryGateRateLimitError, QueryGateServerError, QueryGateServiceUnavailableError, QueryGateUnauthorizedError, QueryGateValidationError, type RequestConfig, type RequestState, type ResourceContract, type SortDefinition, type SortDirection, type ValidationErrors, configureQueryGate, createQueryGate, getQueryGateConfig, isCsrfMismatchError, isForbiddenError, isHttpError, isNetworkError, isNotFoundError, isQueryGateError, isRateLimitError, isServerError, isServiceUnavailableError, isUnauthorizedError, isValidationError, queryGate, resetQueryGateConfig };
package/dist/index.d.ts CHANGED
@@ -48,6 +48,62 @@ interface RequestConfig {
48
48
  headers: Record<string, string>;
49
49
  fetchOptions: RequestInit;
50
50
  }
51
+ /**
52
+ * Pagination type
53
+ */
54
+ type PaginationType = 'paginate' | 'cursor';
55
+ /**
56
+ * Paginate pagination state (Laravel paginate())
57
+ */
58
+ interface PaginatePaginationState {
59
+ type: 'paginate';
60
+ page?: number;
61
+ }
62
+ /**
63
+ * Cursor pagination state (Laravel cursorPaginate())
64
+ */
65
+ interface CursorPaginationState {
66
+ type: 'cursor';
67
+ cursor?: string | null;
68
+ }
69
+ /**
70
+ * Union of pagination states
71
+ */
72
+ type PaginationState = PaginatePaginationState | CursorPaginationState | null;
73
+ /**
74
+ * Laravel paginate response shape
75
+ */
76
+ interface PaginateResponse<T> {
77
+ current_page: number;
78
+ data: T[];
79
+ first_page_url: string;
80
+ from: number | null;
81
+ last_page: number;
82
+ last_page_url: string;
83
+ links: Array<{
84
+ url: string | null;
85
+ label: string;
86
+ active: boolean;
87
+ }>;
88
+ next_page_url: string | null;
89
+ path: string;
90
+ per_page: number;
91
+ prev_page_url: string | null;
92
+ to: number | null;
93
+ total: number;
94
+ }
95
+ /**
96
+ * Laravel cursor paginate response shape
97
+ */
98
+ interface CursorPaginateResponse<T> {
99
+ data: T[];
100
+ path: string;
101
+ per_page: number;
102
+ next_cursor: string | null;
103
+ next_page_url: string | null;
104
+ prev_cursor: string | null;
105
+ prev_page_url: string | null;
106
+ }
51
107
  /**
52
108
  * Internal request state
53
109
  */
@@ -56,10 +112,7 @@ interface RequestState {
56
112
  id?: string | number;
57
113
  filters: FilterDefinition[];
58
114
  sorts: SortDefinition[];
59
- pagination: {
60
- page?: number;
61
- perPage?: number;
62
- };
115
+ pagination: PaginationState;
63
116
  version?: string;
64
117
  action?: string;
65
118
  headers: Record<string, string>;
@@ -199,13 +252,15 @@ declare class QueryGateBuilder<TContract extends ResourceContract> {
199
252
  */
200
253
  sort(field: string, direction?: SortDirection): QueryGateBuilder<TContract>;
201
254
  /**
202
- * Set pagination page
255
+ * Set standard pagination (Laravel paginate())
256
+ * @param page - Page number (optional)
203
257
  */
204
- page(page: number): QueryGateBuilder<TContract>;
258
+ paginate(page?: number): QueryGateBuilder<TContract>;
205
259
  /**
206
- * Set items per page
260
+ * Set cursor pagination (Laravel cursorPaginate())
261
+ * @param cursor - Cursor string (optional, null for first page)
207
262
  */
208
- perPage(perPage: number): QueryGateBuilder<TContract>;
263
+ cursor(cursor?: string | null): QueryGateBuilder<TContract>;
209
264
  /**
210
265
  * Set API version header
211
266
  */
@@ -490,4 +545,4 @@ declare function isServerError(error: unknown): error is QueryGateServerError;
490
545
  */
491
546
  declare function isServiceUnavailableError(error: unknown): error is QueryGateServiceUnavailableError;
492
547
 
493
- export { ActionBuilderNoPayload, ActionBuilderWithPayload, type ActionContract, type FilterDefinition, type FilterOperator, QueryGateBuilder, QueryGateBuilderWithId, type QueryGateConfig, QueryGateCsrfMismatchError, QueryGateError, QueryGateForbiddenError, QueryGateHttpError, QueryGateNetworkError, QueryGateNotFoundError, QueryGateRateLimitError, QueryGateServerError, QueryGateServiceUnavailableError, QueryGateUnauthorizedError, QueryGateValidationError, type RequestConfig, type RequestState, type ResourceContract, type SortDefinition, type SortDirection, type ValidationErrors, configureQueryGate, createQueryGate, getQueryGateConfig, isCsrfMismatchError, isForbiddenError, isHttpError, isNetworkError, isNotFoundError, isQueryGateError, isRateLimitError, isServerError, isServiceUnavailableError, isUnauthorizedError, isValidationError, queryGate, resetQueryGateConfig };
548
+ export { ActionBuilderNoPayload, ActionBuilderWithPayload, type ActionContract, type CursorPaginateResponse, type CursorPaginationState, type FilterDefinition, type FilterOperator, type PaginatePaginationState, type PaginateResponse, type PaginationState, type PaginationType, QueryGateBuilder, QueryGateBuilderWithId, type QueryGateConfig, QueryGateCsrfMismatchError, QueryGateError, QueryGateForbiddenError, QueryGateHttpError, QueryGateNetworkError, QueryGateNotFoundError, QueryGateRateLimitError, QueryGateServerError, QueryGateServiceUnavailableError, QueryGateUnauthorizedError, QueryGateValidationError, type RequestConfig, type RequestState, type ResourceContract, type SortDefinition, type SortDirection, type ValidationErrors, configureQueryGate, createQueryGate, getQueryGateConfig, isCsrfMismatchError, isForbiddenError, isHttpError, isNetworkError, isNotFoundError, isQueryGateError, isRateLimitError, isServerError, isServiceUnavailableError, isUnauthorizedError, isValidationError, queryGate, resetQueryGateConfig };
package/dist/index.js CHANGED
@@ -248,11 +248,16 @@ function buildUrl(config, state) {
248
248
  const sortValue = state.sorts.map((s) => `${s.field}:${s.direction}`).join(",");
249
249
  params.append("sort", sortValue);
250
250
  }
251
- if (state.pagination.page !== void 0) {
252
- params.append("page", String(state.pagination.page));
253
- }
254
- if (state.pagination.perPage !== void 0) {
255
- params.append("per_page", String(state.pagination.perPage));
251
+ if (state.pagination) {
252
+ if (state.pagination.type === "paginate") {
253
+ if (state.pagination.page !== void 0) {
254
+ params.append("page", String(state.pagination.page));
255
+ }
256
+ } else if (state.pagination.type === "cursor") {
257
+ if (state.pagination.cursor !== void 0 && state.pagination.cursor !== null) {
258
+ params.append("cursor", state.pagination.cursor);
259
+ }
260
+ }
256
261
  }
257
262
  const queryString = params.toString();
258
263
  return queryString ? `${baseUrl}${path}?${queryString}` : `${baseUrl}${path}`;
@@ -359,7 +364,7 @@ function createInitialState(resource) {
359
364
  resource,
360
365
  filters: [],
361
366
  sorts: [],
362
- pagination: {},
367
+ pagination: null,
363
368
  headers: {},
364
369
  fetchOptions: {}
365
370
  };
@@ -369,7 +374,7 @@ function cloneState(state) {
369
374
  ...state,
370
375
  filters: [...state.filters],
371
376
  sorts: [...state.sorts],
372
- pagination: { ...state.pagination },
377
+ pagination: state.pagination ? { ...state.pagination } : null,
373
378
  headers: { ...state.headers },
374
379
  fetchOptions: { ...state.fetchOptions }
375
380
  };
@@ -570,19 +575,33 @@ var QueryGateBuilder = class _QueryGateBuilder {
570
575
  return new _QueryGateBuilder(this.config, newState);
571
576
  }
572
577
  /**
573
- * Set pagination page
578
+ * Set standard pagination (Laravel paginate())
579
+ * @param page - Page number (optional)
574
580
  */
575
- page(page) {
581
+ paginate(page) {
576
582
  const newState = cloneState(this.state);
577
- newState.pagination.page = page;
583
+ const paginationState = {
584
+ type: "paginate"
585
+ };
586
+ if (page !== void 0) {
587
+ paginationState.page = page;
588
+ }
589
+ newState.pagination = paginationState;
578
590
  return new _QueryGateBuilder(this.config, newState);
579
591
  }
580
592
  /**
581
- * Set items per page
593
+ * Set cursor pagination (Laravel cursorPaginate())
594
+ * @param cursor - Cursor string (optional, null for first page)
582
595
  */
583
- perPage(perPage) {
596
+ cursor(cursor) {
584
597
  const newState = cloneState(this.state);
585
- newState.pagination.perPage = perPage;
598
+ const paginationState = {
599
+ type: "cursor"
600
+ };
601
+ if (cursor !== void 0) {
602
+ paginationState.cursor = cursor;
603
+ }
604
+ newState.pagination = paginationState;
586
605
  return new _QueryGateBuilder(this.config, newState);
587
606
  }
588
607
  /**
package/dist/index.mjs CHANGED
@@ -192,11 +192,16 @@ function buildUrl(config, state) {
192
192
  const sortValue = state.sorts.map((s) => `${s.field}:${s.direction}`).join(",");
193
193
  params.append("sort", sortValue);
194
194
  }
195
- if (state.pagination.page !== void 0) {
196
- params.append("page", String(state.pagination.page));
197
- }
198
- if (state.pagination.perPage !== void 0) {
199
- params.append("per_page", String(state.pagination.perPage));
195
+ if (state.pagination) {
196
+ if (state.pagination.type === "paginate") {
197
+ if (state.pagination.page !== void 0) {
198
+ params.append("page", String(state.pagination.page));
199
+ }
200
+ } else if (state.pagination.type === "cursor") {
201
+ if (state.pagination.cursor !== void 0 && state.pagination.cursor !== null) {
202
+ params.append("cursor", state.pagination.cursor);
203
+ }
204
+ }
200
205
  }
201
206
  const queryString = params.toString();
202
207
  return queryString ? `${baseUrl}${path}?${queryString}` : `${baseUrl}${path}`;
@@ -303,7 +308,7 @@ function createInitialState(resource) {
303
308
  resource,
304
309
  filters: [],
305
310
  sorts: [],
306
- pagination: {},
311
+ pagination: null,
307
312
  headers: {},
308
313
  fetchOptions: {}
309
314
  };
@@ -313,7 +318,7 @@ function cloneState(state) {
313
318
  ...state,
314
319
  filters: [...state.filters],
315
320
  sorts: [...state.sorts],
316
- pagination: { ...state.pagination },
321
+ pagination: state.pagination ? { ...state.pagination } : null,
317
322
  headers: { ...state.headers },
318
323
  fetchOptions: { ...state.fetchOptions }
319
324
  };
@@ -514,19 +519,33 @@ var QueryGateBuilder = class _QueryGateBuilder {
514
519
  return new _QueryGateBuilder(this.config, newState);
515
520
  }
516
521
  /**
517
- * Set pagination page
522
+ * Set standard pagination (Laravel paginate())
523
+ * @param page - Page number (optional)
518
524
  */
519
- page(page) {
525
+ paginate(page) {
520
526
  const newState = cloneState(this.state);
521
- newState.pagination.page = page;
527
+ const paginationState = {
528
+ type: "paginate"
529
+ };
530
+ if (page !== void 0) {
531
+ paginationState.page = page;
532
+ }
533
+ newState.pagination = paginationState;
522
534
  return new _QueryGateBuilder(this.config, newState);
523
535
  }
524
536
  /**
525
- * Set items per page
537
+ * Set cursor pagination (Laravel cursorPaginate())
538
+ * @param cursor - Cursor string (optional, null for first page)
526
539
  */
527
- perPage(perPage) {
540
+ cursor(cursor) {
528
541
  const newState = cloneState(this.state);
529
- newState.pagination.perPage = perPage;
542
+ const paginationState = {
543
+ type: "cursor"
544
+ };
545
+ if (cursor !== void 0) {
546
+ paginationState.cursor = cursor;
547
+ }
548
+ newState.pagination = paginationState;
530
549
  return new _QueryGateBuilder(this.config, newState);
531
550
  }
532
551
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "laravel-query-gate-sdk",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Contract-driven TypeScript SDK for Laravel Query Gate",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",