@metronome/sdk 0.1.0-alpha.0

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.
Files changed (284) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/LICENSE +201 -0
  3. package/README.md +313 -0
  4. package/_shims/MultipartBody.d.ts +9 -0
  5. package/_shims/MultipartBody.d.ts.map +1 -0
  6. package/_shims/MultipartBody.js +16 -0
  7. package/_shims/MultipartBody.js.map +1 -0
  8. package/_shims/MultipartBody.mjs +12 -0
  9. package/_shims/MultipartBody.mjs.map +1 -0
  10. package/_shims/README.md +46 -0
  11. package/_shims/auto/runtime-bun.d.ts +5 -0
  12. package/_shims/auto/runtime-bun.d.ts.map +1 -0
  13. package/_shims/auto/runtime-bun.js +21 -0
  14. package/_shims/auto/runtime-bun.js.map +1 -0
  15. package/_shims/auto/runtime-bun.mjs +2 -0
  16. package/_shims/auto/runtime-bun.mjs.map +1 -0
  17. package/_shims/auto/runtime-node.d.ts +5 -0
  18. package/_shims/auto/runtime-node.d.ts.map +1 -0
  19. package/_shims/auto/runtime-node.js +21 -0
  20. package/_shims/auto/runtime-node.js.map +1 -0
  21. package/_shims/auto/runtime-node.mjs +2 -0
  22. package/_shims/auto/runtime-node.mjs.map +1 -0
  23. package/_shims/auto/runtime.d.ts +5 -0
  24. package/_shims/auto/runtime.d.ts.map +1 -0
  25. package/_shims/auto/runtime.js +21 -0
  26. package/_shims/auto/runtime.js.map +1 -0
  27. package/_shims/auto/runtime.mjs +2 -0
  28. package/_shims/auto/runtime.mjs.map +1 -0
  29. package/_shims/auto/types-node.d.ts +5 -0
  30. package/_shims/auto/types-node.d.ts.map +1 -0
  31. package/_shims/auto/types-node.js +21 -0
  32. package/_shims/auto/types-node.js.map +1 -0
  33. package/_shims/auto/types-node.mjs +2 -0
  34. package/_shims/auto/types-node.mjs.map +1 -0
  35. package/_shims/auto/types.d.ts +101 -0
  36. package/_shims/auto/types.js +3 -0
  37. package/_shims/auto/types.mjs +3 -0
  38. package/_shims/bun-runtime.d.ts +6 -0
  39. package/_shims/bun-runtime.d.ts.map +1 -0
  40. package/_shims/bun-runtime.js +14 -0
  41. package/_shims/bun-runtime.js.map +1 -0
  42. package/_shims/bun-runtime.mjs +10 -0
  43. package/_shims/bun-runtime.mjs.map +1 -0
  44. package/_shims/index.d.ts +81 -0
  45. package/_shims/index.js +13 -0
  46. package/_shims/index.mjs +7 -0
  47. package/_shims/manual-types.d.ts +12 -0
  48. package/_shims/manual-types.js +3 -0
  49. package/_shims/manual-types.mjs +3 -0
  50. package/_shims/node-runtime.d.ts +3 -0
  51. package/_shims/node-runtime.d.ts.map +1 -0
  52. package/_shims/node-runtime.js +90 -0
  53. package/_shims/node-runtime.js.map +1 -0
  54. package/_shims/node-runtime.mjs +56 -0
  55. package/_shims/node-runtime.mjs.map +1 -0
  56. package/_shims/node-types.d.ts +42 -0
  57. package/_shims/node-types.js +3 -0
  58. package/_shims/node-types.mjs +3 -0
  59. package/_shims/registry.d.ts +37 -0
  60. package/_shims/registry.d.ts.map +1 -0
  61. package/_shims/registry.js +41 -0
  62. package/_shims/registry.js.map +1 -0
  63. package/_shims/registry.mjs +37 -0
  64. package/_shims/registry.mjs.map +1 -0
  65. package/_shims/web-runtime.d.ts +5 -0
  66. package/_shims/web-runtime.d.ts.map +1 -0
  67. package/_shims/web-runtime.js +78 -0
  68. package/_shims/web-runtime.js.map +1 -0
  69. package/_shims/web-runtime.mjs +71 -0
  70. package/_shims/web-runtime.mjs.map +1 -0
  71. package/_shims/web-types.d.ts +83 -0
  72. package/_shims/web-types.js +3 -0
  73. package/_shims/web-types.mjs +3 -0
  74. package/core.d.ts +237 -0
  75. package/core.d.ts.map +1 -0
  76. package/core.js +868 -0
  77. package/core.js.map +1 -0
  78. package/core.mjs +837 -0
  79. package/core.mjs.map +1 -0
  80. package/error.d.ts +53 -0
  81. package/error.d.ts.map +1 -0
  82. package/error.js +143 -0
  83. package/error.js.map +1 -0
  84. package/error.mjs +127 -0
  85. package/error.mjs.map +1 -0
  86. package/index.d.mts +210 -0
  87. package/index.d.ts +210 -0
  88. package/index.d.ts.map +1 -0
  89. package/index.js +133 -0
  90. package/index.js.map +1 -0
  91. package/index.mjs +105 -0
  92. package/index.mjs.map +1 -0
  93. package/package.json +106 -0
  94. package/resource.d.ts +6 -0
  95. package/resource.d.ts.map +1 -0
  96. package/resource.js +11 -0
  97. package/resource.js.map +1 -0
  98. package/resource.mjs +7 -0
  99. package/resource.mjs.map +1 -0
  100. package/resources/alerts.d.ts +103 -0
  101. package/resources/alerts.d.ts.map +1 -0
  102. package/resources/alerts.js +23 -0
  103. package/resources/alerts.js.map +1 -0
  104. package/resources/alerts.mjs +19 -0
  105. package/resources/alerts.mjs.map +1 -0
  106. package/resources/audit-logs.d.ts +83 -0
  107. package/resources/audit-logs.d.ts.map +1 -0
  108. package/resources/audit-logs.js +18 -0
  109. package/resources/audit-logs.js.map +1 -0
  110. package/resources/audit-logs.mjs +14 -0
  111. package/resources/audit-logs.mjs.map +1 -0
  112. package/resources/billable-metrics.d.ts +236 -0
  113. package/resources/billable-metrics.d.ts.map +1 -0
  114. package/resources/billable-metrics.js +36 -0
  115. package/resources/billable-metrics.js.map +1 -0
  116. package/resources/billable-metrics.mjs +32 -0
  117. package/resources/billable-metrics.mjs.map +1 -0
  118. package/resources/credit-grants.d.ts +469 -0
  119. package/resources/credit-grants.d.ts.map +1 -0
  120. package/resources/credit-grants.js +50 -0
  121. package/resources/credit-grants.js.map +1 -0
  122. package/resources/credit-grants.mjs +46 -0
  123. package/resources/credit-grants.mjs.map +1 -0
  124. package/resources/custom-fields.d.ts +82 -0
  125. package/resources/custom-fields.d.ts.map +1 -0
  126. package/resources/custom-fields.js +66 -0
  127. package/resources/custom-fields.js.map +1 -0
  128. package/resources/custom-fields.mjs +62 -0
  129. package/resources/custom-fields.mjs.map +1 -0
  130. package/resources/customers/alerts.d.ts +146 -0
  131. package/resources/customers/alerts.d.ts.map +1 -0
  132. package/resources/customers/alerts.js +35 -0
  133. package/resources/customers/alerts.js.map +1 -0
  134. package/resources/customers/alerts.mjs +31 -0
  135. package/resources/customers/alerts.mjs.map +1 -0
  136. package/resources/customers/billing-config.d.ts +64 -0
  137. package/resources/customers/billing-config.d.ts.map +1 -0
  138. package/resources/customers/billing-config.js +37 -0
  139. package/resources/customers/billing-config.js.map +1 -0
  140. package/resources/customers/billing-config.mjs +33 -0
  141. package/resources/customers/billing-config.mjs.map +1 -0
  142. package/resources/customers/customers.d.ts +313 -0
  143. package/resources/customers/customers.d.ts.map +1 -0
  144. package/resources/customers/customers.js +116 -0
  145. package/resources/customers/customers.js.map +1 -0
  146. package/resources/customers/customers.mjs +89 -0
  147. package/resources/customers/customers.mjs.map +1 -0
  148. package/resources/customers/index.d.ts +6 -0
  149. package/resources/customers/index.d.ts.map +1 -0
  150. package/resources/customers/index.js +15 -0
  151. package/resources/customers/index.js.map +1 -0
  152. package/resources/customers/index.mjs +7 -0
  153. package/resources/customers/index.mjs.map +1 -0
  154. package/resources/customers/invoices.d.ts +331 -0
  155. package/resources/customers/invoices.d.ts.map +1 -0
  156. package/resources/customers/invoices.js +30 -0
  157. package/resources/customers/invoices.js.map +1 -0
  158. package/resources/customers/invoices.mjs +26 -0
  159. package/resources/customers/invoices.mjs.map +1 -0
  160. package/resources/customers/plans.d.ts +239 -0
  161. package/resources/customers/plans.d.ts.map +1 -0
  162. package/resources/customers/plans.js +41 -0
  163. package/resources/customers/plans.js.map +1 -0
  164. package/resources/customers/plans.mjs +37 -0
  165. package/resources/customers/plans.mjs.map +1 -0
  166. package/resources/dashboards.d.ts +61 -0
  167. package/resources/dashboards.d.ts.map +1 -0
  168. package/resources/dashboards.js +19 -0
  169. package/resources/dashboards.js.map +1 -0
  170. package/resources/dashboards.mjs +15 -0
  171. package/resources/dashboards.mjs.map +1 -0
  172. package/resources/index.d.ts +13 -0
  173. package/resources/index.d.ts.map +1 -0
  174. package/resources/index.js +42 -0
  175. package/resources/index.js.map +1 -0
  176. package/resources/index.mjs +14 -0
  177. package/resources/index.mjs.map +1 -0
  178. package/resources/plans.d.ts +217 -0
  179. package/resources/plans.d.ts.map +1 -0
  180. package/resources/plans.js +36 -0
  181. package/resources/plans.js.map +1 -0
  182. package/resources/plans.mjs +32 -0
  183. package/resources/plans.mjs.map +1 -0
  184. package/resources/services.d.ts +26 -0
  185. package/resources/services.d.ts.map +1 -0
  186. package/resources/services.js +20 -0
  187. package/resources/services.js.map +1 -0
  188. package/resources/services.mjs +16 -0
  189. package/resources/services.mjs.map +1 -0
  190. package/resources/shared.d.ts +540 -0
  191. package/resources/shared.d.ts.map +1 -0
  192. package/resources/shared.js +4 -0
  193. package/resources/shared.js.map +1 -0
  194. package/resources/shared.mjs +3 -0
  195. package/resources/shared.mjs.map +1 -0
  196. package/resources/usage.d.ts +182 -0
  197. package/resources/usage.d.ts.map +1 -0
  198. package/resources/usage.js +41 -0
  199. package/resources/usage.js.map +1 -0
  200. package/resources/usage.mjs +37 -0
  201. package/resources/usage.mjs.map +1 -0
  202. package/resources/webhooks.d.ts +22 -0
  203. package/resources/webhooks.d.ts.map +1 -0
  204. package/resources/webhooks.js +91 -0
  205. package/resources/webhooks.js.map +1 -0
  206. package/resources/webhooks.mjs +87 -0
  207. package/resources/webhooks.mjs.map +1 -0
  208. package/shims/node.d.ts +29 -0
  209. package/shims/node.d.ts.map +1 -0
  210. package/shims/node.js +31 -0
  211. package/shims/node.js.map +1 -0
  212. package/shims/node.mjs +5 -0
  213. package/shims/node.mjs.map +1 -0
  214. package/shims/web.d.ts +26 -0
  215. package/shims/web.d.ts.map +1 -0
  216. package/shims/web.js +31 -0
  217. package/shims/web.js.map +1 -0
  218. package/shims/web.mjs +5 -0
  219. package/shims/web.mjs.map +1 -0
  220. package/src/_shims/MultipartBody.ts +9 -0
  221. package/src/_shims/README.md +46 -0
  222. package/src/_shims/auto/runtime-bun.ts +4 -0
  223. package/src/_shims/auto/runtime-node.ts +4 -0
  224. package/src/_shims/auto/runtime.ts +4 -0
  225. package/src/_shims/auto/types-node.ts +4 -0
  226. package/src/_shims/auto/types.d.ts +101 -0
  227. package/src/_shims/auto/types.js +3 -0
  228. package/src/_shims/auto/types.mjs +3 -0
  229. package/src/_shims/bun-runtime.ts +14 -0
  230. package/src/_shims/index.d.ts +81 -0
  231. package/src/_shims/index.js +13 -0
  232. package/src/_shims/index.mjs +7 -0
  233. package/src/_shims/manual-types.d.ts +12 -0
  234. package/src/_shims/manual-types.js +3 -0
  235. package/src/_shims/manual-types.mjs +3 -0
  236. package/src/_shims/node-runtime.ts +83 -0
  237. package/src/_shims/node-types.d.ts +42 -0
  238. package/src/_shims/node-types.js +3 -0
  239. package/src/_shims/node-types.mjs +3 -0
  240. package/src/_shims/registry.ts +67 -0
  241. package/src/_shims/web-runtime.ts +103 -0
  242. package/src/_shims/web-types.d.ts +83 -0
  243. package/src/_shims/web-types.js +3 -0
  244. package/src/_shims/web-types.mjs +3 -0
  245. package/src/core.ts +1146 -0
  246. package/src/error.ts +146 -0
  247. package/src/index.ts +303 -0
  248. package/src/lib/.keep +4 -0
  249. package/src/resource.ts +11 -0
  250. package/src/resources/alerts.ts +144 -0
  251. package/src/resources/audit-logs.ts +116 -0
  252. package/src/resources/billable-metrics.ts +341 -0
  253. package/src/resources/credit-grants.ts +627 -0
  254. package/src/resources/custom-fields.ts +242 -0
  255. package/src/resources/customers/alerts.ts +214 -0
  256. package/src/resources/customers/billing-config.ts +183 -0
  257. package/src/resources/customers/customers.ts +500 -0
  258. package/src/resources/customers/index.ts +53 -0
  259. package/src/resources/customers/invoices.ts +533 -0
  260. package/src/resources/customers/plans.ts +363 -0
  261. package/src/resources/dashboards.ts +98 -0
  262. package/src/resources/index.ts +90 -0
  263. package/src/resources/plans.ts +333 -0
  264. package/src/resources/services.ts +35 -0
  265. package/src/resources/shared.ts +849 -0
  266. package/src/resources/usage.ts +245 -0
  267. package/src/resources/webhooks.ts +120 -0
  268. package/src/shims/node.ts +50 -0
  269. package/src/shims/web.ts +50 -0
  270. package/src/tsconfig.json +11 -0
  271. package/src/uploads.ts +248 -0
  272. package/src/version.ts +1 -0
  273. package/uploads.d.ts +75 -0
  274. package/uploads.d.ts.map +1 -0
  275. package/uploads.js +165 -0
  276. package/uploads.js.map +1 -0
  277. package/uploads.mjs +152 -0
  278. package/uploads.mjs.map +1 -0
  279. package/version.d.ts +2 -0
  280. package/version.d.ts.map +1 -0
  281. package/version.js +5 -0
  282. package/version.js.map +1 -0
  283. package/version.mjs +2 -0
  284. package/version.mjs.map +1 -0
@@ -0,0 +1,245 @@
1
+ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ import * as Core from "../core";
4
+ import { APIResource } from "../resource";
5
+ import * as UsageAPI from "./usage";
6
+
7
+ export class Usage extends APIResource {
8
+ /**
9
+ * Fetch aggregated usage data for multiple customers and billable-metrics, broken
10
+ * into intervals of the specified length.
11
+ */
12
+ list(params: UsageListParams, options?: Core.RequestOptions): Core.APIPromise<UsageListResponse> {
13
+ const { next_page, ...body } = params;
14
+ return this._client.post('/usage', { query: { next_page }, body, ...options });
15
+ }
16
+
17
+ /**
18
+ * Send usage events to Metronome. The body of this request is expected to be a
19
+ * JSON array of between 1 and 100 usage events. Compressed request bodies are
20
+ * supported with a `Content-Encoding: gzip` header. See
21
+ * [Getting usage into Metronome](https://docs.metronome.com/getting-usage-data-into-metronome/overview)
22
+ * to learn more about usage events.
23
+ */
24
+ ingest(body: UsageIngestParams, options?: Core.RequestOptions): Core.APIPromise<void> {
25
+ return this._client.post('/ingest', {
26
+ body,
27
+ ...options,
28
+ headers: { Accept: '*/*', ...options?.headers },
29
+ });
30
+ }
31
+
32
+ /**
33
+ * Fetch aggregated usage data for the specified customer, billable-metric, and
34
+ * optional group, broken into intervals of the specified length.
35
+ */
36
+ listWithGroups(
37
+ params: UsageListWithGroupsParams,
38
+ options?: Core.RequestOptions,
39
+ ): Core.APIPromise<UsageListWithGroupsResponse> {
40
+ const { limit, next_page, ...body } = params;
41
+ return this._client.post('/usage/groups', { query: { limit, next_page }, body, ...options });
42
+ }
43
+ }
44
+
45
+ export interface UsageListResponse {
46
+ data: Array<UsageListResponse.Data>;
47
+
48
+ next_page: string | null;
49
+ }
50
+
51
+ export namespace UsageListResponse {
52
+ export interface Data {
53
+ billable_metric_id: string;
54
+
55
+ billable_metric_name: string;
56
+
57
+ customer_id: string;
58
+
59
+ end_timestamp: string;
60
+
61
+ start_timestamp: string;
62
+
63
+ value: number | null;
64
+
65
+ /**
66
+ * Values will be either a number or null. Null indicates that there were no
67
+ * matches for the group_by value.
68
+ */
69
+ groups?: Record<string, number | null>;
70
+ }
71
+ }
72
+
73
+ export interface UsageListWithGroupsResponse {
74
+ data: Array<UsageListWithGroupsResponse.Data>;
75
+
76
+ next_page: string | null;
77
+ }
78
+
79
+ export namespace UsageListWithGroupsResponse {
80
+ export interface Data {
81
+ ending_before: string;
82
+
83
+ group_key: string | null;
84
+
85
+ group_value: string | null;
86
+
87
+ starting_on: string;
88
+
89
+ value: number | null;
90
+ }
91
+ }
92
+
93
+ export interface UsageListParams {
94
+ /**
95
+ * Body param:
96
+ */
97
+ ending_before: string;
98
+
99
+ /**
100
+ * Body param:
101
+ */
102
+ starting_on: string;
103
+
104
+ /**
105
+ * Body param: A window_size of "day" or "hour" will return the usage for the
106
+ * specified period segmented into daily or hourly aggregates. A window_size of
107
+ * "none" will return a single usage aggregate for the entirety of the specified
108
+ * period.
109
+ */
110
+ window_size: 'hour' | 'day' | 'none' | 'HOUR' | 'DAY' | 'NONE' | 'Hour' | 'Day' | 'None';
111
+
112
+ /**
113
+ * Query param: Cursor that indicates where the next page of results should start.
114
+ */
115
+ next_page?: string;
116
+
117
+ /**
118
+ * Body param: A list of billable metrics to fetch usage for. If absent, all
119
+ * billable metrics will be returned.
120
+ */
121
+ billable_metrics?: Array<UsageListParams.BillableMetric>;
122
+
123
+ /**
124
+ * Body param: A list of Metronome customer IDs to fetch usage for. If absent,
125
+ * usage for all customers will be returned.
126
+ */
127
+ customer_ids?: Array<string>;
128
+ }
129
+
130
+ export namespace UsageListParams {
131
+ export interface BillableMetric {
132
+ id: string;
133
+
134
+ group_by?: BillableMetric.GroupBy;
135
+ }
136
+
137
+ export namespace BillableMetric {
138
+ export interface GroupBy {
139
+ /**
140
+ * The name of the group_by key to use
141
+ */
142
+ key: string;
143
+
144
+ /**
145
+ * Values of the group_by key to return in the query. If this field is omitted, all
146
+ * available values will be returned, up to a maximum of 200.
147
+ */
148
+ values?: Array<string>;
149
+ }
150
+ }
151
+ }
152
+
153
+ export type UsageIngestParams = Array<UsageIngestParams.Usage>;
154
+
155
+ export namespace UsageIngestParams {
156
+ export interface Usage {
157
+ customer_id: string;
158
+
159
+ event_type: string;
160
+
161
+ /**
162
+ * RFC 3339 formatted
163
+ */
164
+ timestamp: string;
165
+
166
+ transaction_id: string;
167
+
168
+ properties?: Record<string, unknown>;
169
+ }
170
+ }
171
+
172
+ export interface UsageListWithGroupsParams {
173
+ /**
174
+ * Body param:
175
+ */
176
+ billable_metric_id: string;
177
+
178
+ /**
179
+ * Body param:
180
+ */
181
+ customer_id: string;
182
+
183
+ /**
184
+ * Body param: A window_size of "day" or "hour" will return the usage for the
185
+ * specified period segmented into daily or hourly aggregates. A window_size of
186
+ * "none" will return a single usage aggregate for the entirety of the specified
187
+ * period.
188
+ */
189
+ window_size: 'hour' | 'day' | 'none' | 'HOUR' | 'DAY' | 'NONE' | 'Hour' | 'Day' | 'None';
190
+
191
+ /**
192
+ * Query param: Max number of results that should be returned
193
+ */
194
+ limit?: number;
195
+
196
+ /**
197
+ * Query param: Cursor that indicates where the next page of results should start.
198
+ */
199
+ next_page?: string;
200
+
201
+ /**
202
+ * Body param: If true, will return the usage for the current billing period. Will
203
+ * return an error if the customer is currently uncontracted or starting_on and
204
+ * ending_before are specified when this is true.
205
+ */
206
+ current_period?: boolean;
207
+
208
+ /**
209
+ * Body param:
210
+ */
211
+ ending_before?: string;
212
+
213
+ /**
214
+ * Body param:
215
+ */
216
+ group_by?: UsageListWithGroupsParams.GroupBy;
217
+
218
+ /**
219
+ * Body param:
220
+ */
221
+ starting_on?: string;
222
+ }
223
+
224
+ export namespace UsageListWithGroupsParams {
225
+ export interface GroupBy {
226
+ /**
227
+ * The name of the group_by key to use
228
+ */
229
+ key: string;
230
+
231
+ /**
232
+ * Values of the group_by key to return in the query. Omit this if you'd like all
233
+ * values for the key returned.
234
+ */
235
+ values?: Array<string>;
236
+ }
237
+ }
238
+
239
+ export namespace Usage {
240
+ export import UsageListResponse = UsageAPI.UsageListResponse;
241
+ export import UsageListWithGroupsResponse = UsageAPI.UsageListWithGroupsResponse;
242
+ export import UsageListParams = UsageAPI.UsageListParams;
243
+ export import UsageIngestParams = UsageAPI.UsageIngestParams;
244
+ export import UsageListWithGroupsParams = UsageAPI.UsageListWithGroupsParams;
245
+ }
@@ -0,0 +1,120 @@
1
+ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
+
3
+ import { APIResource } from '../resource';
4
+ import { createHmac } from 'crypto';
5
+ import { getRequiredHeader, HeadersLike } from '../core';
6
+
7
+ export class Webhooks extends APIResource {
8
+ /**
9
+ * Validates that the given payload was sent by Metronome and parses the payload.
10
+ */
11
+ unwrap(
12
+ payload: string,
13
+ headers: HeadersLike,
14
+ secret: string | undefined | null = this._client.webhookSecret,
15
+ ): Object {
16
+ this.verifySignature(payload, headers, secret);
17
+ return JSON.parse(payload);
18
+ }
19
+
20
+ private validateSecret(secret: string | null | undefined): asserts secret is string {
21
+ if (typeof secret !== 'string') {
22
+ throw new Error(
23
+ "The webhook secret must either be set using the env var, METRONOME_WEBHOOK_SECRET, on the client class, Metronome({ webhook_secret: '123' }), or passed to this function",
24
+ );
25
+ }
26
+
27
+ return;
28
+ }
29
+
30
+ private signPayload(payload: string, { date, secret }: { date: string; secret: string }) {
31
+ const encoder = new TextEncoder();
32
+ const toSign = encoder.encode(`${date}\n${payload}`);
33
+
34
+ const hmac = createHmac('sha256', secret);
35
+ hmac.update(toSign);
36
+
37
+ return hmac.digest('hex');
38
+ }
39
+
40
+ /** Make an assertion, if not `true`, then throw. */
41
+ private assert(expr: unknown, msg = ''): asserts expr {
42
+ if (!expr) {
43
+ throw new Error(msg);
44
+ }
45
+ }
46
+
47
+ /** Compare to array buffers or data views in a way that timing based attacks
48
+ * cannot gain information about the platform. */
49
+ private timingSafeEqual(
50
+ a: ArrayBufferView | ArrayBufferLike | DataView,
51
+ b: ArrayBufferView | ArrayBufferLike | DataView,
52
+ ): boolean {
53
+ if (a.byteLength !== b.byteLength) {
54
+ return false;
55
+ }
56
+ if (!(a instanceof DataView)) {
57
+ a = new DataView(ArrayBuffer.isView(a) ? a.buffer : a);
58
+ }
59
+ if (!(b instanceof DataView)) {
60
+ b = new DataView(ArrayBuffer.isView(b) ? b.buffer : b);
61
+ }
62
+ this.assert(a instanceof DataView);
63
+ this.assert(b instanceof DataView);
64
+ const length = a.byteLength;
65
+ let out = 0;
66
+ let i = -1;
67
+ while (++i < length) {
68
+ out |= a.getUint8(i) ^ b.getUint8(i);
69
+ }
70
+ return out === 0;
71
+ }
72
+
73
+ /**
74
+ * Validates whether or not the webhook payload was sent by Metronome.
75
+ *
76
+ * An error will be raised if the webhook payload was not sent by Metronome.
77
+ */
78
+ verifySignature(
79
+ body: string,
80
+ headers: HeadersLike,
81
+ secret: string | undefined | null = this._client.webhookSecret,
82
+ ): void {
83
+ this.validateSecret(secret);
84
+
85
+ const msgDate = getRequiredHeader(headers, 'Date');
86
+ const msgSignature = getRequiredHeader(headers, 'Metronome-Webhook-Signature');
87
+
88
+ const now = Date.now();
89
+ const timestampSeconds = Math.floor(new Date(msgDate).valueOf());
90
+
91
+ if (isNaN(timestampSeconds)) {
92
+ throw new Error(`Invalid timestamp header: ${msgDate}`);
93
+ }
94
+
95
+ if (typeof body !== 'string') {
96
+ throw new Error(
97
+ 'Webhook body must be passed as the raw JSON string sent from the server (do not parse it first).',
98
+ );
99
+ }
100
+
101
+ const webhook_tolerance_in_seconds = 5 * 60; // 5 minutes
102
+ if (now - timestampSeconds > webhook_tolerance_in_seconds) {
103
+ throw new Error('Webhook timestamp is too old');
104
+ }
105
+
106
+ if (timestampSeconds > now + webhook_tolerance_in_seconds) {
107
+ throw new Error('Webhook timestamp is too new');
108
+ }
109
+
110
+ const expectedSignature = this.signPayload(body, { date: msgDate, secret });
111
+ const encoder = new globalThis.TextEncoder();
112
+
113
+ if (this.timingSafeEqual(encoder.encode(msgSignature), encoder.encode(expectedSignature))) {
114
+ // valid!
115
+ return;
116
+ }
117
+
118
+ throw new Error('The given webhook signature does not match the expected signature');
119
+ }
120
+ }
@@ -0,0 +1,50 @@
1
+ // @ts-ignore
2
+ import * as types from '../_shims/node-types';
3
+ import { setShims } from '../_shims/registry';
4
+ import { getRuntime } from '../_shims/node-runtime';
5
+ setShims(getRuntime());
6
+
7
+ declare module '../_shims/manual-types' {
8
+ export namespace manual {
9
+ // @ts-ignore
10
+ export type Agent = types.Agent;
11
+ // @ts-ignore
12
+ export import fetch = types.fetch;
13
+ // @ts-ignore
14
+ export type Request = types.Request;
15
+ // @ts-ignore
16
+ export type RequestInfo = types.RequestInfo;
17
+ // @ts-ignore
18
+ export type RequestInit = types.RequestInit;
19
+ // @ts-ignore
20
+ export type Response = types.Response;
21
+ // @ts-ignore
22
+ export type ResponseInit = types.ResponseInit;
23
+ // @ts-ignore
24
+ export type ResponseType = types.ResponseType;
25
+ // @ts-ignore
26
+ export type BodyInit = types.BodyInit;
27
+ // @ts-ignore
28
+ export type Headers = types.Headers;
29
+ // @ts-ignore
30
+ export type HeadersInit = types.HeadersInit;
31
+ // @ts-ignore
32
+ export type BlobPropertyBag = types.BlobPropertyBag;
33
+ // @ts-ignore
34
+ export type FilePropertyBag = types.FilePropertyBag;
35
+ // @ts-ignore
36
+ export type FileFromPathOptions = types.FileFromPathOptions;
37
+ // @ts-ignore
38
+ export import FormData = types.FormData;
39
+ // @ts-ignore
40
+ export import File = types.File;
41
+ // @ts-ignore
42
+ export import Blob = types.Blob;
43
+ // @ts-ignore
44
+ export type Readable = types.Readable;
45
+ // @ts-ignore
46
+ export type FsReadStream = types.FsReadStream;
47
+ // @ts-ignore
48
+ export import ReadableStream = types.ReadableStream;
49
+ }
50
+ }
@@ -0,0 +1,50 @@
1
+ // @ts-ignore
2
+ import * as types from '../_shims/web-types';
3
+ import { setShims } from '../_shims/registry';
4
+ import { getRuntime } from '../_shims/web-runtime';
5
+ setShims(getRuntime({ manuallyImported: true }));
6
+
7
+ declare module '../_shims/manual-types' {
8
+ export namespace manual {
9
+ // @ts-ignore
10
+ export type Agent = types.Agent;
11
+ // @ts-ignore
12
+ export import fetch = types.fetch;
13
+ // @ts-ignore
14
+ export type Request = types.Request;
15
+ // @ts-ignore
16
+ export type RequestInfo = types.RequestInfo;
17
+ // @ts-ignore
18
+ export type RequestInit = types.RequestInit;
19
+ // @ts-ignore
20
+ export type Response = types.Response;
21
+ // @ts-ignore
22
+ export type ResponseInit = types.ResponseInit;
23
+ // @ts-ignore
24
+ export type ResponseType = types.ResponseType;
25
+ // @ts-ignore
26
+ export type BodyInit = types.BodyInit;
27
+ // @ts-ignore
28
+ export type Headers = types.Headers;
29
+ // @ts-ignore
30
+ export type HeadersInit = types.HeadersInit;
31
+ // @ts-ignore
32
+ export type BlobPropertyBag = types.BlobPropertyBag;
33
+ // @ts-ignore
34
+ export type FilePropertyBag = types.FilePropertyBag;
35
+ // @ts-ignore
36
+ export type FileFromPathOptions = types.FileFromPathOptions;
37
+ // @ts-ignore
38
+ export import FormData = types.FormData;
39
+ // @ts-ignore
40
+ export import File = types.File;
41
+ // @ts-ignore
42
+ export import Blob = types.Blob;
43
+ // @ts-ignore
44
+ export type Readable = types.Readable;
45
+ // @ts-ignore
46
+ export type FsReadStream = types.FsReadStream;
47
+ // @ts-ignore
48
+ export import ReadableStream = types.ReadableStream;
49
+ }
50
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ // this config is included in the published src directory to prevent TS errors
3
+ // from appearing when users go to source, and VSCode opens the source .ts file
4
+ // via declaration maps
5
+ "include": ["index.ts"],
6
+ "compilerOptions": {
7
+ "target": "es2015",
8
+ "lib": ["DOM"],
9
+ "moduleResolution": "node"
10
+ }
11
+ }