@crvouga/mockingbird-service-junction 0.1.0 → 0.1.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.
Files changed (62) hide show
  1. package/README.md +23 -11
  2. package/dist/index.d.ts +492 -21
  3. package/dist/index.js +6086 -107
  4. package/dist/index.js.map +7 -1
  5. package/package.json +11 -10
  6. package/dist/catalog.d.ts +0 -63
  7. package/dist/catalog.d.ts.map +0 -1
  8. package/dist/catalog.js +0 -736
  9. package/dist/catalog.js.map +0 -1
  10. package/dist/coverage-corpus.d.ts +0 -76
  11. package/dist/coverage-corpus.d.ts.map +0 -1
  12. package/dist/coverage-corpus.js +0 -166
  13. package/dist/coverage-corpus.js.map +0 -1
  14. package/dist/generated/openapi.d.ts +0 -7
  15. package/dist/generated/openapi.d.ts.map +0 -1
  16. package/dist/generated/openapi.js +0 -5
  17. package/dist/generated/openapi.js.map +0 -1
  18. package/dist/index.d.ts.map +0 -1
  19. package/dist/lab-accounts.d.ts +0 -38
  20. package/dist/lab-accounts.d.ts.map +0 -1
  21. package/dist/lab-accounts.js +0 -213
  22. package/dist/lab-accounts.js.map +0 -1
  23. package/dist/orders.d.ts +0 -18
  24. package/dist/orders.d.ts.map +0 -1
  25. package/dist/orders.js +0 -1247
  26. package/dist/orders.js.map +0 -1
  27. package/dist/prefetch.d.ts +0 -43
  28. package/dist/prefetch.d.ts.map +0 -1
  29. package/dist/prefetch.js +0 -131
  30. package/dist/prefetch.js.map +0 -1
  31. package/dist/reshape.d.ts +0 -22
  32. package/dist/reshape.d.ts.map +0 -1
  33. package/dist/reshape.js +0 -190
  34. package/dist/reshape.js.map +0 -1
  35. package/dist/results.d.ts +0 -19
  36. package/dist/results.d.ts.map +0 -1
  37. package/dist/results.js +0 -221
  38. package/dist/results.js.map +0 -1
  39. package/dist/scheduling.d.ts +0 -113
  40. package/dist/scheduling.d.ts.map +0 -1
  41. package/dist/scheduling.js +0 -1508
  42. package/dist/scheduling.js.map +0 -1
  43. package/dist/sealed-corpus.d.ts +0 -28
  44. package/dist/sealed-corpus.d.ts.map +0 -1
  45. package/dist/sealed-corpus.js +0 -17
  46. package/dist/sealed-corpus.js.map +0 -1
  47. package/dist/seed-from.d.ts +0 -27
  48. package/dist/seed-from.d.ts.map +0 -1
  49. package/dist/seed-from.js +0 -523
  50. package/dist/seed-from.js.map +0 -1
  51. package/dist/seeds.d.ts +0 -9
  52. package/dist/seeds.d.ts.map +0 -1
  53. package/dist/seeds.js +0 -9
  54. package/dist/seeds.js.map +0 -1
  55. package/dist/state.d.ts +0 -270
  56. package/dist/state.d.ts.map +0 -1
  57. package/dist/state.js +0 -448
  58. package/dist/state.js.map +0 -1
  59. package/dist/users.d.ts +0 -13
  60. package/dist/users.d.ts.map +0 -1
  61. package/dist/users.js +0 -669
  62. package/dist/users.js.map +0 -1
package/dist/users.js DELETED
@@ -1,669 +0,0 @@
1
- import { HttpError, jsonRes } from "@crvouga/mockingbird-service";
2
- import { MOCK_TEAM_ID } from "./state.js";
3
- const jsonBody = (context) => {
4
- const body = context.body;
5
- const value = body.kind === "json" ? body.value : undefined;
6
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
7
- throw new HttpError(422, {
8
- detail: [
9
- {
10
- type: "model_attributes_type",
11
- loc: ["body"],
12
- msg: "Input should be a valid dictionary or object to extract fields from",
13
- input: value,
14
- },
15
- ],
16
- });
17
- }
18
- return value;
19
- };
20
- const render = (user, rawEnd = false) => ({
21
- user_id: user.user_id,
22
- team_id: user.team_id,
23
- client_user_id: user.client_user_id,
24
- created_on: user.created_on,
25
- connected_sources: user.connected_sources,
26
- fallback_time_zone: user.fallback_time_zone,
27
- fallback_birth_date: user.fallback_birth_date,
28
- ingestion_start: user.ingestion_start,
29
- ingestion_end: rawEnd
30
- ? user.ingestion_end
31
- : user.ingestion_start === null
32
- ? null
33
- : (user.ingestion_end ?? "0001-01-01"),
34
- });
35
- const listUsers = (state, offset, limit) => {
36
- // Sandbox lists by created_on desc; same-second ties follow creation order
37
- // (collection newest), not UUID lexicographic order.
38
- const all = [...state.users.list({ order: "newest" })].sort((left, right) => {
39
- const leftAt = Date.parse(String(left.value.created_on ?? "")) || 0;
40
- const rightAt = Date.parse(String(right.value.created_on ?? "")) || 0;
41
- if (rightAt !== leftAt)
42
- return rightAt - leftAt;
43
- return 0;
44
- });
45
- const users = all.slice(offset, offset + limit).map((entry) => render(entry.value, true));
46
- return {
47
- users,
48
- total: users.length === 0 ? 0 : all.length,
49
- offset,
50
- limit,
51
- };
52
- };
53
- const isValidUuid = (value) => /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(value);
54
- function notFound(detail) {
55
- throw new HttpError(404, { detail });
56
- }
57
- const queryInt = (context, name, fallback) => {
58
- const raw = context.query[name];
59
- if (raw === undefined)
60
- return fallback;
61
- if (typeof raw !== "string" || !/^-?\d+$/.test(raw))
62
- throw new HttpError(422, { detail: `${name} must be an integer` });
63
- return Number(raw);
64
- };
65
- const isValidIanaTimezone = (value) => {
66
- try {
67
- new Intl.DateTimeFormat("en-US", { timeZone: value });
68
- return true;
69
- }
70
- catch {
71
- return false;
72
- }
73
- };
74
- const isValidDate = (value) => {
75
- if (!/^\d{4}-\d{2}-\d{2}$/.test(value))
76
- return false;
77
- const [year, month, day] = value.split("-").map(Number);
78
- const y = year ?? 0;
79
- const m = month ?? 0;
80
- const d = day ?? 0;
81
- const date = new Date(Date.UTC(y, m - 1, d));
82
- return date.getUTCFullYear() === y && date.getUTCMonth() === m - 1 && date.getUTCDate() === d;
83
- };
84
- const stringError = (path, value) => ({
85
- type: "string_type",
86
- loc: ["body", ...path.split(".")],
87
- msg: "Input should be a valid string",
88
- input: value,
89
- });
90
- const missingError = (path, input) => ({
91
- type: "missing",
92
- loc: ["body", ...path.split(".")],
93
- msg: "Field required",
94
- input,
95
- });
96
- const dateError = (path, value) => {
97
- const input = String(value);
98
- if (input.length <= 7) {
99
- return {
100
- type: "date_from_datetime_parsing",
101
- loc: ["body", ...path.split(".")],
102
- msg: "Input should be a valid date or datetime, input is too short",
103
- input: value,
104
- ctx: { error: "input is too short" },
105
- };
106
- }
107
- return {
108
- type: "date_from_datetime_parsing",
109
- loc: ["body", ...path.split(".")],
110
- msg: "Input should be a valid date or datetime, invalid character in year",
111
- input: value,
112
- ctx: { error: "invalid character in year" },
113
- };
114
- };
115
- /** Pydantic-style email validation mirroring the sandbox's error reasons. */
116
- const emailErrorOf = (value) => {
117
- if (!value.includes("@")) {
118
- return {
119
- msg: "value is not a valid email address: An email address must have an @-sign.",
120
- reason: "An email address must have an @-sign.",
121
- };
122
- }
123
- const [local = "", ...domainParts] = value.split("@");
124
- const domain = domainParts.join("@");
125
- if (local === "") {
126
- return {
127
- msg: "value is not a valid email address: There must be something before the @-sign.",
128
- reason: "There must be something before the @-sign.",
129
- };
130
- }
131
- if (domain === "") {
132
- return {
133
- msg: "value is not a valid email address: There must be something after the @-sign.",
134
- reason: "There must be something after the @-sign.",
135
- };
136
- }
137
- if (/\s/.test(local)) {
138
- return {
139
- msg: `value is not a valid email address: The email address contains invalid characters before the @-sign: ${describeLocalChar(local)}.`,
140
- reason: `The email address contains invalid characters before the @-sign: ${describeLocalChar(local)}.`,
141
- };
142
- }
143
- if (domain.includes("@") || /[^a-zA-Z0-9.\-_]/.test(domain)) {
144
- return {
145
- msg: `value is not a valid email address: The part after the @-sign contains invalid characters: '@'.`,
146
- reason: `The part after the @-sign contains invalid characters: '@'.`,
147
- };
148
- }
149
- if (!domain.includes(".")) {
150
- return {
151
- msg: "value is not a valid email address: The part after the @-sign is not valid. It should have a period.",
152
- reason: "The part after the @-sign is not valid. It should have a period.",
153
- };
154
- }
155
- return undefined;
156
- };
157
- const describeLocalChar = (local) => {
158
- for (const character of local) {
159
- if (/\s/.test(character))
160
- return character === " " ? "SPACE" : "WS";
161
- }
162
- return characterDescription(local);
163
- };
164
- const characterDescription = (value) => {
165
- for (const character of value) {
166
- if (!/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]/.test(character)) {
167
- const code = character.codePointAt(0) ?? 0;
168
- if (code > 126)
169
- return "NON printable";
170
- return `'${character}'`;
171
- }
172
- }
173
- return "SPACE";
174
- };
175
- const emailValidationError = (value) => {
176
- const error = emailErrorOf(value);
177
- if (!error)
178
- return undefined;
179
- return {
180
- type: "value_error",
181
- loc: ["body", "email"],
182
- msg: error.msg,
183
- input: value,
184
- ctx: { reason: error.reason },
185
- };
186
- };
187
- /** Pydantic date parsing mirroring the sandbox's `date` field error taxonomy. */
188
- const dobValidationError = (value) => {
189
- if (typeof value === "string") {
190
- const codePoints = [...value];
191
- if (codePoints.some((character) => (character.codePointAt(0) ?? 0) > 127)) {
192
- return {
193
- type: "date_from_datetime_parsing",
194
- loc: ["body", "dob"],
195
- msg: "Input should be a valid date or datetime, invalid character in year",
196
- input: value,
197
- ctx: { error: "invalid character in year" },
198
- };
199
- }
200
- if (/^\d+$/.test(value)) {
201
- return {
202
- type: "date_from_datetime_inexact",
203
- loc: ["body", "dob"],
204
- msg: "Datetimes provided to dates should have zero time - e.g. be exact dates",
205
- input: value,
206
- };
207
- }
208
- if (value.length < 10) {
209
- return {
210
- type: "date_from_datetime_parsing",
211
- loc: ["body", "dob"],
212
- msg: "Input should be a valid date or datetime, input is too short",
213
- input: value,
214
- ctx: { error: "input is too short" },
215
- };
216
- }
217
- const iso = value.match(/^(\d{4})([-/])(\d{2}|[^-])\2(\d{2}|[^-]*)(.*)$/);
218
- if (iso === null) {
219
- // Pydantic/speedate: once four year digits are consumed, a non-`-` next
220
- // character is reported as a separator error (not an invalid year char).
221
- if (/^\d{4}/.test(value)) {
222
- return {
223
- type: "date_from_datetime_parsing",
224
- loc: ["body", "dob"],
225
- msg: "Input should be a valid date or datetime, invalid date separator, expected `-`",
226
- input: value,
227
- ctx: { error: "invalid date separator, expected `-`" },
228
- };
229
- }
230
- return {
231
- type: "date_from_datetime_parsing",
232
- loc: ["body", "dob"],
233
- msg: "Input should be a valid date or datetime, invalid character in year",
234
- input: value,
235
- ctx: { error: "invalid character in year" },
236
- };
237
- }
238
- const [, year = "", separator = "-", monthRaw = "", dayRaw = "", rest = ""] = iso;
239
- if (separator !== "-") {
240
- return {
241
- type: "date_from_datetime_parsing",
242
- loc: ["body", "dob"],
243
- msg: "Input should be a valid date or datetime, invalid date separator, expected `-`",
244
- input: value,
245
- ctx: { error: "invalid date separator, expected `-`" },
246
- };
247
- }
248
- if (!/^\d+$/.test(year ?? "")) {
249
- return {
250
- type: "date_from_datetime_parsing",
251
- loc: ["body", "dob"],
252
- msg: "Input should be a valid date or datetime, invalid character in year",
253
- input: value,
254
- ctx: { error: "invalid character in year" },
255
- };
256
- }
257
- if (!/^\d+$/.test(monthRaw ?? "")) {
258
- return {
259
- type: "date_from_datetime_parsing",
260
- loc: ["body", "dob"],
261
- msg: "Input should be a valid date or datetime, invalid character in month",
262
- input: value,
263
- ctx: { error: "invalid character in month" },
264
- };
265
- }
266
- if (!/^\d+$/.test(dayRaw ?? "")) {
267
- return {
268
- type: "date_from_datetime_parsing",
269
- loc: ["body", "dob"],
270
- msg: "Input should be a valid date or datetime, invalid character in day",
271
- input: value,
272
- ctx: { error: "invalid character in day" },
273
- };
274
- }
275
- const month = Number(monthRaw);
276
- if (month < 1 || month > 12) {
277
- return {
278
- type: "date_from_datetime_parsing",
279
- loc: ["body", "dob"],
280
- msg: "Input should be a valid date or datetime, month value is outside expected range of 1-12",
281
- input: value,
282
- ctx: { error: "month value is outside expected range of 1-12" },
283
- };
284
- }
285
- const day = Number(dayRaw);
286
- const yearNumber = Number(year);
287
- const daysInMonth = new Date(Date.UTC(yearNumber, month, 0)).getUTCDate();
288
- if (day < 1 || day > daysInMonth) {
289
- return {
290
- type: "date_from_datetime_parsing",
291
- loc: ["body", "dob"],
292
- msg: "Input should be a valid date or datetime, day value is outside expected range",
293
- input: value,
294
- ctx: { error: "day value is outside expected range" },
295
- };
296
- }
297
- if (rest !== "" && !/^T00:00:00(\.\d+)?(Z|[+-]\d{2}:\d{2})?$/.test(rest)) {
298
- return {
299
- type: "date_from_datetime_inexact",
300
- loc: ["body", "dob"],
301
- msg: "Datetimes provided to dates should have zero time - e.g. be exact dates",
302
- input: value,
303
- };
304
- }
305
- return undefined;
306
- }
307
- if (typeof value === "number") {
308
- return {
309
- type: "date_from_datetime_inexact",
310
- loc: ["body", "dob"],
311
- msg: "Datetimes provided to dates should have zero time - e.g. be exact dates",
312
- input: value,
313
- };
314
- }
315
- return {
316
- type: "date_type",
317
- loc: ["body", "dob"],
318
- msg: "Input should be a valid date",
319
- input: value,
320
- };
321
- };
322
- const userInfoValidationErrors = (body) => {
323
- const errors = [];
324
- const push = (error) => {
325
- if (error)
326
- errors.push(error);
327
- };
328
- // Field-by-field, in the sandbox's fixed order; each field emits its missing OR
329
- // type/value error before moving to the next.
330
- for (const field of ["first_name", "last_name"]) {
331
- const value = body[field];
332
- if (value === undefined)
333
- push(missingError(field, body));
334
- else if (typeof value !== "string")
335
- push(stringError(field, value));
336
- }
337
- const email = body.email;
338
- if (email === undefined)
339
- push(missingError("email", body));
340
- else if (typeof email !== "string")
341
- push(stringError("email", email));
342
- else
343
- push(emailValidationError(email));
344
- const phone = body.phone_number;
345
- if (phone === undefined)
346
- push(missingError("phone_number", body));
347
- else if (phone === null) {
348
- push({
349
- type: "value_error",
350
- loc: ["body", "phone_number"],
351
- msg: "Value error, Phone number cannot be None",
352
- input: null,
353
- ctx: { error: {} },
354
- });
355
- }
356
- else if (typeof phone === "string") {
357
- const digits = phone.replace(/\D/g, "");
358
- if (digits.length < 10 || !/^[\d\s()+-]*$/.test(phone)) {
359
- push({
360
- type: "value_error",
361
- loc: ["body", "phone_number"],
362
- msg: `Value error, Invalid phone number: ${phone}`,
363
- input: phone,
364
- ctx: { error: {} },
365
- });
366
- }
367
- }
368
- const gender = body.gender;
369
- if (gender === undefined)
370
- push(missingError("gender", body));
371
- else if (typeof gender !== "string")
372
- push(stringError("gender", gender));
373
- if (body.dob === undefined)
374
- push(missingError("dob", body));
375
- else
376
- push(dobValidationError(body.dob));
377
- const address = body.address;
378
- if (address === undefined)
379
- push(missingError("address", body));
380
- else if (address === null || typeof address !== "object" || Array.isArray(address)) {
381
- push({
382
- type: "model_attributes_type",
383
- loc: ["body", "address"],
384
- msg: "Input should be a valid dictionary or object to extract fields from",
385
- input: address,
386
- });
387
- }
388
- else {
389
- const addressRecord = address;
390
- for (const field of ["first_line", "country", "zip", "city", "state"]) {
391
- const value = addressRecord[field];
392
- if (value === undefined)
393
- push(missingError(`address.${field}`, addressRecord));
394
- else if (typeof value !== "string")
395
- push(stringError(`address.${field}`, value));
396
- }
397
- if (addressRecord.second_line !== undefined && typeof addressRecord.second_line !== "string") {
398
- push(stringError("address.second_line", addressRecord.second_line));
399
- }
400
- }
401
- return errors;
402
- };
403
- export const userHandlers = (state) => ({
404
- patch_user_info_v2_user__user_id__info_patch: async (context) => {
405
- const id = context.params.user_id ?? "";
406
- const body = jsonBody(context);
407
- const errors = userInfoValidationErrors(body);
408
- if (errors.length > 0)
409
- throw new HttpError(422, { detail: errors });
410
- if (!state.users.has(id))
411
- notFound("User not found");
412
- const existing = state.userInfo.get(id) ?? {};
413
- const rawAddress = typeof body.address === "object" && body.address !== null && !Array.isArray(body.address)
414
- ? body.address
415
- : undefined;
416
- const info = {
417
- ...existing,
418
- ...body,
419
- ...(rawAddress === undefined
420
- ? {}
421
- : {
422
- address: {
423
- first_line: rawAddress.first_line ?? "",
424
- second_line: typeof rawAddress.second_line === "string" ? rawAddress.second_line : "",
425
- country: rawAddress.country ?? "",
426
- zip: rawAddress.zip ?? "",
427
- city: rawAddress.city ?? "",
428
- state: rawAddress.state ?? "",
429
- access_notes: typeof rawAddress.access_notes === "string" ? rawAddress.access_notes : null,
430
- },
431
- }),
432
- };
433
- state.userInfo.insert(id, info);
434
- return jsonRes(200, info);
435
- },
436
- create_user_v2_user_post: async (context) => {
437
- const body = jsonBody(context);
438
- const clientUserId = body.client_user_id;
439
- if (clientUserId === undefined) {
440
- throw new HttpError(422, {
441
- detail: [
442
- {
443
- type: "missing",
444
- loc: ["body", "client_user_id"],
445
- msg: "Field required",
446
- input: body,
447
- },
448
- ],
449
- });
450
- }
451
- if (typeof clientUserId !== "string") {
452
- throw new HttpError(422, {
453
- detail: [
454
- {
455
- type: "string_type",
456
- loc: ["body", "client_user_id"],
457
- msg: "Input should be a valid string",
458
- input: clientUserId,
459
- },
460
- ],
461
- });
462
- }
463
- const existing = state.byClientId.get(clientUserId);
464
- if (existing) {
465
- const user = state.users.get(existing.user_id);
466
- throw new HttpError(400, {
467
- detail: {
468
- error_type: "INVALID_REQUEST",
469
- error_message: "Client user id already exists.",
470
- user_id: existing.user_id,
471
- created_on: user?.created_on ?? state.isoNow(context.now),
472
- },
473
- });
474
- }
475
- const userId = state.nextUserId();
476
- const createdOn = state.isoNow(context.now);
477
- const tz = typeof body.fallback_time_zone === "string"
478
- ? { id: body.fallback_time_zone, source_slug: "manual", updated_at: createdOn }
479
- : null;
480
- const user = {
481
- user_id: userId,
482
- team_id: MOCK_TEAM_ID,
483
- client_user_id: clientUserId,
484
- created_on: createdOn,
485
- connected_sources: [],
486
- fallback_time_zone: tz,
487
- fallback_birth_date: null,
488
- ingestion_start: null,
489
- ingestion_end: null,
490
- };
491
- state.users.insert(userId, user);
492
- state.byClientId.insert(clientUserId, { user_id: userId });
493
- return jsonRes(200, render(user));
494
- },
495
- get_user_v2_user__user_id__get: async (context) => {
496
- const id = context.params.user_id ?? "";
497
- if (!isValidUuid(id)) {
498
- throw new HttpError(422, {
499
- detail: `Invalid format for parameter user_id: error unmarshaling '${id}' text as *uuid.UUID: invalid UUID length: ${id.length}`,
500
- });
501
- }
502
- const user = state.users.get(id);
503
- if (user)
504
- return jsonRes(200, render(user));
505
- if (state.deletedUsers.has(id)) {
506
- throw new HttpError(404, { detail: "You have scheduled this user for deletion." });
507
- }
508
- notFound("Not found");
509
- },
510
- delete_user_v2_user__user_id__delete: async (context) => {
511
- const id = context.params.user_id ?? "";
512
- const user = state.users.get(id);
513
- if (!user) {
514
- if (state.deletedUsers.has(id)) {
515
- throw new HttpError(404, {
516
- detail: "The user has been scheduled for deletion as per your previous request",
517
- });
518
- }
519
- notFound("The user does not or no longer exists in this team");
520
- }
521
- state.users.delete(id);
522
- state.byClientId.delete(user.client_user_id);
523
- state.deletedUsers.insert(id, { user_id: id });
524
- return jsonRes(200, { success: true });
525
- },
526
- get_user_by_client_user_id_v2_user_resolve__client_user_id__get: async (context) => {
527
- const clientUserId = context.params.client_user_id ?? "";
528
- const binding = state.byClientId.get(clientUserId);
529
- if (!binding)
530
- notFound("User not found");
531
- const user = state.users.get(binding.user_id);
532
- if (!user)
533
- notFound("User not found");
534
- return jsonRes(200, render(user));
535
- },
536
- patch_user_v2_user__user_id__patch: async (context) => {
537
- const id = context.params.user_id ?? "";
538
- const user = state.users.get(id);
539
- if (!user) {
540
- if (state.deletedUsers.has(id)) {
541
- throw new HttpError(404, {
542
- detail: "The user has been scheduled for deletion as per your previous request",
543
- });
544
- }
545
- notFound("The user does not or no longer exists in this team");
546
- }
547
- const body = jsonBody(context);
548
- const now = state.isoNow(context.now);
549
- const patchable = [
550
- "client_user_id",
551
- "fallback_time_zone",
552
- "fallback_birth_date",
553
- "ingestion_start",
554
- "ingestion_end",
555
- ];
556
- if (!patchable.some((key) => body[key] !== undefined)) {
557
- throw new HttpError(400, { detail: "Nothing to patch" });
558
- }
559
- const validationError = () => {
560
- const tz = body.fallback_time_zone;
561
- if (tz !== undefined && tz !== null) {
562
- if (typeof tz !== "string")
563
- return stringError("fallback_time_zone", tz);
564
- if (!isValidIanaTimezone(tz)) {
565
- return {
566
- type: "value_error",
567
- loc: ["body", "fallback_time_zone"],
568
- msg: `Value error, Invalid IANA time zone: ${tz}`,
569
- input: tz,
570
- ctx: { error: {} },
571
- };
572
- }
573
- }
574
- const birth = body.fallback_birth_date;
575
- if (birth !== undefined && birth !== null) {
576
- if (typeof birth !== "string")
577
- return stringError("fallback_birth_date", birth);
578
- if (!isValidDate(birth))
579
- return dateError("fallback_birth_date", birth);
580
- }
581
- const start = body.ingestion_start;
582
- if (start !== undefined && start !== null) {
583
- if (typeof start !== "string")
584
- return stringError("ingestion_start", start);
585
- if (!isValidDate(start))
586
- return dateError("ingestion_start", start);
587
- }
588
- const end = body.ingestion_end;
589
- if (end !== undefined && end !== null) {
590
- if (typeof end !== "string")
591
- return stringError("ingestion_end", end);
592
- if (!isValidDate(end))
593
- return dateError("ingestion_end", end);
594
- }
595
- const cid = body.client_user_id;
596
- if (cid !== undefined) {
597
- if (cid === null) {
598
- return {
599
- type: "value_error",
600
- loc: ["body"],
601
- msg: "Value error, client_user_id is not a field that can be reset to null.",
602
- input: body,
603
- ctx: { error: {} },
604
- };
605
- }
606
- if (typeof cid !== "string")
607
- return stringError("client_user_id", cid);
608
- }
609
- return undefined;
610
- };
611
- const error = validationError();
612
- if (error)
613
- throw new HttpError(422, { detail: [error] });
614
- if (body.client_user_id !== undefined) {
615
- const raw = body.client_user_id;
616
- const taken = state.byClientId.get(raw);
617
- if (taken && taken.user_id !== id)
618
- throw new HttpError(409, { detail: "Client user id already exists" });
619
- state.byClientId.delete(user.client_user_id);
620
- state.byClientId.insert(raw, { user_id: id });
621
- user.client_user_id = raw;
622
- }
623
- if (body.fallback_time_zone !== undefined) {
624
- const raw = body.fallback_time_zone;
625
- user.fallback_time_zone =
626
- typeof raw === "string" ? { id: raw, source_slug: "manual", updated_at: now } : null;
627
- }
628
- if (body.fallback_birth_date !== undefined) {
629
- const raw = body.fallback_birth_date;
630
- user.fallback_birth_date =
631
- typeof raw === "string" ? { value: raw, source_slug: "manual", updated_at: now } : null;
632
- }
633
- const startProvided = body.ingestion_start !== undefined;
634
- const endProvided = body.ingestion_end !== undefined;
635
- if (startProvided) {
636
- const raw = body.ingestion_start;
637
- user.ingestion_start = typeof raw === "string" ? raw : null;
638
- }
639
- if (endProvided) {
640
- const rawEnd = body.ingestion_end;
641
- user.ingestion_end = typeof rawEnd === "string" ? rawEnd : null;
642
- }
643
- state.users.update(id, user);
644
- return new Response(null, { status: 204 });
645
- },
646
- get_latest_user_info_user_v2_user__user_id__info_latest_get: async (context) => {
647
- const id = context.params.user_id ?? "";
648
- if (!isValidUuid(id)) {
649
- throw new HttpError(422, {
650
- detail: `Invalid format for parameter user_id: error unmarshaling '${id}' text as *uuid.UUID: invalid UUID length: ${id.length}`,
651
- });
652
- }
653
- if (!state.users.has(id) && !state.deletedUsers.has(id))
654
- notFound("User not found");
655
- const info = state.userInfo.get(id);
656
- if (!info)
657
- notFound("User demographics data not found");
658
- return jsonRes(200, info);
659
- },
660
- get_teams_users_v2_user_get: async (context) => {
661
- const offset = queryInt(context, "offset", 0);
662
- const limit = queryInt(context, "limit", 100);
663
- if (offset < 0 || limit < 0 || limit > 500) {
664
- throw new HttpError(500, "Internal Server Error", { "content-type": "text/plain" });
665
- }
666
- return jsonRes(200, listUsers(state, offset, limit));
667
- },
668
- });
669
- //# sourceMappingURL=users.js.map