Skip to content

Commit

Permalink
Adding a standardized pagination implementation to entitlement entiti…
Browse files Browse the repository at this point in the history
…es OM-779 (#1241)

* feat: add pagination template to ent

* chore: remove stringr

* feat: add pagination to shared ent

* feat: add pagination to internal entitlement API

* style: clean up comments

* feat: add support for pagination zero value

* feat!: switch to paged pagination in API query params and internal APIs

* feat: add paginated responses to list endpoints

* fix: add items as prop when marshalling

* feat: backfill limit offset to not break API

* feat: fix regression tests

* style: fix lint

* fix: extract unions to OAPI schema to fix go client Unmarshal

* chore: rename response interface
  • Loading branch information
GAlexIHU authored Jul 26, 2024
1 parent a55ecb3 commit 55ad96f
Show file tree
Hide file tree
Showing 36 changed files with 2,680 additions and 959 deletions.
875 changes: 604 additions & 271 deletions api/api.gen.go

Large diffs are not rendered by default.

935 changes: 658 additions & 277 deletions api/client/go/client.gen.go

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions api/client/node/clients/entitlement.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { components, operations } from '../schemas/openapi.js'
import { RequestOptions, BaseClient, OpenMeterConfig } from './client.js'
import { Paginated } from './pagination.js'

export type Entitlement =
| EntitlementMetered
Expand Down Expand Up @@ -36,15 +37,13 @@ export class EntitlementClient extends BaseClient {

/**
* List all entitlements regardless of subject.
* @description
* Most useful for administrative purposes.
* @example
* const entitlement = await openmeter.entitlements.list()
*/
public async list(
params?: ListEntitlementQueryParams,
options?: RequestOptions
): Promise<Entitlement[]> {
): Promise<Entitlement[] | Paginated<Entitlement>> {
const searchParams = params
? BaseClient.toURLSearchParams(params)
: undefined
Expand Down
3 changes: 2 additions & 1 deletion api/client/node/clients/feature.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { components, operations } from '../schemas/openapi.js'
import { RequestOptions, BaseClient, OpenMeterConfig } from './client.js'
import { Paginated } from './pagination.js'

export type Feature = components['schemas']['Feature']
export type FeatureCreateInputs = components['schemas']['FeatureCreateInputs']
Expand Down Expand Up @@ -63,7 +64,7 @@ export class FeatureClient extends BaseClient {
public async list(
params?: ListFeatureQueryParams,
options?: RequestOptions
): Promise<Feature[]> {
): Promise<Feature[] | Paginated<Feature>> {
const searchParams = params
? BaseClient.toURLSearchParams(params)
: undefined
Expand Down
3 changes: 2 additions & 1 deletion api/client/node/clients/grant.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { components, operations } from '../schemas/openapi.js'
import { RequestOptions, BaseClient, OpenMeterConfig } from './client.js'
import { Paginated } from './pagination.js'

export type EntitlementGrant = components['schemas']['EntitlementGrant']
export type EntitlementGrantCreateInput =
Expand All @@ -22,7 +23,7 @@ export class GrantClient extends BaseClient {
public async list(
params?: ListGrantQueryParams,
options?: RequestOptions
): Promise<EntitlementGrant[]> {
): Promise<EntitlementGrant[] | Paginated<EntitlementGrant>> {
const searchParams = params
? BaseClient.toURLSearchParams(params)
: undefined
Expand Down
6 changes: 6 additions & 0 deletions api/client/node/clients/pagination.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface Paginated<T> {
items: T[]
totalCount: number
page: number
pageSize: number
}
115 changes: 107 additions & 8 deletions api/client/node/schemas/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@
* Do not make direct changes to the file.
*/

/** OneOf type helpers */
type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never }
type XOR<T, U> = T | U extends object
? (Without<T, U> & U) | (Without<U, T> & T)
: T | U
type OneOf<T extends any[]> = T extends [infer Only]
? Only
: T extends [infer A, infer B, ...infer Rest]
? OneOf<[XOR<A, B>, ...Rest]>
: never

export interface paths {
'/api/v1/events': {
/**
Expand Down Expand Up @@ -127,13 +138,14 @@ export interface paths {
/**
* List entitlements
* @description List all entitlements regardless of subject. This endpoint is intended for administrative purposes.
* If page is provided that takes precedence and the paginated response is returned.
*/
get: operations['listEntitlements']
}
'/api/v1/features': {
/**
* List features
* @description List all features.
* @description List all features. If page is provided that takes precedence and the paginated response is returned.
*/
get: operations['listFeatures']
/**
Expand Down Expand Up @@ -161,6 +173,8 @@ export interface paths {
/**
* List grants
* @description List all grants for all the subjects and entitlements. This endpoint is intended for administrative purposes only. To fetch the grants of a specific entitlement please use the /api/v1/subjects/{subjectKeyOrID}/entitlements/{entitlementOrFeatureID}/grants endpoint.
*
* If page is provided that takes precedence and the paginated response is returned.
*/
get: operations['listGrants']
}
Expand Down Expand Up @@ -610,6 +624,30 @@ export interface components {
archivedAt?: string
} & components['schemas']['FeatureCreateInputs'] &
components['schemas']['SharedMetaFields']
ListFeatureResponse: OneOf<
[
components['schemas']['Feature'][],
{
/**
* @description Total number of features.
* @example 500
*/
totalCount: number
/**
* @description Current page number.
* @example 1
*/
page: number
/**
* @description Number of features per page.
* @example 100
*/
pageSize: number
/** @description List of features. */
items: components['schemas']['Feature'][]
},
]
>
/** @description Limited representation of a feature resource which includes only its unique identifiers (id, key). */
FeatureMeta: {
/**
Expand Down Expand Up @@ -754,6 +792,30 @@ export interface components {
| components['schemas']['EntitlementMetered']
| components['schemas']['EntitlementStatic']
| components['schemas']['EntitlementBoolean']
ListEntitlementResponse: OneOf<
[
components['schemas']['Entitlement'][],
{
/**
* @description Total number of entitlements.
* @example 500
*/
totalCount: number
/**
* @description Current page number.
* @example 1
*/
page: number
/**
* @description Number of entitlements per page.
* @example 100
*/
pageSize: number
/** @description List of entitlements. */
items: components['schemas']['Entitlement'][]
},
]
>
/**
* @description A segment of the grant burn down history.
*
Expand Down Expand Up @@ -994,6 +1056,30 @@ export interface components {
voidedAt?: string
recurrence?: components['schemas']['RecurringPeriod']
}
ListEntitlementGrantResponse: OneOf<
[
components['schemas']['EntitlementGrant'][],
{
/**
* @description Total number of grants.
* @example 500
*/
totalCount: number
/**
* @description Current page number.
* @example 1
*/
page: number
/**
* @description Number of grants per page.
* @example 100
*/
pageSize: number
/** @description List of grants. */
items: components['schemas']['EntitlementGrant'][]
},
]
>
EntitlementValue: {
/**
* @description Whether the subject has access to the feature. Shared accross all entitlement types.
Expand Down Expand Up @@ -1640,6 +1726,10 @@ export interface components {
entitlementIdOrFeatureKey: string
/** @description Include deleted entries. */
includeDeleted?: boolean
/** @description Page number to return */
queryPage?: number
/** @description Number of entries to return per page */
queryPageSize?: number
/** @description Number of entries to return */
queryLimit?: number
/** @description Number of entries to skip */
Expand Down Expand Up @@ -2105,21 +2195,24 @@ export interface operations {
/**
* List entitlements
* @description List all entitlements regardless of subject. This endpoint is intended for administrative purposes.
* If page is provided that takes precedence and the paginated response is returned.
*/
listEntitlements: {
parameters: {
query?: {
page?: components['parameters']['queryPage']
pageSize?: components['parameters']['queryPageSize']
limit?: components['parameters']['queryLimit']
offset?: components['parameters']['queryOffset']
/** @description Order by field */
orderBy?: 'createdAt' | 'updatedAt'
}
}
responses: {
/** @description List of entitlements. */
/** @description List of entitlements. If page is provided that takes precedence and the paginated response is returned. */
200: {
content: {
'application/json': components['schemas']['Entitlement'][]
'application/json': components['schemas']['ListEntitlementResponse']
}
}
400: components['responses']['BadRequestProblemResponse']
Expand All @@ -2129,11 +2222,13 @@ export interface operations {
}
/**
* List features
* @description List all features.
* @description List all features. If page is provided that takes precedence and the paginated response is returned.
*/
listFeatures: {
parameters: {
query?: {
page?: components['parameters']['queryPage']
pageSize?: components['parameters']['queryPageSize']
limit?: components['parameters']['queryLimit']
offset?: components['parameters']['queryOffset']
/** @description Order by field */
Expand All @@ -2143,10 +2238,10 @@ export interface operations {
}
}
responses: {
/** @description List of features. */
/** @description List of features. If page is provided that takes precedence and the paginated response is returned. */
200: {
content: {
'application/json': components['schemas']['Feature'][]
'application/json': components['schemas']['ListFeatureResponse']
}
}
400: components['responses']['BadRequestProblemResponse']
Expand Down Expand Up @@ -2226,10 +2321,14 @@ export interface operations {
/**
* List grants
* @description List all grants for all the subjects and entitlements. This endpoint is intended for administrative purposes only. To fetch the grants of a specific entitlement please use the /api/v1/subjects/{subjectKeyOrID}/entitlements/{entitlementOrFeatureID}/grants endpoint.
*
* If page is provided that takes precedence and the paginated response is returned.
*/
listGrants: {
parameters: {
query?: {
page?: components['parameters']['queryPage']
pageSize?: components['parameters']['queryPageSize']
limit?: components['parameters']['queryLimit']
offset?: components['parameters']['queryOffset']
/** @description Order by field */
Expand All @@ -2238,10 +2337,10 @@ export interface operations {
}
}
responses: {
/** @description List of grants. */
/** @description List of grants. If page is provided that takes precedence and the paginated response is returned. */
200: {
content: {
'application/json': components['schemas']['EntitlementGrant'][]
'application/json': components['schemas']['ListEntitlementGrantResponse']
}
}
401: components['responses']['UnauthorizedProblemResponse']
Expand Down
Loading

0 comments on commit 55ad96f

Please sign in to comment.