Skip to content

Commit 4e4372d

Browse files
committed
feat: add install app endpoint
1 parent 3c3e56e commit 4e4372d

22 files changed

Lines changed: 1865 additions & 1136 deletions

File tree

api/spec/packages/aip-client-javascript/README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -320,13 +320,13 @@ The full call path, HTTP route, and a short description are listed below.
320320

321321
### Apps
322322

323-
| Method | HTTP | Description |
324-
| -------------------------------------------- | ----------------------------------------------------- | ---------------------------------------------- |
325-
| `client.apps.list` | `GET /openmeter/apps` | List installed apps. |
326-
| `client.apps.get` | `GET /openmeter/apps/{appId}` | Get an installed app. |
327-
| `client.apps.listCatalog` | `GET /openmeter/app-catalog` | List available apps. |
328-
| `client.apps.getCatalogItem` | `GET /openmeter/app-catalog/{appType}` | Get an app catalog item by type. |
329-
| `client.apps.getCatalogItemOauth2InstallUrl` | `GET /openmeter/app-catalog/{appType}/install/oauth2` | Get OAuth2 install URL for an app catalog item |
323+
| Method | HTTP | Description |
324+
| ---------------------------- | -------------------------------------- | -------------------------------- |
325+
| `client.apps.list` | `GET /openmeter/apps` | List installed apps. |
326+
| `client.apps.get` | `GET /openmeter/apps/{appId}` | Get an installed app. |
327+
| `client.apps.listCatalog` | `GET /openmeter/app-catalog` | List available apps. |
328+
| `client.apps.getCatalogItem` | `GET /openmeter/app-catalog/{appType}` | Get an app catalog item by type. |
329+
| `client.apps.install` | `POST /openmeter/app-catalog/install` | Install app from the catalog |
330330

331331
### Billing
332332

api/spec/packages/aip-client-javascript/src/funcs/apps.ts

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ import type {
1515
ListAppCatalogResponse,
1616
GetAppCatalogItemRequest,
1717
GetAppCatalogItemResponse,
18-
GetAppCatalogItemOauth2InstallUrlRequest,
19-
GetAppCatalogItemOauth2InstallUrlResponse,
18+
InstallAppRequest,
19+
InstallAppResponse,
2020
} from '../models/operations/apps.js'
2121

2222
/**
@@ -152,33 +152,28 @@ export function getAppCatalogItem(
152152
}
153153

154154
/**
155-
* Get OAuth2 install URL for an app catalog item
155+
* Install app from the catalog
156156
*
157-
* GET /openmeter/app-catalog/{appType}/install/oauth2
157+
* POST /openmeter/app-catalog/install
158158
*/
159-
export function getAppCatalogItemOauth2InstallUrl(
159+
export function installApp(
160160
client: Client,
161-
req: GetAppCatalogItemOauth2InstallUrlRequest,
161+
req: InstallAppRequest,
162162
options?: RequestOptions,
163-
): Promise<Result<GetAppCatalogItemOauth2InstallUrlResponse>> {
163+
): Promise<Result<InstallAppResponse>> {
164164
return request(() => {
165-
const path = `openmeter/app-catalog/${(() => {
166-
if (req.appType === undefined) {
167-
throw new Error('missing path parameter: appType')
168-
}
169-
return encodeURIComponent(String(req.appType))
170-
})()}/install/oauth2`
165+
const body = toWire(req, schemas.installAppBody)
166+
if (client._options.validate) {
167+
assertValid(schemas.installAppBodyWire, body)
168+
}
171169
return http(client)
172-
.get(path, options)
170+
.post('openmeter/app-catalog/install', { ...options, json: body })
173171
.json()
174172
.then((data) => {
175173
if (client._options.validate) {
176-
assertValid(
177-
schemas.getAppCatalogItemOauth2InstallUrlResponseWire,
178-
data,
179-
)
174+
assertValid(schemas.installAppResponseWire, data)
180175
}
181-
return fromWire(data, schemas.getAppCatalogItemOauth2InstallUrlResponse)
176+
return fromWire(data, schemas.installAppResponse)
182177
})
183178
})
184179
}

api/spec/packages/aip-client-javascript/src/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@ export type {
7373
PriceFree,
7474
RateCardStaticEntitlement,
7575
RateCardBooleanEntitlement,
76-
AppOAuth2InstallResponse,
76+
InstallAppStripeWithApiKey,
77+
InstallAppSandbox,
78+
InstallAppExternalInvoicing,
7779
WorkflowCollectionAlignmentSubscription,
7880
WorkflowPaymentChargeAutomaticallySettings,
7981
WorkflowPaymentSendInvoiceSettings,
@@ -312,6 +314,7 @@ export type {
312314
FeaturePagePaginatedResponse,
313315
Workflow,
314316
AppPagePaginatedResponse,
317+
BillingInstallAppResponse,
315318
ProfileApps,
316319
ChargeUsageBased,
317320
SubscriptionAddonRateCard,

api/spec/packages/aip-client-javascript/src/models/operations/apps.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ import type {
77
App,
88
AppCatalogItem,
99
AppCatalogItemPagePaginatedResponse,
10-
AppOAuth2InstallResponse,
1110
AppPagePaginatedResponse,
11+
BillingInstallAppResponse,
12+
InstallAppRequest as InstallAppRequestBody,
1213
} from '../types.js'
1314

1415
export interface ListAppsQuery {
@@ -37,7 +38,5 @@ export type GetAppCatalogItemRequest = {
3738
}
3839
export type GetAppCatalogItemResponse = AppCatalogItem
3940

40-
export type GetAppCatalogItemOauth2InstallUrlRequest = {
41-
appType: string
42-
}
43-
export type GetAppCatalogItemOauth2InstallUrlResponse = AppOAuth2InstallResponse
41+
export type InstallAppRequest = AcceptDateStrings<InstallAppRequestBody>
42+
export type InstallAppResponse = BillingInstallAppResponse

api/spec/packages/aip-client-javascript/src/models/schemas.ts

Lines changed: 76 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -728,16 +728,30 @@ export const appStatus = z
728728
.enum(['ready', 'unauthorized'])
729729
.describe('Connection status of an installed app.')
730730

731-
export const appOAuth2InstallResponse = z
731+
export const installAppStripeWithApiKey = z
732732
.object({
733-
url: z
734-
.string()
735-
.describe('The URL to start the OAuth2 authorization code grant flow.'),
733+
type: z.literal('stripe').describe('Type of the app.'),
734+
name: z.string().describe('Name of the app.'),
735+
createBillingProfile: z.boolean().describe('Description of the app.'),
736+
apiKey: z.string().describe('API key for the app.'),
736737
})
738+
.describe('Model for installing an app from the catalog with an API key.')
737739

738-
.describe(
739-
'Response from the billing app installation endpoint to initiate the OAuth2 authorization flow. This response contains the authorization URL where the user should be redirected to grant permissions to the application. The URL includes all necessary OAuth2 parameters such as client_id, redirect_uri, scope, and state.',
740-
)
740+
export const installAppSandbox = z
741+
.object({
742+
type: z.literal('sandbox').describe('Type of the app.'),
743+
name: z.string().describe('Name of the app.'),
744+
createBillingProfile: z.boolean().describe('Description of the app.'),
745+
})
746+
.describe('Base model for installing an app from the catalog.')
747+
748+
export const installAppExternalInvoicing = z
749+
.object({
750+
type: z.literal('external_invoicing').describe('Type of the app.'),
751+
name: z.string().describe('Name of the app.'),
752+
createBillingProfile: z.boolean().describe('Description of the app.'),
753+
})
754+
.describe('Base model for installing an app from the catalog.')
741755

742756
export const taxIdentificationCode = z
743757
.string()
@@ -2805,6 +2819,14 @@ export const appCapability = z
28052819
})
28062820
.describe('App capability describes a function that an App can perform.')
28072821

2822+
export const installAppRequest = z
2823+
.discriminatedUnion('type', [
2824+
installAppStripeWithApiKey,
2825+
installAppSandbox,
2826+
installAppExternalInvoicing,
2827+
])
2828+
.describe('Request to install an app from the catalog.')
2829+
28082830
export const partyTaxIdentity = z
28092831
.object({
28102832
code: taxIdentificationCode.optional(),
@@ -5037,6 +5059,13 @@ export const appPagePaginatedResponse = z
50375059
})
50385060
.describe('Page paginated response.')
50395061

5062+
export const billingInstallAppResponse = z
5063+
.object({
5064+
app: app,
5065+
defaultForCapabilityTypes: z.array(appCapabilityType),
5066+
})
5067+
.describe('Response of the app install.')
5068+
50405069
export const profileApps = z
50415070
.object({
50425071
tax: app,
@@ -6118,12 +6147,9 @@ export const getAppCatalogItemPathParams = z.object({
61186147

61196148
export const getAppCatalogItemResponse = appCatalogItem
61206149

6121-
export const getAppCatalogItemOauth2InstallUrlPathParams = z.object({
6122-
appType: appType,
6123-
})
6150+
export const installAppBody = installAppRequest
61246151

6125-
export const getAppCatalogItemOauth2InstallUrlResponse =
6126-
appOAuth2InstallResponse
6152+
export const installAppResponse = billingInstallAppResponse
61276153

61286154
export const listBillingProfilesQueryParams = z.object({
61296155
page: z
@@ -7273,16 +7299,30 @@ export const appStatusWire = z
72737299
.enum(['ready', 'unauthorized'])
72747300
.describe('Connection status of an installed app.')
72757301

7276-
export const appOAuth2InstallResponseWire = z
7302+
export const installAppStripeWithApiKeyWire = z
72777303
.strictObject({
7278-
url: z
7279-
.string()
7280-
.describe('The URL to start the OAuth2 authorization code grant flow.'),
7304+
type: z.literal('stripe').describe('Type of the app.'),
7305+
name: z.string().describe('Name of the app.'),
7306+
create_billing_profile: z.boolean().describe('Description of the app.'),
7307+
api_key: z.string().describe('API key for the app.'),
72817308
})
7309+
.describe('Model for installing an app from the catalog with an API key.')
72827310

7283-
.describe(
7284-
'Response from the billing app installation endpoint to initiate the OAuth2 authorization flow. This response contains the authorization URL where the user should be redirected to grant permissions to the application. The URL includes all necessary OAuth2 parameters such as client_id, redirect_uri, scope, and state.',
7285-
)
7311+
export const installAppSandboxWire = z
7312+
.strictObject({
7313+
type: z.literal('sandbox').describe('Type of the app.'),
7314+
name: z.string().describe('Name of the app.'),
7315+
create_billing_profile: z.boolean().describe('Description of the app.'),
7316+
})
7317+
.describe('Base model for installing an app from the catalog.')
7318+
7319+
export const installAppExternalInvoicingWire = z
7320+
.strictObject({
7321+
type: z.literal('external_invoicing').describe('Type of the app.'),
7322+
name: z.string().describe('Name of the app.'),
7323+
create_billing_profile: z.boolean().describe('Description of the app.'),
7324+
})
7325+
.describe('Base model for installing an app from the catalog.')
72867326

72877327
export const taxIdentificationCodeWire = z
72887328
.string()
@@ -9352,6 +9392,14 @@ export const appCapabilityWire = z
93529392
})
93539393
.describe('App capability describes a function that an App can perform.')
93549394

9395+
export const installAppRequestWire = z
9396+
.discriminatedUnion('type', [
9397+
installAppStripeWithApiKeyWire,
9398+
installAppSandboxWire,
9399+
installAppExternalInvoicingWire,
9400+
])
9401+
.describe('Request to install an app from the catalog.')
9402+
93559403
export const partyTaxIdentityWire = z
93569404
.strictObject({
93579405
code: taxIdentificationCodeWire.optional(),
@@ -11602,6 +11650,13 @@ export const appPagePaginatedResponseWire = z
1160211650
})
1160311651
.describe('Page paginated response.')
1160411652

11653+
export const billingInstallAppResponseWire = z
11654+
.strictObject({
11655+
app: appWire,
11656+
default_for_capability_types: z.array(appCapabilityTypeWire),
11657+
})
11658+
.describe('Response of the app install.')
11659+
1160511660
export const profileAppsWire = z
1160611661
.strictObject({
1160711662
tax: appWire,
@@ -12691,12 +12746,9 @@ export const getAppCatalogItemPathParamsWire = z.object({
1269112746

1269212747
export const getAppCatalogItemResponseWire = appCatalogItemWire
1269312748

12694-
export const getAppCatalogItemOauth2InstallUrlPathParamsWire = z.object({
12695-
appType: appTypeWire,
12696-
})
12749+
export const installAppBodyWire = installAppRequestWire
1269712750

12698-
export const getAppCatalogItemOauth2InstallUrlResponseWire =
12699-
appOAuth2InstallResponseWire
12751+
export const installAppResponseWire = billingInstallAppResponseWire
1270012752

1270112753
export const listBillingProfilesQueryParamsWire = z.object({
1270212754
page: z

api/spec/packages/aip-client-javascript/src/models/types.ts

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -199,17 +199,36 @@ export interface RateCardBooleanEntitlement {
199199
type: 'boolean'
200200
}
201201

202-
/**
203-
* Response from the billing app installation endpoint to initiate the OAuth2
204-
* authorization flow.
205-
*
206-
* This response contains the authorization URL where the user should be redirected
207-
* to grant permissions to the application. The URL includes all necessary OAuth2
208-
* parameters such as client_id, redirect_uri, scope, and state.
209-
*/
210-
export interface AppOAuth2InstallResponse {
211-
/** The URL to start the OAuth2 authorization code grant flow. */
212-
url: string
202+
/** Model for installing an app from the catalog with an API key. */
203+
export interface InstallAppStripeWithApiKey {
204+
/** Type of the app. */
205+
type: 'stripe'
206+
/** Name of the app. */
207+
name: string
208+
/** Description of the app. */
209+
createBillingProfile: boolean
210+
/** API key for the app. */
211+
apiKey: string
212+
}
213+
214+
/** Base model for installing an app from the catalog. */
215+
export interface InstallAppSandbox {
216+
/** Type of the app. */
217+
type: 'sandbox'
218+
/** Name of the app. */
219+
name: string
220+
/** Description of the app. */
221+
createBillingProfile: boolean
222+
}
223+
224+
/** Base model for installing an app from the catalog. */
225+
export interface InstallAppExternalInvoicing {
226+
/** Type of the app. */
227+
type: 'external_invoicing'
228+
/** Name of the app. */
229+
name: string
230+
/** Description of the app. */
231+
createBillingProfile: boolean
213232
}
214233

215234
/**
@@ -4453,6 +4472,18 @@ export interface AppPagePaginatedResponse {
44534472
meta: PaginatedMeta
44544473
}
44554474

4475+
/** Response of the app install. */
4476+
export interface BillingInstallAppResponse {
4477+
app: App
4478+
defaultForCapabilityTypes: (
4479+
| 'report_usage'
4480+
| 'report_events'
4481+
| 'calculate_tax'
4482+
| 'invoice_customers'
4483+
| 'collect_payments'
4484+
)[]
4485+
}
4486+
44564487
/** Applications used by a billing profile. */
44574488
export interface ProfileApps {
44584489
/** The tax app used for this workflow. */
@@ -5306,6 +5337,12 @@ export type DateTimeFieldFilter =
53065337
*/
53075338
export type SubscriptionEditTiming = 'immediate' | 'next_billing_cycle' | Date
53085339

5340+
/** Request to install an app from the catalog. */
5341+
export type InstallAppRequest =
5342+
| InstallAppStripeWithApiKey
5343+
| InstallAppSandbox
5344+
| InstallAppExternalInvoicing
5345+
53095346
/** Payment settings for a billing workflow. */
53105347
export type WorkflowPaymentSettings =
53115348
| WorkflowPaymentChargeAutomaticallySettings

0 commit comments

Comments
 (0)