@openmeter/sdk 1.0.0-beta.1 → 1.0.0-beta.13

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.
@@ -3,29 +3,31 @@
3
3
  * Do not make direct changes to the file.
4
4
  */
5
5
  export interface paths {
6
- "/api/v1/events": {
6
+ '/api/v1/events': {
7
+ /** @description Retrieve latest raw events. */
8
+ get: operations['listEvents'];
7
9
  /** @description Ingest events */
8
- post: operations["ingestEvents"];
10
+ post: operations['ingestEvents'];
9
11
  };
10
- "/api/v1/meters": {
12
+ '/api/v1/meters': {
11
13
  /** @description List meters */
12
- get: operations["listMeters"];
14
+ get: operations['listMeters'];
13
15
  /** @description Create meter */
14
- post: operations["createMeter"];
16
+ post: operations['createMeter'];
15
17
  };
16
- "/api/v1/meters/{meterIdOrSlug}": {
18
+ '/api/v1/meters/{meterIdOrSlug}': {
17
19
  /** @description Get meter by slugs */
18
- get: operations["getMeter"];
20
+ get: operations['getMeter'];
19
21
  /** @description Delete meter by slug */
20
- delete: operations["deleteMeter"];
22
+ delete: operations['deleteMeter'];
21
23
  };
22
- "/api/v1/meters/{meterIdOrSlug}/values": {
23
- /** @description Get meter values */
24
- get: operations["getMeterValues"];
24
+ '/api/v1/meters/{meterIdOrSlug}/query': {
25
+ /** @description Query meter */
26
+ get: operations['queryMeter'];
25
27
  };
26
- "/api/v1/namespaces": {
27
- /** @description Create namespace */
28
- post: operations["createNamespace"];
28
+ '/api/v1/meters/{meterIdOrSlug}/subjects': {
29
+ /** @description List meter subjects */
30
+ get: operations['listMeterSubjects'];
29
31
  };
30
32
  }
31
33
  export type webhooks = Record<string, never>;
@@ -100,7 +102,7 @@ export interface components {
100
102
  * @example application/json
101
103
  * @enum {string|null}
102
104
  */
103
- datacontenttype?: "application/json" | null;
105
+ datacontenttype?: 'application/json' | null;
104
106
  /**
105
107
  * Format: uri
106
108
  * @description Identifies the schema that data adheres to.
@@ -136,7 +138,7 @@ export interface components {
136
138
  id?: string;
137
139
  /**
138
140
  * @description A unique identifier for the meter.
139
- * @example my-meter
141
+ * @example my_meter
140
142
  */
141
143
  slug: string;
142
144
  /**
@@ -144,7 +146,7 @@ export interface components {
144
146
  * @example My Meter Description
145
147
  */
146
148
  description?: string | null;
147
- aggregation: components["schemas"]["MeterAggregation"];
149
+ aggregation: components['schemas']['MeterAggregation'];
148
150
  /**
149
151
  * @description The event type to aggregate.
150
152
  * @example api_request
@@ -154,185 +156,190 @@ export interface components {
154
156
  * @description JSONPath expression to extract the value from the event data.
155
157
  * @example $.duration_ms
156
158
  */
157
- valueProperty: string;
159
+ valueProperty?: string;
158
160
  /**
159
161
  * @description Named JSONPath expressions to extract the group by values from the event data.
160
162
  * @example {
161
- * "duration_ms": "$.duration_ms",
163
+ * "method": "$.method",
162
164
  * "path": "$.path"
163
165
  * }
164
166
  */
165
167
  groupBy?: {
166
168
  [key: string]: string;
167
169
  };
168
- windowSize: components["schemas"]["WindowSize"];
170
+ windowSize: components['schemas']['WindowSize'];
169
171
  };
170
172
  /**
171
173
  * @description The aggregation type to use for the meter.
172
174
  * @enum {string}
173
175
  */
174
- MeterAggregation: "SUM" | "COUNT" | "AVG" | "MIN" | "MAX";
176
+ MeterAggregation: 'SUM' | 'COUNT' | 'AVG' | 'MIN' | 'MAX';
175
177
  /** @enum {string} */
176
- WindowSize: "MINUTE" | "HOUR" | "DAY";
177
- MeterValue: {
178
- /** @description The subject of the meter value. */
179
- subject?: string;
178
+ WindowSize: 'MINUTE' | 'HOUR' | 'DAY';
179
+ MeterQueryRow: {
180
+ value: number;
180
181
  /** Format: date-time */
181
182
  windowStart: string;
182
183
  /** Format: date-time */
183
184
  windowEnd: string;
184
- value: number;
185
+ /** @description The subject of the meter value. */
186
+ subject?: string | null;
185
187
  groupBy?: {
186
188
  [key: string]: string;
187
189
  } | null;
188
190
  };
189
191
  IdOrSlug: string;
190
- Namespace: {
191
- /**
192
- * @description A namespace
193
- * @example my-namesapce
194
- */
195
- namespace: string;
196
- };
197
192
  };
198
193
  responses: {
199
194
  /** @description Bad Request */
200
195
  BadRequestProblemResponse: {
201
196
  content: {
202
- "application/problem+json": components["schemas"]["Problem"];
197
+ 'application/problem+json': components['schemas']['Problem'];
203
198
  };
204
199
  };
205
200
  /** @description Method not allowed, feature not supported */
206
201
  MethodNotAllowedProblemResponse: {
207
202
  content: {
208
- "application/problem+json": components["schemas"]["Problem"];
203
+ 'application/problem+json': components['schemas']['Problem'];
209
204
  };
210
205
  };
211
206
  /** @description Not Found */
212
207
  NotFoundProblemResponse: {
213
208
  content: {
214
- "application/problem+json": components["schemas"]["Problem"];
209
+ 'application/problem+json': components['schemas']['Problem'];
215
210
  };
216
211
  };
217
212
  /** @description Not Implemented */
218
213
  NotImplementedProblemResponse: {
219
214
  content: {
220
- "application/problem+json": components["schemas"]["Problem"];
215
+ 'application/problem+json': components['schemas']['Problem'];
221
216
  };
222
217
  };
223
218
  /** @description Unexpected error */
224
219
  UnexpectedProblemResponse: {
225
220
  content: {
226
- "application/problem+json": components["schemas"]["Problem"];
221
+ 'application/problem+json': components['schemas']['Problem'];
227
222
  };
228
223
  };
229
224
  };
230
225
  parameters: {
231
226
  /** @description A unique identifier for the meter. */
232
- meterIdOrSlug: components["schemas"]["IdOrSlug"];
227
+ meterIdOrSlug: components['schemas']['IdOrSlug'];
233
228
  /**
234
- * @description Optional namespace
235
- * @default default
229
+ * @description Start date-time in RFC 3339 format in UTC timezone.
230
+ * Must be aligned with the window size.
231
+ * Inclusive.
236
232
  */
237
- namespaceParam?: string;
233
+ queryFrom?: string;
234
+ /**
235
+ * @description End date-time in RFC 3339 format in UTC timezone.
236
+ * Must be aligned with the window size.
237
+ * Inclusive.
238
+ */
239
+ queryTo?: string;
240
+ /** @description If not specified, a single usage aggregate will be returned for the entirety of the specified period for each subject and group. */
241
+ queryWindowSize?: components['schemas']['WindowSize'];
242
+ querySubject?: string[];
243
+ /** @description If not specified a single aggregate will be returned for each subject and time window. */
244
+ queryGroupBy?: string[];
238
245
  };
239
246
  requestBodies: never;
240
247
  headers: never;
241
248
  pathItems: never;
242
249
  }
250
+ export type $defs = Record<string, never>;
243
251
  export type external = Record<string, never>;
244
252
  export interface operations {
245
- /** @description Ingest events */
246
- ingestEvents: {
253
+ /** @description Retrieve latest raw events. */
254
+ listEvents: {
247
255
  parameters: {
248
- header?: {
249
- "OM-Namespace"?: components["parameters"]["namespaceParam"];
256
+ query?: {
257
+ /** @description Number of events to return. */
258
+ limit?: number;
259
+ };
260
+ };
261
+ responses: {
262
+ /** @description Events response */
263
+ 200: {
264
+ content: {
265
+ 'application/json': components['schemas']['Event'][];
266
+ };
250
267
  };
268
+ 400: components['responses']['BadRequestProblemResponse'];
269
+ default: components['responses']['UnexpectedProblemResponse'];
251
270
  };
271
+ };
272
+ /** @description Ingest events */
273
+ ingestEvents: {
252
274
  requestBody: {
253
275
  content: {
254
- "application/cloudevents+json": components["schemas"]["Event"];
276
+ 'application/cloudevents+json': components['schemas']['Event'];
277
+ 'application/cloudevents-batch+json': components['schemas']['Event'][];
255
278
  };
256
279
  };
257
280
  responses: {
258
281
  /** @description OK */
259
- 200: {
282
+ 204: {
260
283
  content: never;
261
284
  };
262
- 400: components["responses"]["BadRequestProblemResponse"];
263
- default: components["responses"]["UnexpectedProblemResponse"];
285
+ 400: components['responses']['BadRequestProblemResponse'];
286
+ default: components['responses']['UnexpectedProblemResponse'];
264
287
  };
265
288
  };
266
289
  /** @description List meters */
267
290
  listMeters: {
268
- parameters: {
269
- header?: {
270
- "OM-Namespace"?: components["parameters"]["namespaceParam"];
271
- };
272
- };
273
291
  responses: {
274
292
  /** @description Meters response */
275
293
  200: {
276
294
  content: {
277
- "application/json": components["schemas"]["Meter"][];
295
+ 'application/json': components['schemas']['Meter'][];
278
296
  };
279
297
  };
280
- default: components["responses"]["UnexpectedProblemResponse"];
298
+ default: components['responses']['UnexpectedProblemResponse'];
281
299
  };
282
300
  };
283
301
  /** @description Create meter */
284
302
  createMeter: {
285
- parameters: {
286
- header?: {
287
- "OM-Namespace"?: components["parameters"]["namespaceParam"];
288
- };
289
- };
290
303
  requestBody: {
291
304
  content: {
292
- "application/json": components["schemas"]["Meter"];
305
+ 'application/json': components['schemas']['Meter'];
293
306
  };
294
307
  };
295
308
  responses: {
296
309
  /** @description Created */
297
310
  201: {
298
311
  content: {
299
- "application/json": components["schemas"]["Meter"];
312
+ 'application/json': components['schemas']['Meter'];
300
313
  };
301
314
  };
302
- 400: components["responses"]["BadRequestProblemResponse"];
303
- 501: components["responses"]["NotImplementedProblemResponse"];
304
- default: components["responses"]["UnexpectedProblemResponse"];
315
+ 400: components['responses']['BadRequestProblemResponse'];
316
+ 501: components['responses']['NotImplementedProblemResponse'];
317
+ default: components['responses']['UnexpectedProblemResponse'];
305
318
  };
306
319
  };
307
320
  /** @description Get meter by slugs */
308
321
  getMeter: {
309
322
  parameters: {
310
- header?: {
311
- "OM-Namespace"?: components["parameters"]["namespaceParam"];
312
- };
313
323
  path: {
314
- meterIdOrSlug: components["parameters"]["meterIdOrSlug"];
324
+ meterIdOrSlug: components['parameters']['meterIdOrSlug'];
315
325
  };
316
326
  };
317
327
  responses: {
318
328
  /** @description OK */
319
329
  200: {
320
330
  content: {
321
- "application/json": components["schemas"]["Meter"];
331
+ 'application/json': components['schemas']['Meter'];
322
332
  };
323
333
  };
324
- 404: components["responses"]["NotFoundProblemResponse"];
325
- default: components["responses"]["UnexpectedProblemResponse"];
334
+ 404: components['responses']['NotFoundProblemResponse'];
335
+ default: components['responses']['UnexpectedProblemResponse'];
326
336
  };
327
337
  };
328
338
  /** @description Delete meter by slug */
329
339
  deleteMeter: {
330
340
  parameters: {
331
- header?: {
332
- "OM-Namespace"?: components["parameters"]["namespaceParam"];
333
- };
334
341
  path: {
335
- meterIdOrSlug: components["parameters"]["meterIdOrSlug"];
342
+ meterIdOrSlug: components['parameters']['meterIdOrSlug'];
336
343
  };
337
344
  };
338
345
  responses: {
@@ -340,75 +347,60 @@ export interface operations {
340
347
  204: {
341
348
  content: never;
342
349
  };
343
- 404: components["responses"]["NotFoundProblemResponse"];
344
- 501: components["responses"]["NotImplementedProblemResponse"];
345
- default: components["responses"]["UnexpectedProblemResponse"];
350
+ 404: components['responses']['NotFoundProblemResponse'];
351
+ 501: components['responses']['NotImplementedProblemResponse'];
352
+ default: components['responses']['UnexpectedProblemResponse'];
346
353
  };
347
354
  };
348
- /** @description Get meter values */
349
- getMeterValues: {
355
+ /** @description Query meter */
356
+ queryMeter: {
350
357
  parameters: {
351
358
  query?: {
352
- subject?: string;
353
- /**
354
- * @description Start date-time in RFC 3339 format.
355
- * Must be aligned with the window size.
356
- * Inclusive.
357
- */
358
- from?: string;
359
- /**
360
- * @description End date-time in RFC 3339 format.
361
- * Must be aligned with the window size.
362
- * Inclusive.
363
- */
364
- to?: string;
365
- /** @description If not specified, a single usage aggregate will be returned for the entirety of the specified period for each subject and group. */
366
- windowSize?: components["schemas"]["WindowSize"];
367
- /**
368
- * @description If not specified, OpenMeter will use the default aggregation type.
369
- * As OpenMeter stores aggregates defined by meter config, passing a different aggregate can lead to inaccurate results.
370
- * For example getting the MIN of SUMs.
371
- */
372
- aggregation?: components["schemas"]["MeterAggregation"];
373
- /** @description If not specified a single aggregate will be returned for each subject and time window. */
374
- groupBy?: string;
375
- };
376
- header?: {
377
- "OM-Namespace"?: components["parameters"]["namespaceParam"];
359
+ from?: components['parameters']['queryFrom'];
360
+ to?: components['parameters']['queryTo'];
361
+ windowSize?: components['parameters']['queryWindowSize'];
362
+ subject?: components['parameters']['querySubject'];
363
+ groupBy?: components['parameters']['queryGroupBy'];
378
364
  };
379
365
  path: {
380
- meterIdOrSlug: components["parameters"]["meterIdOrSlug"];
366
+ meterIdOrSlug: components['parameters']['meterIdOrSlug'];
381
367
  };
382
368
  };
383
369
  responses: {
384
370
  /** @description OK */
385
371
  200: {
386
372
  content: {
387
- "application/json": {
388
- windowSize?: components["schemas"]["WindowSize"];
389
- data: components["schemas"]["MeterValue"][];
373
+ 'application/json': {
374
+ /** Format: date-time */
375
+ from?: string;
376
+ /** Format: date-time */
377
+ to?: string;
378
+ windowSize?: components['schemas']['WindowSize'];
379
+ data: components['schemas']['MeterQueryRow'][];
390
380
  };
381
+ 'text/csv': string;
391
382
  };
392
383
  };
393
- 400: components["responses"]["BadRequestProblemResponse"];
394
- default: components["responses"]["UnexpectedProblemResponse"];
384
+ 400: components['responses']['BadRequestProblemResponse'];
385
+ default: components['responses']['UnexpectedProblemResponse'];
395
386
  };
396
387
  };
397
- /** @description Create namespace */
398
- createNamespace: {
399
- requestBody: {
400
- content: {
401
- "application/json": components["schemas"]["Namespace"];
388
+ /** @description List meter subjects */
389
+ listMeterSubjects: {
390
+ parameters: {
391
+ path: {
392
+ meterIdOrSlug: components['parameters']['meterIdOrSlug'];
402
393
  };
403
394
  };
404
395
  responses: {
405
- /** @description Created */
406
- 201: {
396
+ /** @description OK */
397
+ 200: {
407
398
  content: {
408
- "application/json": components["schemas"]["Namespace"];
399
+ 'application/json': string[];
409
400
  };
410
401
  };
411
- default: components["responses"]["UnexpectedProblemResponse"];
402
+ 400: components['responses']['BadRequestProblemResponse'];
403
+ default: components['responses']['UnexpectedProblemResponse'];
412
404
  };
413
405
  };
414
406
  }
@@ -1,13 +1,14 @@
1
1
  import { MockAgent } from 'undici';
2
- import { mockMeter, mockMeterValue } from './mocks.js';
2
+ import { mockEvent, mockMeter, mockMeterValue } from './mocks.js';
3
3
  export const mockAgent = new MockAgent();
4
4
  mockAgent.disableNetConnect();
5
5
  const client = mockAgent.get('http://127.0.0.1:8888');
6
- client.intercept({
6
+ client
7
+ .intercept({
7
8
  path: '/api/v1/events',
8
9
  method: 'POST',
9
10
  headers: {
10
- 'Accept': 'application/json',
11
+ Accept: 'application/json',
11
12
  'Content-Type': 'application/cloudevents+json',
12
13
  },
13
14
  body: JSON.stringify({
@@ -20,14 +21,28 @@ client.intercept({
20
21
  data: {
21
22
  api_calls: 1,
22
23
  },
23
- })
24
+ }),
24
25
  })
25
26
  .reply(204);
26
- client.intercept({
27
+ client
28
+ .intercept({
29
+ path: `/api/v1/events`,
30
+ method: 'GET',
31
+ headers: {
32
+ Accept: 'application/json',
33
+ },
34
+ })
35
+ .reply(200, [mockEvent], {
36
+ headers: {
37
+ 'Content-Type': 'application/json',
38
+ },
39
+ });
40
+ client
41
+ .intercept({
27
42
  path: '/api/v1/events',
28
43
  method: 'POST',
29
44
  headers: {
30
- 'Accept': 'application/json',
45
+ Accept: 'application/json',
31
46
  'Content-Type': 'application/cloudevents+json',
32
47
  },
33
48
  body: JSON.stringify({
@@ -39,67 +54,131 @@ client.intercept({
39
54
  data: {
40
55
  api_calls: 1,
41
56
  },
42
- })
57
+ }),
43
58
  })
44
59
  .reply(204);
45
- client.intercept({
60
+ client
61
+ .intercept({
46
62
  path: '/api/v1/meters',
47
63
  method: 'GET',
48
64
  headers: {
49
- 'Accept': 'application/json'
50
- }
65
+ Accept: 'application/json',
66
+ },
51
67
  })
52
68
  .reply(200, [mockMeter], {
53
69
  headers: {
54
- 'Content-Type': 'application/json'
55
- }
70
+ 'Content-Type': 'application/json',
71
+ },
56
72
  });
57
- client.intercept({
73
+ client
74
+ .intercept({
58
75
  path: `/api/v1/meters/${mockMeter.slug}`,
59
76
  method: 'GET',
60
77
  headers: {
61
- 'Accept': 'application/json'
62
- }
78
+ Accept: 'application/json',
79
+ },
63
80
  })
64
81
  .reply(200, mockMeter, {
65
82
  headers: {
66
- 'Content-Type': 'application/json'
67
- }
83
+ 'Content-Type': 'application/json',
84
+ },
68
85
  });
69
- client.intercept({
86
+ /** Meter Values */
87
+ client
88
+ .intercept({
70
89
  path: `/api/v1/meters/${mockMeter.slug}/values`,
71
90
  query: {},
72
91
  method: 'GET',
73
92
  headers: {
74
- 'Accept': 'application/json'
75
- }
93
+ Accept: 'application/json',
94
+ },
76
95
  })
77
96
  .reply(200, {
78
97
  windowSize: 'HOUR',
79
- data: [mockMeterValue]
98
+ data: [mockMeterValue],
80
99
  }, {
81
100
  headers: {
82
- 'Content-Type': 'application/json'
83
- }
101
+ 'Content-Type': 'application/json',
102
+ },
84
103
  });
85
- client.intercept({
104
+ client
105
+ .intercept({
86
106
  path: `/api/v1/meters/${mockMeter.slug}/values`,
87
107
  query: {
88
108
  subject: 'user-1',
89
109
  from: new Date('2021-01-01').toISOString(),
90
110
  to: new Date('2021-01-02').toISOString(),
91
- windowSize: 'HOUR'
111
+ windowSize: 'HOUR',
112
+ },
113
+ method: 'GET',
114
+ headers: {
115
+ Accept: 'application/json',
116
+ },
117
+ })
118
+ .reply(200, {
119
+ windowSize: 'HOUR',
120
+ data: [mockMeterValue],
121
+ }, {
122
+ headers: {
123
+ 'Content-Type': 'application/json',
124
+ },
125
+ });
126
+ /** Meter Query */
127
+ client
128
+ .intercept({
129
+ path: `/api/v1/meters/${mockMeter.slug}/query`,
130
+ query: {},
131
+ method: 'GET',
132
+ headers: {
133
+ Accept: 'application/json',
134
+ },
135
+ })
136
+ .reply(200, {
137
+ from: mockMeterValue.windowStart,
138
+ to: mockMeterValue.windowEnd,
139
+ windowSize: 'HOUR',
140
+ data: [mockMeterValue],
141
+ }, {
142
+ headers: {
143
+ 'Content-Type': 'application/json',
144
+ },
145
+ });
146
+ client
147
+ .intercept({
148
+ path: `/api/v1/meters/${mockMeter.slug}/query`,
149
+ query: {
150
+ subject: 'user-1',
151
+ groupBy: 'a,b',
152
+ from: new Date('2021-01-01').toISOString(),
153
+ to: new Date('2021-01-02').toISOString(),
154
+ windowSize: 'HOUR',
92
155
  },
93
156
  method: 'GET',
94
157
  headers: {
95
- 'Accept': 'application/json'
96
- }
158
+ Accept: 'application/json',
159
+ },
97
160
  })
98
161
  .reply(200, {
162
+ from: mockMeterValue.windowStart,
163
+ to: mockMeterValue.windowEnd,
99
164
  windowSize: 'HOUR',
100
- data: [mockMeterValue]
165
+ data: [mockMeterValue],
101
166
  }, {
102
167
  headers: {
103
- 'Content-Type': 'application/json'
104
- }
168
+ 'Content-Type': 'application/json',
169
+ },
170
+ });
171
+ /** Meter Subjects */
172
+ client
173
+ .intercept({
174
+ path: `/api/v1/meters/${mockMeter.slug}/subjects`,
175
+ method: 'GET',
176
+ headers: {
177
+ Accept: 'application/json',
178
+ },
179
+ })
180
+ .reply(200, [mockMeterValue.subject], {
181
+ headers: {
182
+ 'Content-Type': 'application/json',
183
+ },
105
184
  });
@@ -1,4 +1,5 @@
1
- import { Meter } from "../index.js";
1
+ import { Event, Meter } from '../index.js';
2
+ export declare const mockEvent: Event;
2
3
  export declare const mockMeter: Meter;
3
4
  export declare const mockMeterValue: {
4
5
  subject: string;