@aranova/tracking-next 1.1.0 → 1.2.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.
@@ -1,12 +1,114 @@
1
1
  import * as z from 'zod/mini';
2
2
  import { A as ApiTransportConfig } from './request-Doq36Rt0.mjs';
3
3
 
4
+ /**
5
+ * BookingResponse
6
+ *
7
+ * A created booking. `manage_token` is present only on the create response.
8
+ */
9
+ declare const zBookingResponse: z.ZodMiniObject<{
10
+ all_day: z.ZodMiniBoolean<boolean>;
11
+ appointment_type: z.ZodMiniNullable<z.ZodMiniString<string>>;
12
+ calendar_key: z.ZodMiniString<string>;
13
+ created_at: z.iso.ZodMiniISODateTime;
14
+ customer: z.ZodMiniObject<{
15
+ email: z.ZodMiniEmail;
16
+ name: z.ZodMiniNullable<z.ZodMiniString<string>>;
17
+ phone: z.ZodMiniNullable<z.ZodMiniString<string>>;
18
+ sms_consent: z.ZodMiniDefault<z.ZodMiniBoolean<boolean>>;
19
+ }, z.core.$strict>;
20
+ end_at: z.iso.ZodMiniISODateTime;
21
+ google_event_id: z.ZodMiniNullable<z.ZodMiniString<string>>;
22
+ google_html_link: z.ZodMiniNullable<z.ZodMiniString<string>>;
23
+ google_sync_state: z.ZodMiniEnum<{
24
+ failed: "failed";
25
+ queued: "queued";
26
+ synced: "synced";
27
+ uncertain: "uncertain";
28
+ drifted: "drifted";
29
+ }>;
30
+ ical_uid: z.ZodMiniNullable<z.ZodMiniString<string>>;
31
+ id: z.ZodMiniString<string>;
32
+ manage_token: z.ZodMiniNullable<z.ZodMiniString<string>>;
33
+ meet_url: z.ZodMiniNullable<z.ZodMiniString<string>>;
34
+ organizer_email: z.ZodMiniNullable<z.ZodMiniString<string>>;
35
+ start_at: z.iso.ZodMiniISODateTime;
36
+ status: z.ZodMiniEnum<{
37
+ pending: "pending";
38
+ confirmed: "confirmed";
39
+ cancelled: "cancelled";
40
+ no_show: "no_show";
41
+ }>;
42
+ time_zone: z.ZodMiniString<string>;
43
+ title: z.ZodMiniString<string>;
44
+ }, z.core.$strict>;
45
+ /**
46
+ * BusyInterval
47
+ */
48
+ declare const zBusyInterval: z.ZodMiniObject<{
49
+ end_at: z.iso.ZodMiniISODateTime;
50
+ source: z.ZodMiniEnum<{
51
+ google: "google";
52
+ booking: "booking";
53
+ }>;
54
+ start_at: z.iso.ZodMiniISODateTime;
55
+ }, z.core.$strict>;
56
+ /**
57
+ * BusyResponse
58
+ *
59
+ * The calendar's busy truth over a window — times only, never contents.
60
+ */
61
+ declare const zBusyResponse: z.ZodMiniObject<{
62
+ busy: z.ZodMiniArray<z.ZodMiniObject<{
63
+ end_at: z.iso.ZodMiniISODateTime;
64
+ source: z.ZodMiniEnum<{
65
+ google: "google";
66
+ booking: "booking";
67
+ }>;
68
+ start_at: z.iso.ZodMiniISODateTime;
69
+ }, z.core.$strict>>;
70
+ calendar_key: z.ZodMiniString<string>;
71
+ generated_at: z.iso.ZodMiniISODateTime;
72
+ time_zone: z.ZodMiniString<string>;
73
+ window: z.ZodMiniObject<{
74
+ since: z.iso.ZodMiniISODateTime;
75
+ until: z.iso.ZodMiniISODateTime;
76
+ }, z.core.$strict>;
77
+ }, z.core.$strict>;
78
+ /**
79
+ * CalendarSummary
80
+ *
81
+ * A calendar as a client website sees it.
82
+ *
83
+ * The trailing fields are populated only for a secret key. A public key ships
84
+ * in a browser bundle, and the grantee's email plus our granted scopes are a
85
+ * third party's identity and our integration posture — not the client site's
86
+ * business.
87
+ */
88
+ declare const zCalendarSummary: z.ZodMiniObject<{
89
+ allow_overlaps: z.ZodMiniBoolean<boolean>;
90
+ calendar_key: z.ZodMiniString<string>;
91
+ connected_at: z.ZodMiniNullable<z.iso.ZodMiniISODateTime>;
92
+ google_account_email: z.ZodMiniNullable<z.ZodMiniString<string>>;
93
+ granted_scopes: z.ZodMiniNullable<z.ZodMiniArray<z.ZodMiniString<string>>>;
94
+ label: z.ZodMiniString<string>;
95
+ status: z.ZodMiniEnum<{
96
+ disabled: "disabled";
97
+ pending_invite: "pending_invite";
98
+ awaiting_calendar_selection: "awaiting_calendar_selection";
99
+ connected: "connected";
100
+ needs_reconnect: "needs_reconnect";
101
+ revoked: "revoked";
102
+ }>;
103
+ time_zone: z.ZodMiniString<string>;
104
+ }, z.core.$strict>;
105
+
4
106
  /**
5
107
  * Calendar wire schemas.
6
108
  *
7
109
  * The object shapes come from the backend's own spec — see
8
110
  * `../generated/zod.gen.ts` and `packages/tracking-core/openapi-ts.config.ts`.
9
- * This file adds only what JSON Schema cannot express: the end/duration XOR,
111
+ * This file adds only what JSON Schema cannot express: the start/date and end/duration XORs,
10
112
  * the IANA timezone check, and defaults Pydantic omits from the spec because
11
113
  * `default_factory` is not serialized (`attendees: []`, `reminders.overrides:
12
114
  * []`) — composed onto the generated base, never duplicating its shape.
@@ -19,15 +121,17 @@ declare const MAX_REMINDER_OVERRIDES = 5;
19
121
  declare const MAX_REMINDER_MINUTES = 40320;
20
122
  declare const MAX_BOOKING_MINUTES = 1440;
21
123
  declare const BOOKING_SOURCES: readonly ["website", "phone", "walk_in", "import", "operator"];
22
- declare const BOOKING_STATUSES: readonly ["pending", "confirmed", "cancelled", "no_show"];
23
- declare const GOOGLE_SYNC_STATES: readonly ["queued", "synced", "uncertain", "failed", "drifted"];
24
- declare const CALENDAR_SYNC_STATUSES: readonly ["pending_invite", "awaiting_calendar_selection", "connected", "needs_reconnect", "revoked", "disabled"];
25
- /** Every failure the calendar API can hand back, so a site can branch on it. */
26
- declare const CALENDAR_ERROR_CODES: readonly ["slot_unavailable", "calendar_not_connected", "calendar_disconnected", "booking_not_found", "outside_booking_window", "rate_limited", "google_error"];
124
+ declare const BOOKING_STATUSES: ("pending" | "confirmed" | "cancelled" | "no_show")[];
125
+ declare const GOOGLE_SYNC_STATES: ("failed" | "queued" | "synced" | "uncertain" | "drifted")[];
126
+ declare const CALENDAR_SYNC_STATUSES: ("disabled" | "pending_invite" | "awaiting_calendar_selection" | "connected" | "needs_reconnect" | "revoked")[];
127
+ /**
128
+ * Every failure code the calendar API can hand back, so a site can branch on it.
129
+ * `satisfies` pins each one to the backend's generated `ErrorCode` enum.
130
+ */
131
+ declare const CALENDAR_ERROR_CODES: readonly ["slot_unavailable", "calendar_not_connected", "calendar_disconnected", "booking_not_found", "booking_not_cancellable", "booking_not_reschedulable", "manage_token_invalid", "rate_limited", "google_error"];
27
132
  type CalendarErrorCode = (typeof CALENDAR_ERROR_CODES)[number];
28
133
  type BookingStatus = (typeof BOOKING_STATUSES)[number];
29
134
  type GoogleSyncState = (typeof GOOGLE_SYNC_STATES)[number];
30
- type CalendarSyncStatus = (typeof CALENDAR_SYNC_STATUSES)[number];
31
135
  type JsonScalar = string | number | boolean | null;
32
136
  declare const bookingAttendeeSchema: z.ZodMiniObject<{
33
137
  display_name: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniString<string>>>;
@@ -123,12 +227,13 @@ declare const bookingCreateSchema: z.ZodMiniObject<{
123
227
  phone: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniString<string>>>;
124
228
  sms_consent: z.ZodMiniDefault<z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>>;
125
229
  }, z.core.$strict>;
230
+ date: z.ZodMiniOptional<z.ZodMiniNullable<z.iso.ZodMiniISODate>>;
126
231
  description: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniString<string>>>;
127
232
  duration_minutes: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniInt>>;
128
233
  end_at: z.ZodMiniOptional<z.ZodMiniNullable<z.iso.ZodMiniISODateTime>>;
129
234
  idempotency_key: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniString<string>>>;
130
235
  send_invites: z.ZodMiniDefault<z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>>;
131
- start_at: z.iso.ZodMiniISODateTime;
236
+ start_at: z.ZodMiniOptional<z.ZodMiniNullable<z.iso.ZodMiniISODateTime>>;
132
237
  title: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniString<string>>>;
133
238
  time_zone: z.ZodMiniString<string>;
134
239
  location: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniObject<{
@@ -205,48 +310,13 @@ type BookingCustomer = z.input<typeof bookingCustomerSchema>;
205
310
  type BookingMetadata<TCustom extends Record<string, JsonScalar> = Record<string, JsonScalar>> = Omit<z.input<typeof bookingMetadataSchema>, "custom"> & {
206
311
  custom?: TCustom | null;
207
312
  };
208
- interface CalendarSummary {
209
- calendar_key: string;
210
- label: string;
211
- time_zone: string;
212
- status: CalendarSyncStatus;
213
- /** Secret-key only. A public key gets `null`: whose Google account is behind
214
- * a calendar is a third party's identity, not the client site's business. */
215
- google_account_email?: string | null;
216
- granted_scopes?: string[] | null;
217
- connected_at?: string | null;
218
- }
219
- interface BusyInterval {
220
- start_at: string;
221
- end_at: string;
222
- source: "google" | "booking";
223
- }
224
- interface BusyResponse {
225
- calendar_key: string;
226
- time_zone: string;
227
- window: {
228
- since: string;
229
- until: string;
230
- };
231
- busy: BusyInterval[];
232
- generated_at: string;
233
- }
234
- interface Booking {
235
- id: string;
236
- calendar_key: string;
237
- status: BookingStatus;
238
- google_sync_state: GoogleSyncState;
239
- start_at: string;
240
- end_at: string;
241
- time_zone: string;
242
- appointment_type: string | null;
243
- title: string;
244
- customer: BookingCustomer;
245
- google_html_link: string | null;
246
- meet_url: string | null;
247
- /** Returned only on create — the capability credential for manage links. */
248
- manage_token?: string | null;
249
- }
313
+ /** A calendar as the site sees it. `google_account_email` and friends are null for a public key. */
314
+ type CalendarSummary = z.output<typeof zCalendarSummary>;
315
+ type CalendarSyncStatus = CalendarSummary["status"];
316
+ type BusyInterval = z.output<typeof zBusyInterval>;
317
+ type BusyResponse = z.output<typeof zBusyResponse>;
318
+ /** A booking as the API returns it; field docs live on the backend's `BookingResponse`. */
319
+ type Booking = z.output<typeof zBookingResponse>;
250
320
 
251
321
  type CalendarTransportConfig = ApiTransportConfig;
252
322
 
@@ -1,12 +1,114 @@
1
1
  import * as z from 'zod/mini';
2
2
  import { A as ApiTransportConfig } from './request-Doq36Rt0.js';
3
3
 
4
+ /**
5
+ * BookingResponse
6
+ *
7
+ * A created booking. `manage_token` is present only on the create response.
8
+ */
9
+ declare const zBookingResponse: z.ZodMiniObject<{
10
+ all_day: z.ZodMiniBoolean<boolean>;
11
+ appointment_type: z.ZodMiniNullable<z.ZodMiniString<string>>;
12
+ calendar_key: z.ZodMiniString<string>;
13
+ created_at: z.iso.ZodMiniISODateTime;
14
+ customer: z.ZodMiniObject<{
15
+ email: z.ZodMiniEmail;
16
+ name: z.ZodMiniNullable<z.ZodMiniString<string>>;
17
+ phone: z.ZodMiniNullable<z.ZodMiniString<string>>;
18
+ sms_consent: z.ZodMiniDefault<z.ZodMiniBoolean<boolean>>;
19
+ }, z.core.$strict>;
20
+ end_at: z.iso.ZodMiniISODateTime;
21
+ google_event_id: z.ZodMiniNullable<z.ZodMiniString<string>>;
22
+ google_html_link: z.ZodMiniNullable<z.ZodMiniString<string>>;
23
+ google_sync_state: z.ZodMiniEnum<{
24
+ failed: "failed";
25
+ queued: "queued";
26
+ synced: "synced";
27
+ uncertain: "uncertain";
28
+ drifted: "drifted";
29
+ }>;
30
+ ical_uid: z.ZodMiniNullable<z.ZodMiniString<string>>;
31
+ id: z.ZodMiniString<string>;
32
+ manage_token: z.ZodMiniNullable<z.ZodMiniString<string>>;
33
+ meet_url: z.ZodMiniNullable<z.ZodMiniString<string>>;
34
+ organizer_email: z.ZodMiniNullable<z.ZodMiniString<string>>;
35
+ start_at: z.iso.ZodMiniISODateTime;
36
+ status: z.ZodMiniEnum<{
37
+ pending: "pending";
38
+ confirmed: "confirmed";
39
+ cancelled: "cancelled";
40
+ no_show: "no_show";
41
+ }>;
42
+ time_zone: z.ZodMiniString<string>;
43
+ title: z.ZodMiniString<string>;
44
+ }, z.core.$strict>;
45
+ /**
46
+ * BusyInterval
47
+ */
48
+ declare const zBusyInterval: z.ZodMiniObject<{
49
+ end_at: z.iso.ZodMiniISODateTime;
50
+ source: z.ZodMiniEnum<{
51
+ google: "google";
52
+ booking: "booking";
53
+ }>;
54
+ start_at: z.iso.ZodMiniISODateTime;
55
+ }, z.core.$strict>;
56
+ /**
57
+ * BusyResponse
58
+ *
59
+ * The calendar's busy truth over a window — times only, never contents.
60
+ */
61
+ declare const zBusyResponse: z.ZodMiniObject<{
62
+ busy: z.ZodMiniArray<z.ZodMiniObject<{
63
+ end_at: z.iso.ZodMiniISODateTime;
64
+ source: z.ZodMiniEnum<{
65
+ google: "google";
66
+ booking: "booking";
67
+ }>;
68
+ start_at: z.iso.ZodMiniISODateTime;
69
+ }, z.core.$strict>>;
70
+ calendar_key: z.ZodMiniString<string>;
71
+ generated_at: z.iso.ZodMiniISODateTime;
72
+ time_zone: z.ZodMiniString<string>;
73
+ window: z.ZodMiniObject<{
74
+ since: z.iso.ZodMiniISODateTime;
75
+ until: z.iso.ZodMiniISODateTime;
76
+ }, z.core.$strict>;
77
+ }, z.core.$strict>;
78
+ /**
79
+ * CalendarSummary
80
+ *
81
+ * A calendar as a client website sees it.
82
+ *
83
+ * The trailing fields are populated only for a secret key. A public key ships
84
+ * in a browser bundle, and the grantee's email plus our granted scopes are a
85
+ * third party's identity and our integration posture — not the client site's
86
+ * business.
87
+ */
88
+ declare const zCalendarSummary: z.ZodMiniObject<{
89
+ allow_overlaps: z.ZodMiniBoolean<boolean>;
90
+ calendar_key: z.ZodMiniString<string>;
91
+ connected_at: z.ZodMiniNullable<z.iso.ZodMiniISODateTime>;
92
+ google_account_email: z.ZodMiniNullable<z.ZodMiniString<string>>;
93
+ granted_scopes: z.ZodMiniNullable<z.ZodMiniArray<z.ZodMiniString<string>>>;
94
+ label: z.ZodMiniString<string>;
95
+ status: z.ZodMiniEnum<{
96
+ disabled: "disabled";
97
+ pending_invite: "pending_invite";
98
+ awaiting_calendar_selection: "awaiting_calendar_selection";
99
+ connected: "connected";
100
+ needs_reconnect: "needs_reconnect";
101
+ revoked: "revoked";
102
+ }>;
103
+ time_zone: z.ZodMiniString<string>;
104
+ }, z.core.$strict>;
105
+
4
106
  /**
5
107
  * Calendar wire schemas.
6
108
  *
7
109
  * The object shapes come from the backend's own spec — see
8
110
  * `../generated/zod.gen.ts` and `packages/tracking-core/openapi-ts.config.ts`.
9
- * This file adds only what JSON Schema cannot express: the end/duration XOR,
111
+ * This file adds only what JSON Schema cannot express: the start/date and end/duration XORs,
10
112
  * the IANA timezone check, and defaults Pydantic omits from the spec because
11
113
  * `default_factory` is not serialized (`attendees: []`, `reminders.overrides:
12
114
  * []`) — composed onto the generated base, never duplicating its shape.
@@ -19,15 +121,17 @@ declare const MAX_REMINDER_OVERRIDES = 5;
19
121
  declare const MAX_REMINDER_MINUTES = 40320;
20
122
  declare const MAX_BOOKING_MINUTES = 1440;
21
123
  declare const BOOKING_SOURCES: readonly ["website", "phone", "walk_in", "import", "operator"];
22
- declare const BOOKING_STATUSES: readonly ["pending", "confirmed", "cancelled", "no_show"];
23
- declare const GOOGLE_SYNC_STATES: readonly ["queued", "synced", "uncertain", "failed", "drifted"];
24
- declare const CALENDAR_SYNC_STATUSES: readonly ["pending_invite", "awaiting_calendar_selection", "connected", "needs_reconnect", "revoked", "disabled"];
25
- /** Every failure the calendar API can hand back, so a site can branch on it. */
26
- declare const CALENDAR_ERROR_CODES: readonly ["slot_unavailable", "calendar_not_connected", "calendar_disconnected", "booking_not_found", "outside_booking_window", "rate_limited", "google_error"];
124
+ declare const BOOKING_STATUSES: ("pending" | "confirmed" | "cancelled" | "no_show")[];
125
+ declare const GOOGLE_SYNC_STATES: ("failed" | "queued" | "synced" | "uncertain" | "drifted")[];
126
+ declare const CALENDAR_SYNC_STATUSES: ("disabled" | "pending_invite" | "awaiting_calendar_selection" | "connected" | "needs_reconnect" | "revoked")[];
127
+ /**
128
+ * Every failure code the calendar API can hand back, so a site can branch on it.
129
+ * `satisfies` pins each one to the backend's generated `ErrorCode` enum.
130
+ */
131
+ declare const CALENDAR_ERROR_CODES: readonly ["slot_unavailable", "calendar_not_connected", "calendar_disconnected", "booking_not_found", "booking_not_cancellable", "booking_not_reschedulable", "manage_token_invalid", "rate_limited", "google_error"];
27
132
  type CalendarErrorCode = (typeof CALENDAR_ERROR_CODES)[number];
28
133
  type BookingStatus = (typeof BOOKING_STATUSES)[number];
29
134
  type GoogleSyncState = (typeof GOOGLE_SYNC_STATES)[number];
30
- type CalendarSyncStatus = (typeof CALENDAR_SYNC_STATUSES)[number];
31
135
  type JsonScalar = string | number | boolean | null;
32
136
  declare const bookingAttendeeSchema: z.ZodMiniObject<{
33
137
  display_name: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniString<string>>>;
@@ -123,12 +227,13 @@ declare const bookingCreateSchema: z.ZodMiniObject<{
123
227
  phone: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniString<string>>>;
124
228
  sms_consent: z.ZodMiniDefault<z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>>;
125
229
  }, z.core.$strict>;
230
+ date: z.ZodMiniOptional<z.ZodMiniNullable<z.iso.ZodMiniISODate>>;
126
231
  description: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniString<string>>>;
127
232
  duration_minutes: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniInt>>;
128
233
  end_at: z.ZodMiniOptional<z.ZodMiniNullable<z.iso.ZodMiniISODateTime>>;
129
234
  idempotency_key: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniString<string>>>;
130
235
  send_invites: z.ZodMiniDefault<z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>>;
131
- start_at: z.iso.ZodMiniISODateTime;
236
+ start_at: z.ZodMiniOptional<z.ZodMiniNullable<z.iso.ZodMiniISODateTime>>;
132
237
  title: z.ZodMiniOptional<z.ZodMiniNullable<z.ZodMiniString<string>>>;
133
238
  time_zone: z.ZodMiniString<string>;
134
239
  location: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniObject<{
@@ -205,48 +310,13 @@ type BookingCustomer = z.input<typeof bookingCustomerSchema>;
205
310
  type BookingMetadata<TCustom extends Record<string, JsonScalar> = Record<string, JsonScalar>> = Omit<z.input<typeof bookingMetadataSchema>, "custom"> & {
206
311
  custom?: TCustom | null;
207
312
  };
208
- interface CalendarSummary {
209
- calendar_key: string;
210
- label: string;
211
- time_zone: string;
212
- status: CalendarSyncStatus;
213
- /** Secret-key only. A public key gets `null`: whose Google account is behind
214
- * a calendar is a third party's identity, not the client site's business. */
215
- google_account_email?: string | null;
216
- granted_scopes?: string[] | null;
217
- connected_at?: string | null;
218
- }
219
- interface BusyInterval {
220
- start_at: string;
221
- end_at: string;
222
- source: "google" | "booking";
223
- }
224
- interface BusyResponse {
225
- calendar_key: string;
226
- time_zone: string;
227
- window: {
228
- since: string;
229
- until: string;
230
- };
231
- busy: BusyInterval[];
232
- generated_at: string;
233
- }
234
- interface Booking {
235
- id: string;
236
- calendar_key: string;
237
- status: BookingStatus;
238
- google_sync_state: GoogleSyncState;
239
- start_at: string;
240
- end_at: string;
241
- time_zone: string;
242
- appointment_type: string | null;
243
- title: string;
244
- customer: BookingCustomer;
245
- google_html_link: string | null;
246
- meet_url: string | null;
247
- /** Returned only on create — the capability credential for manage links. */
248
- manage_token?: string | null;
249
- }
313
+ /** A calendar as the site sees it. `google_account_email` and friends are null for a public key. */
314
+ type CalendarSummary = z.output<typeof zCalendarSummary>;
315
+ type CalendarSyncStatus = CalendarSummary["status"];
316
+ type BusyInterval = z.output<typeof zBusyInterval>;
317
+ type BusyResponse = z.output<typeof zBusyResponse>;
318
+ /** A booking as the API returns it; field docs live on the backend's `BookingResponse`. */
319
+ type Booking = z.output<typeof zBookingResponse>;
250
320
 
251
321
  type CalendarTransportConfig = ApiTransportConfig;
252
322
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aranova/tracking-next",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "private": false,
5
5
  "type": "commonjs",
6
6
  "description": "Next.js tracking utilities for Aranova client sites",