weflayr 0.22.1 → 0.22.2

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.
@@ -48,7 +48,7 @@ async function withClientReturning(responseBody, statusCode, run, clientOptions
48
48
 
49
49
  test('client sends the bearer key to the configured host', async () => {
50
50
  await withClientReturning({ rows: [] }, 200, async (client, seenRequests) => {
51
- const { data } = await api.getAllRevenue({ client, throwOnError: true });
51
+ const { data } = await api.getRevenue({ client, throwOnError: true });
52
52
  assert.deepEqual(data, { rows: [] });
53
53
  assert.deepEqual(seenRequests, [
54
54
  { method: 'GET', url: '/api/revenue/', authorization: 'Bearer wf-test-key', body: null },
@@ -82,7 +82,7 @@ test('client picks up apiKey from WEFLAYR_API_KEY env var', async () => {
82
82
  { rows: [] },
83
83
  200,
84
84
  async (client, seenRequests) => {
85
- await api.getAllRevenue({ client, throwOnError: true });
85
+ await api.getRevenue({ client, throwOnError: true });
86
86
  assert.equal(seenRequests[0].authorization, 'Bearer env-key');
87
87
  },
88
88
  { apiKey: undefined }
@@ -97,8 +97,8 @@ test('client picks up apiKey from WEFLAYR_API_KEY env var', async () => {
97
97
  test('setRevenue posts the rows in snake_case and parses the booked count', async () => {
98
98
  await withClientReturning({ ok: true, rows_inserted: 2 }, 200, async (client, seenRequests) => {
99
99
  const rows = [
100
- { customerName: 'c_1', amount: '1200.50', month: '2026-06' },
101
- { customerName: 'c_2', amount: '800', month: '2026-06' },
100
+ { customerName: 'c_1', amount: 1200.5, month: '2026-06' },
101
+ { customerName: 'c_2', amount: 800, month: '2026-06' },
102
102
  ];
103
103
  const { data } = await api.setRevenue({ client, throwOnError: true, body: { rows } });
104
104
  assert.deepEqual(data, { ok: true, rowsInserted: 2 });
@@ -107,70 +107,91 @@ test('setRevenue posts the rows in snake_case and parses the booked count', asyn
107
107
  assert.equal(request.url, '/api/revenue/');
108
108
  assert.deepEqual(request.body, {
109
109
  rows: [
110
- { customer_name: 'c_1', amount: '1200.50', month: '2026-06' },
111
- { customer_name: 'c_2', amount: '800', month: '2026-06' },
110
+ { customer_name: 'c_1', amount: 1200.5, month: '2026-06' },
111
+ { customer_name: 'c_2', amount: 800, month: '2026-06' },
112
112
  ],
113
113
  });
114
114
  });
115
115
  });
116
116
 
117
- test('getAllRevenue parses the returned rows into camelCase', async () => {
117
+ test('setRevenue posts the revenueId in snake_case and the upsert flag', async () => {
118
+ await withClientReturning({ ok: true, rows_inserted: 1 }, 200, async (client, seenRequests) => {
119
+ const rows = [
120
+ {
121
+ revenueId: 'b3f2b160-6e12-4f1a-9c3d-0a2e7c9b5d41',
122
+ customerName: 'c_1',
123
+ amount: 1300,
124
+ month: '2026-06',
125
+ },
126
+ ];
127
+ const { data } = await api.setRevenue({
128
+ client,
129
+ throwOnError: true,
130
+ body: { upsert: true, rows },
131
+ });
132
+ assert.deepEqual(data, { ok: true, rowsInserted: 1 });
133
+ assert.deepEqual(seenRequests[0].body, {
134
+ upsert: true,
135
+ rows: [
136
+ {
137
+ revenue_id: 'b3f2b160-6e12-4f1a-9c3d-0a2e7c9b5d41',
138
+ customer_name: 'c_1',
139
+ amount: 1300,
140
+ month: '2026-06',
141
+ },
142
+ ],
143
+ });
144
+ });
145
+ });
146
+
147
+ test('getRevenue parses the returned rows into camelCase', async () => {
118
148
  const wireRow = {
119
149
  customer_name: 'c_1',
120
150
  metric_name: 'revenue',
121
151
  month: '2026-06',
122
- amount: '1200.50000000',
152
+ amount: 1200.5,
123
153
  source: 'api',
124
154
  };
125
155
  await withClientReturning({ rows: [wireRow] }, 200, async (client) => {
126
- const { data } = await api.getAllRevenue({ client, throwOnError: true });
156
+ const { data } = await api.getRevenue({ client, throwOnError: true });
127
157
  assert.deepEqual(data.rows, [
128
158
  {
129
159
  customerName: 'c_1',
130
160
  metricName: 'revenue',
131
161
  month: '2026-06',
132
- amount: '1200.50000000',
162
+ amount: 1200.5,
133
163
  source: 'api',
134
164
  },
135
165
  ]);
136
166
  });
137
167
  });
138
168
 
139
- test('getCustomerRevenue requests the customer path', async () => {
169
+ test('getRevenue sends the customerNames filter as repeated params', async () => {
140
170
  await withClientReturning({ rows: [] }, 200, async (client, seenRequests) => {
141
- const { data } = await api.getCustomerRevenue({
171
+ const { data } = await api.getRevenue({
142
172
  client,
143
173
  throwOnError: true,
144
- path: { customerName: 'c_1' },
174
+ query: { customerNames: ['c_1', 'c_2'] },
145
175
  });
146
176
  assert.deepEqual(data, { rows: [] });
147
- assert.equal(seenRequests[0].url, '/api/revenue/c_1/');
148
- });
149
- });
150
-
151
- test('getCustomerRevenue surfaces a 404 and its error', async () => {
152
- const rejection = { error: 'No revenue for this customer.' };
153
- await withClientReturning(rejection, 404, async (client) => {
154
- const { error, response } = await api.getCustomerRevenue({
155
- client,
156
- path: { customerName: 'nobody' },
157
- });
158
- assert.equal(response.status, 404);
159
- assert.deepEqual(error, rejection);
177
+ const query = new URL(seenRequests[0].url, 'http://x').searchParams;
178
+ assert.deepEqual(query.getAll('customer_names'), ['c_1', 'c_2']);
160
179
  });
161
180
  });
162
181
 
163
- test('deleteCustomerRevenue parses the deleted count', async () => {
164
- await withClientReturning({ ok: true, rows_deleted: 1 }, 200, async (client, seenRequests) => {
165
- const { data } = await api.deleteCustomerRevenue({
182
+ test('deleteRevenue sends the customerNames filter and parses the deleted count', async () => {
183
+ await withClientReturning({ ok: true, rows_deleted: 2 }, 200, async (client, seenRequests) => {
184
+ const { data } = await api.deleteRevenue({
166
185
  client,
167
186
  throwOnError: true,
168
- path: { customerName: 'c_1' },
187
+ query: { customerNames: ['c_1', 'c_2'] },
169
188
  });
170
- assert.deepEqual(data, { ok: true, rowsDeleted: 1 });
189
+ assert.deepEqual(data, { ok: true, rowsDeleted: 2 });
171
190
  const request = seenRequests[0];
172
191
  assert.equal(request.method, 'DELETE');
173
- assert.equal(request.url, '/api/revenue/c_1/');
192
+ const url = new URL(request.url, 'http://x');
193
+ assert.equal(url.pathname, '/api/revenue/');
194
+ assert.deepEqual(url.searchParams.getAll('customer_names'), ['c_1', 'c_2']);
174
195
  });
175
196
  });
176
197
 
@@ -178,51 +199,50 @@ test('deleteCustomerRevenue parses the deleted count', async () => {
178
199
 
179
200
  test('setKeyMetrics posts the rows in snake_case and parses the booked count', async () => {
180
201
  await withClientReturning({ ok: true, rows_inserted: 1 }, 200, async (client, seenRequests) => {
181
- const rows = [
182
- { userName: 'u_1', metricName: 'Meetings booked', amount: '3', month: '2026-06' },
183
- ];
202
+ const rows = [{ userName: 'u_1', metricName: 'Meetings booked', amount: 3, month: '2026-06' }];
184
203
  const { data } = await api.setKeyMetrics({ client, throwOnError: true, body: { rows } });
185
204
  assert.deepEqual(data, { ok: true, rowsInserted: 1 });
186
205
  const request = seenRequests[0];
187
206
  assert.equal(request.method, 'POST');
188
207
  assert.equal(request.url, '/api/key-metrics/');
189
208
  assert.deepEqual(request.body, {
190
- rows: [{ user_name: 'u_1', metric_name: 'Meetings booked', amount: '3', month: '2026-06' }],
209
+ rows: [{ user_name: 'u_1', metric_name: 'Meetings booked', amount: 3, month: '2026-06' }],
191
210
  });
192
211
  });
193
212
  });
194
213
 
195
- test('getAllKeyMetrics parses the returned rows into camelCase', async () => {
214
+ test('getKeyMetrics parses the returned rows into camelCase', async () => {
196
215
  const wireRow = {
197
216
  user_name: 'u_1',
198
217
  metric_name: 'Meetings booked',
199
218
  month: '2026-06',
200
- amount: '3.00000000',
219
+ amount: 3.0,
201
220
  source: 'api',
202
221
  };
203
222
  await withClientReturning({ rows: [wireRow] }, 200, async (client) => {
204
- const { data } = await api.getAllKeyMetrics({ client, throwOnError: true });
223
+ const { data } = await api.getKeyMetrics({ client, throwOnError: true });
205
224
  assert.deepEqual(data.rows, [
206
225
  {
207
226
  userName: 'u_1',
208
227
  metricName: 'Meetings booked',
209
228
  month: '2026-06',
210
- amount: '3.00000000',
229
+ amount: 3.0,
211
230
  source: 'api',
212
231
  },
213
232
  ]);
214
233
  });
215
234
  });
216
235
 
217
- test('getUserKeyMetrics requests the user path', async () => {
236
+ test('getKeyMetrics sends the userNames filter as repeated params', async () => {
218
237
  await withClientReturning({ rows: [] }, 200, async (client, seenRequests) => {
219
- const { data } = await api.getUserKeyMetrics({
238
+ const { data } = await api.getKeyMetrics({
220
239
  client,
221
240
  throwOnError: true,
222
- path: { userName: 'u_1' },
241
+ query: { userNames: ['u_1', 'u_2'] },
223
242
  });
224
243
  assert.deepEqual(data, { rows: [] });
225
- assert.equal(seenRequests[0].url, '/api/key-metrics/u_1/');
244
+ const query = new URL(seenRequests[0].url, 'http://x').searchParams;
245
+ assert.deepEqual(query.getAll('user_names'), ['u_1', 'u_2']);
226
246
  });
227
247
  });
228
248
 
@@ -238,17 +258,19 @@ test('setKeyMetrics surfaces a 422 and its details', async () => {
238
258
  });
239
259
  });
240
260
 
241
- test('deleteUserKeyMetrics parses the deleted count', async () => {
242
- await withClientReturning({ ok: true, rows_deleted: 1 }, 200, async (client, seenRequests) => {
243
- const { data } = await api.deleteUserKeyMetrics({
261
+ test('deleteKeyMetrics sends the userNames filter and parses the deleted count', async () => {
262
+ await withClientReturning({ ok: true, rows_deleted: 2 }, 200, async (client, seenRequests) => {
263
+ const { data } = await api.deleteKeyMetrics({
244
264
  client,
245
265
  throwOnError: true,
246
- path: { userName: 'u_1' },
266
+ query: { userNames: ['u_1', 'u_2'] },
247
267
  });
248
- assert.deepEqual(data, { ok: true, rowsDeleted: 1 });
268
+ assert.deepEqual(data, { ok: true, rowsDeleted: 2 });
249
269
  const request = seenRequests[0];
250
270
  assert.equal(request.method, 'DELETE');
251
- assert.equal(request.url, '/api/key-metrics/u_1/');
271
+ const url = new URL(request.url, 'http://x');
272
+ assert.equal(url.pathname, '/api/key-metrics/');
273
+ assert.deepEqual(url.searchParams.getAll('user_names'), ['u_1', 'u_2']);
252
274
  });
253
275
  });
254
276
 
@@ -290,41 +312,50 @@ test('setCustomersTags leaves tag keys untouched, even when they contain undersc
290
312
  );
291
313
  });
292
314
 
293
- test('getAllCustomersTags parses the returned customers into camelCase', async () => {
315
+ test('getCustomersTags parses the returned customers into camelCase', async () => {
294
316
  const wireCustomer = { customer_name: 'c_1', tags: { plan: 'pro' } };
295
317
  await withClientReturning(
296
318
  { customers: [wireCustomer], next_cursor: null, has_more: false },
297
319
  200,
298
320
  async (client) => {
299
- const { data } = await api.getAllCustomersTags({ client, throwOnError: true });
321
+ const { data } = await api.getCustomersTags({ client, throwOnError: true });
300
322
  assert.deepEqual(data.customers, [{ customerName: 'c_1', tags: { plan: 'pro' } }]);
301
323
  }
302
324
  );
303
325
  });
304
326
 
305
- test('getCustomerTags parses the customer tags, leaving tag keys untouched', async () => {
306
- const wireTags = { customer_name: 'c_1', tags: { plan: 'pro', utm_source: 'ads' } };
307
- await withClientReturning(wireTags, 200, async (client, seenRequests) => {
308
- const { data } = await api.getCustomerTags({
309
- client,
310
- throwOnError: true,
311
- path: { customerName: 'c_1' },
312
- });
313
- assert.deepEqual(data, { customerName: 'c_1', tags: { plan: 'pro', utm_source: 'ads' } });
314
- assert.equal(seenRequests[0].url, '/api/customer-tags/c_1/');
315
- });
327
+ test('getCustomersTags sends the customerNames filter, leaving tag keys untouched', async () => {
328
+ const wireCustomer = { customer_name: 'c_1', tags: { plan: 'pro', utm_source: 'ads' } };
329
+ await withClientReturning(
330
+ { customers: [wireCustomer], next_cursor: null, has_more: false },
331
+ 200,
332
+ async (client, seenRequests) => {
333
+ const { data } = await api.getCustomersTags({
334
+ client,
335
+ throwOnError: true,
336
+ query: { customerNames: ['c_1', 'c_2'] },
337
+ });
338
+ assert.deepEqual(data.customers, [
339
+ { customerName: 'c_1', tags: { plan: 'pro', utm_source: 'ads' } },
340
+ ]);
341
+ const query = new URL(seenRequests[0].url, 'http://x').searchParams;
342
+ assert.deepEqual(query.getAll('customer_names'), ['c_1', 'c_2']);
343
+ }
344
+ );
316
345
  });
317
346
 
318
- test('deleteCustomerTags parses the deleted count', async () => {
319
- await withClientReturning({ ok: true, tags_deleted: 1 }, 200, async (client, seenRequests) => {
320
- const { data } = await api.deleteCustomerTags({
347
+ test('deleteCustomersTags sends the customerNames filter and parses the deleted count', async () => {
348
+ await withClientReturning({ ok: true, tags_deleted: 3 }, 200, async (client, seenRequests) => {
349
+ const { data } = await api.deleteCustomersTags({
321
350
  client,
322
351
  throwOnError: true,
323
- path: { customerName: 'c_1' },
352
+ query: { customerNames: ['c_1', 'c_2'] },
324
353
  });
325
- assert.deepEqual(data, { ok: true, tagsDeleted: 1 });
354
+ assert.deepEqual(data, { ok: true, tagsDeleted: 3 });
326
355
  const request = seenRequests[0];
327
356
  assert.equal(request.method, 'DELETE');
328
- assert.equal(request.url, '/api/customer-tags/c_1/');
357
+ const url = new URL(request.url, 'http://x');
358
+ assert.equal(url.pathname, '/api/customer-tags/');
359
+ assert.deepEqual(url.searchParams.getAll('customer_names'), ['c_1', 'c_2']);
329
360
  });
330
361
  });