Skip to content

Commit c8488ca

Browse files
authored
fix(api): update v3 subscription endpoints (#3703)
1 parent bf910c6 commit c8488ca

File tree

13 files changed

+531
-403
lines changed

13 files changed

+531
-403
lines changed

api/spec/lib/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { operationSummaryRule } from './rules/operation-summary.js'
66
import { operationIdKebabCaseRule } from './rules/operation-id.js'
77
import { noNullableRule } from './rules/no-nullable.js'
88
import { compositionOverInheritanceRule } from './rules/composition-over-inheritance.js'
9+
import { repeatedPrefixGroupingRule } from './rules/field-prefix.js'
910

1011
const packageName = '@openmeter/api-spec'
1112

@@ -19,6 +20,7 @@ const rules = [
1920
operationSummaryRule,
2021
operationIdKebabCaseRule,
2122
compositionOverInheritanceRule,
23+
repeatedPrefixGroupingRule,
2224
]
2325

2426
export const $linter = defineLinter({
@@ -43,6 +45,7 @@ export const $linter = defineLinter({
4345
[`${packageName}/${operationSummaryRule.name}`]: true,
4446
[`${packageName}/${operationIdKebabCaseRule.name}`]: true,
4547
[`${packageName}/${compositionOverInheritanceRule.name}`]: true,
48+
[`${packageName}/${repeatedPrefixGroupingRule.name}`]: true,
4649
},
4750
},
4851
},

api/spec/lib/rules/field-prefix.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { createRule, paramMessage } from '@typespec/compiler'
2+
3+
export const repeatedPrefixGroupingRule = createRule({
4+
name: 'repeated-prefix-grouping',
5+
severity: 'warning',
6+
description: 'Disallow repeated <prefix>_* field prefixes within a model.',
7+
messages: {
8+
default: paramMessage`Repeated "${'prefix'}_" field prefix detected (${`fields`}). Group them under a "${'prefix'}" object.`,
9+
},
10+
create(context) {
11+
return {
12+
model: (model) => {
13+
if (!model?.properties || model.properties.size === 0) {
14+
return
15+
}
16+
17+
const byPrefix = new Map()
18+
19+
for (const prop of model.properties.values()) {
20+
const name = prop?.name
21+
if (!name) {
22+
continue
23+
}
24+
25+
// "prefix" is everything before the first underscore.
26+
const underscoreIndex = name.indexOf('_')
27+
if (underscoreIndex <= 0) {
28+
continue
29+
}
30+
31+
const prefix = name.slice(0, underscoreIndex)
32+
if (!prefix) continue
33+
34+
const list = byPrefix.get(prefix) ?? []
35+
list.push(name)
36+
byPrefix.set(prefix, list)
37+
}
38+
39+
for (const [prefix, fields] of byPrefix.entries()) {
40+
if (fields.length <= 1) {
41+
continue
42+
}
43+
44+
context.reportDiagnostic({
45+
target: model,
46+
messageId: 'default',
47+
format: {
48+
prefix,
49+
fields: fields.sort().join(', '),
50+
},
51+
})
52+
}
53+
},
54+
}
55+
},
56+
})

api/spec/src/v3/entitlements/access.tsp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import "../../types.tsp";
21
import "./entitlements.tsp";
2+
import "../shared/index.tsp";
33

44
namespace Entitlements;
55

@@ -20,7 +20,7 @@ model EntitlementAccessResult {
2020
*/
2121
@example("available_models")
2222
@visibility(Lifecycle.Read)
23-
feature_key: ExternalKey;
23+
feature_key: Shared.ResourceKey;
2424

2525
/**
2626
* Whether the customer has access to the feature.

api/spec/src/v3/meters/meter.tsp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ model Meter {
4141
* If not specified, all historical events are included.
4242
*/
4343
@visibility(Lifecycle.Read, Lifecycle.Create)
44-
event_from?: Shared.DateTime;
44+
events_from?: Shared.DateTime;
4545

4646
/**
4747
* JSONPath expression to extract the value from the ingested event's data property.

api/spec/src/v3/subscriptions/operations.tsp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ interface SubscriptionsOperations {
121121
@post
122122
@operationId("cancel-subscription")
123123
@summary("Cancel subscription")
124-
@route("/cancel")
124+
@route("/{subscriptionId}/cancel")
125125
@extension(Shared.UnstableExtension, true)
126126
@extension(Shared.InternalExtension, true)
127127
cancel(@path subscriptionId: Shared.ULID, @body body: SubscriptionCancel):
@@ -136,7 +136,7 @@ interface SubscriptionsOperations {
136136
@post
137137
@operationId("unschedule-cancelation")
138138
@summary("Unschedule subscription cancelation")
139-
@route("/unschedule-cancelation")
139+
@route("/{subscriptionId}/unschedule-cancelation")
140140
@extension(Shared.UnstableExtension, true)
141141
@extension(Shared.InternalExtension, true)
142142
unscheduleCancelation(@path subscriptionId: Shared.ULID):
@@ -154,7 +154,7 @@ interface SubscriptionsOperations {
154154
@summary("Change subscription")
155155
@extension(Shared.UnstableExtension, true)
156156
@extension(Shared.InternalExtension, true)
157-
@route("/change")
157+
@route("/{subscriptionId}/change")
158158
change(
159159
@path subscriptionId: Shared.ULID,
160160

api/spec/src/v3/subscriptions/subscription.tsp

Lines changed: 55 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ enum SubscriptionEditTimingEnum {
3535
@friendlyName("BillingSubscriptionEditTiming")
3636
union SubscriptionEditTiming {
3737
Enum: SubscriptionEditTimingEnum,
38-
Custom: DateTime,
38+
Custom: Shared.DateTime,
3939
}
4040

4141
/**
@@ -49,54 +49,64 @@ model SubscriptionCreate {
4949
>>;
5050

5151
/**
52-
* The ID of the customer to create the subscription for.
53-
*
54-
* Either customer ID or customer key must be provided.
55-
* If both are provided, the ID will be used.
52+
* The customer to create the subscription for.
5653
*/
57-
@visibility(Lifecycle.Create)
58-
@summary("Customer ID")
59-
customer_id?: Shared.ULID;
60-
61-
/**
62-
* The key of the customer to create the subscription for.
63-
*
64-
* Either customer ID or customer key must be provided.
65-
* If both are provided, the ID will be used.
66-
*/
67-
@visibility(Lifecycle.Create)
68-
@summary("Customer Key")
69-
customer_key?: Shared.ExternalResourceKey;
70-
71-
/**
72-
* The plan ID of the subscription.
73-
* Set if subscription is created from a plan.
74-
*
75-
* ID or Key of the plan is required if creating a subscription from a plan.
76-
* If both are provided, the ID will be used.
77-
*/
78-
@visibility(Lifecycle.Create)
79-
@summary("Plan ID")
80-
plan_id?: Shared.ULID;
81-
82-
/**
83-
* The plan Key of the subscription, if any.
84-
* Set if subscription is created from a plan.
85-
*
86-
* ID or Key of the plan is required if creating a subscription from a plan.
87-
* If both are provided, the ID will be used.
88-
*/
89-
@visibility(Lifecycle.Create)
90-
@summary("Plan Key")
91-
plan_key?: Shared.ResourceKey;
54+
customer: {
55+
/**
56+
* The ID of the customer to create the subscription for.
57+
*
58+
* Either customer ID or customer key must be provided.
59+
* If both are provided, the ID will be used.
60+
*/
61+
@visibility(Lifecycle.Create)
62+
@summary("Customer ID")
63+
id?: Shared.ULID;
64+
65+
/**
66+
* The key of the customer to create the subscription for.
67+
*
68+
* Either customer ID or customer key must be provided.
69+
* If both are provided, the ID will be used.
70+
*/
71+
@visibility(Lifecycle.Create)
72+
@summary("Customer Key")
73+
key?: Shared.ExternalResourceKey;
74+
};
9275

9376
/**
94-
* The plan version of the subscription, if any.
95-
* If not provided, the latest version of the plan will be used.
77+
* The plan reference of the subscription.
9678
*/
97-
@visibility(Lifecycle.Create)
98-
@summary("Plan Version")
99-
plan_version?: integer;
79+
plan: {
80+
/**
81+
* The plan ID of the subscription.
82+
* Set if subscription is created from a plan.
83+
*
84+
* ID or Key of the plan is required if creating a subscription from a plan.
85+
* If both are provided, the ID will be used.
86+
*/
87+
@visibility(Lifecycle.Create)
88+
@summary("Plan ID")
89+
id?: Shared.ULID;
90+
91+
/**
92+
* The plan Key of the subscription, if any.
93+
* Set if subscription is created from a plan.
94+
*
95+
* ID or Key of the plan is required if creating a subscription from a plan.
96+
* If both are provided, the ID will be used.
97+
*/
98+
@visibility(Lifecycle.Create)
99+
@summary("Plan Key")
100+
key?: Shared.ResourceKey;
101+
102+
/**
103+
* The plan version of the subscription, if any.
104+
* If not provided, the latest version of the plan will be used.
105+
*/
106+
@visibility(Lifecycle.Create)
107+
@summary("Plan Version")
108+
version?: integer;
109+
};
100110

101111
/**
102112
* The billing anchor of the subscription.

0 commit comments

Comments
 (0)