@go-avro/avro-js 0.0.44 → 0.0.46

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.
@@ -517,6 +517,11 @@ declare module '../client/QueryClient' {
517
517
  }>>;
518
518
  }
519
519
  }
520
+ export type ListQueryMatch = 'match' | 'nomatch' | 'unknown';
521
+ export declare function matchesEventsListQuery(queryKey: readonly unknown[], item: any): ListQueryMatch;
522
+ export declare function matchesBillsListQuery(queryKey: readonly unknown[], item: any): ListQueryMatch;
523
+ export declare function matchesJobsListQuery(queryKey: readonly unknown[], item: any): ListQueryMatch;
524
+ export declare function matchesRoutesListQuery(queryKey: readonly unknown[], _item: any): ListQueryMatch;
520
525
  export declare class AvroQueryClient {
521
526
  protected config: Required<AvroQueryClientConfig>;
522
527
  readonly socket: Socket;
@@ -618,23 +623,13 @@ export declare class AvroQueryClient {
618
623
  getAuthState(): AuthState;
619
624
  getAuthStateAsync(): Promise<AuthState>;
620
625
  getQueryClient(): QueryClient;
621
- /**
622
- * Fetch an entity from the API, optionally construct it, and surgically
623
- * update all matching React-Query caches (individual + list + infinite).
624
- *
625
- * Shared by socket handlers and mutation `onSuccess` callbacks so the
626
- * sender gets an immediate cache sync and everyone else gets the socket
627
- * update — both use the identical code path.
628
- *
629
- * @returns The fetched (and optionally constructed) item, or `undefined`
630
- * for deletes / entities without a fetchPath.
631
- */
632
626
  _syncEntity(queryClient: QueryClient, params: {
633
627
  action: 'create' | 'update' | 'delete';
634
628
  entityKey: string;
635
629
  id: string;
636
630
  fetchPath?: string;
637
631
  construct?: (raw: any) => any;
632
+ matchesQuery?: (queryKey: readonly unknown[], item: any) => ListQueryMatch;
638
633
  }): Promise<any>;
639
634
  useLogout(): ReturnType<typeof useMutation<void, StandardError, CancelToken | undefined>>;
640
635
  fetchJobs(body?: {
@@ -7,6 +7,91 @@ import { StandardError } from '../types/error';
7
7
  function isBulkEvent(c) {
8
8
  return 'invalidateKeys' in c;
9
9
  }
10
+ export function matchesEventsListQuery(queryKey, item) {
11
+ if (queryKey.length < 11)
12
+ return 'match';
13
+ if (!item)
14
+ return 'match';
15
+ const knownIds = queryKey[3];
16
+ const unknownIds = queryKey[4];
17
+ const query = queryKey[5];
18
+ const includeUnbilled = queryKey[6];
19
+ const includeBilled = queryKey[7];
20
+ const includePaid = queryKey[8];
21
+ const filterJobId = queryKey[9];
22
+ if (knownIds && knownIds.length > 0 && !knownIds.includes(item.id))
23
+ return 'nomatch';
24
+ if (unknownIds && unknownIds.length > 0 && unknownIds.includes(item.id))
25
+ return 'nomatch';
26
+ if (filterJobId && item.job_id !== filterJobId)
27
+ return 'nomatch';
28
+ const status = item.status;
29
+ if (status !== undefined) {
30
+ const isPaid = status === 'PAID' || status === 'PREPAID' || status === 'EXTERNALLY_PAID';
31
+ const isBilled = status === 'BILLED' || status === 'EXTERNALLY_BILLED';
32
+ const isUnbilled = !isPaid && !isBilled;
33
+ if (includePaid === false && isPaid)
34
+ return 'nomatch';
35
+ if (includeBilled === false && isBilled)
36
+ return 'nomatch';
37
+ if (includeUnbilled === false && isUnbilled)
38
+ return 'nomatch';
39
+ }
40
+ if (query && query.length > 0)
41
+ return 'unknown';
42
+ return 'match';
43
+ }
44
+ export function matchesBillsListQuery(queryKey, item) {
45
+ if (queryKey.length < 6)
46
+ return 'match';
47
+ if (!item)
48
+ return 'match';
49
+ const query = queryKey[2];
50
+ const knownIds = queryKey[3];
51
+ const unknownIds = queryKey[4];
52
+ const paidFilter = queryKey[5];
53
+ if (knownIds && knownIds.length > 0 && !knownIds.includes(item.id))
54
+ return 'nomatch';
55
+ if (unknownIds && unknownIds.length > 0 && unknownIds.includes(item.id))
56
+ return 'nomatch';
57
+ const status = item.status;
58
+ if (paidFilter !== undefined && status !== undefined) {
59
+ const isPaid = status === 'PAID' || status === 'MANUALLY_PAID';
60
+ if (paidFilter === true && !isPaid)
61
+ return 'nomatch';
62
+ if (paidFilter === false && isPaid)
63
+ return 'nomatch';
64
+ }
65
+ if (query && query.length > 0)
66
+ return 'unknown';
67
+ return 'match';
68
+ }
69
+ export function matchesJobsListQuery(queryKey, item) {
70
+ if (queryKey[0] !== 'infinite')
71
+ return 'match';
72
+ if (queryKey.length < 6)
73
+ return 'match';
74
+ if (!item)
75
+ return 'match';
76
+ const query = queryKey[4];
77
+ const routeId = queryKey[5];
78
+ if (routeId && routeId.length > 0) {
79
+ const routes = item.routes ?? [];
80
+ if (!routes.some((r) => r?.route_id === routeId))
81
+ return 'nomatch';
82
+ }
83
+ if (query && query.length > 0)
84
+ return 'unknown';
85
+ return 'match';
86
+ }
87
+ export function matchesRoutesListQuery(queryKey, _item) {
88
+ if (queryKey.length < 5)
89
+ return 'match';
90
+ const query = queryKey[3];
91
+ if (query && query.length > 0)
92
+ return 'unknown';
93
+ return 'match';
94
+ }
10
95
  /**
11
96
  * Maps socket event names to cache-update strategies.
12
97
  *
@@ -38,12 +123,14 @@ const SOCKET_EVENT_CONFIG = {
38
123
  action: 'create',
39
124
  fetchPath: (id) => `/job/${id}`,
40
125
  construct: (d) => new Job(d),
126
+ matchesQuery: matchesJobsListQuery,
41
127
  },
42
128
  update_job: {
43
129
  entityKey: 'jobs',
44
130
  action: 'update',
45
131
  fetchPath: (id) => `/job/${id}`,
46
132
  construct: (d) => new Job(d),
133
+ matchesQuery: matchesJobsListQuery,
47
134
  },
48
135
  delete_job: { entityKey: 'jobs', action: 'delete', fetchPath: null },
49
136
  update_jobs: { invalidateKeys: [['jobs'], ['infinite', 'jobs']] },
@@ -54,12 +141,14 @@ const SOCKET_EVENT_CONFIG = {
54
141
  action: 'create',
55
142
  fetchPath: (id) => `/route/${id}`,
56
143
  construct: (d) => new Route(d),
144
+ matchesQuery: matchesRoutesListQuery,
57
145
  },
58
146
  update_route: {
59
147
  entityKey: 'routes',
60
148
  action: 'update',
61
149
  fetchPath: (id) => `/route/${id}`,
62
150
  construct: (d) => new Route(d),
151
+ matchesQuery: matchesRoutesListQuery,
63
152
  },
64
153
  delete_route: { entityKey: 'routes', action: 'delete', fetchPath: null },
65
154
  // ── Events (also refetch parent job — overdueness, last_event, etc.) ──
@@ -68,12 +157,14 @@ const SOCKET_EVENT_CONFIG = {
68
157
  action: 'create',
69
158
  fetchPath: (id) => `/event/${id}`,
70
159
  construct: (d) => new _Event(d),
160
+ matchesQuery: matchesEventsListQuery,
71
161
  relatedRefetch: [
72
162
  {
73
163
  entityKey: 'jobs',
74
164
  idField: 'job_id',
75
165
  fetchPath: (id) => `/job/${id}`,
76
166
  construct: (d) => new Job(d),
167
+ matchesQuery: matchesJobsListQuery,
77
168
  },
78
169
  ],
79
170
  },
@@ -82,12 +173,14 @@ const SOCKET_EVENT_CONFIG = {
82
173
  action: 'update',
83
174
  fetchPath: (id) => `/event/${id}`,
84
175
  construct: (d) => new _Event(d),
176
+ matchesQuery: matchesEventsListQuery,
85
177
  relatedRefetch: [
86
178
  {
87
179
  entityKey: 'jobs',
88
180
  idField: 'job_id',
89
181
  fetchPath: (id) => `/job/${id}`,
90
182
  construct: (d) => new Job(d),
183
+ matchesQuery: matchesJobsListQuery,
91
184
  },
92
185
  ],
93
186
  },
@@ -101,6 +194,7 @@ const SOCKET_EVENT_CONFIG = {
101
194
  idField: 'job_id',
102
195
  fetchPath: (id) => `/job/${id}`,
103
196
  construct: (d) => new Job(d),
197
+ matchesQuery: matchesJobsListQuery,
104
198
  },
105
199
  ],
106
200
  },
@@ -115,6 +209,7 @@ const SOCKET_EVENT_CONFIG = {
115
209
  entityKey: 'bills',
116
210
  action: 'create',
117
211
  fetchPath: (id) => `/bill/${id}`,
212
+ matchesQuery: matchesBillsListQuery,
118
213
  },
119
214
  delete_bill: { entityKey: 'bills', action: 'delete', fetchPath: null },
120
215
  update_bills: { invalidateKeys: [['bills']] },
@@ -348,10 +443,10 @@ export class AvroQueryClient {
348
443
  id,
349
444
  fetchPath: fetchPath ? fetchPath(id) : undefined,
350
445
  construct: config.construct,
446
+ matchesQuery: config.matchesQuery,
351
447
  });
352
448
  // Invalidate any additional keys (e.g. companies → /company/list)
353
449
  alsoInvalidate?.forEach((k) => queryClient.invalidateQueries({ queryKey: k }));
354
- // Refetch & patch related entities (e.g. event → parent job)
355
450
  if (relatedRefetch) {
356
451
  for (const related of relatedRefetch) {
357
452
  const relatedId = data?.[related.idField] ?? fetchedItem?.[related.idField];
@@ -363,6 +458,7 @@ export class AvroQueryClient {
363
458
  id: relatedId,
364
459
  fetchPath: related.fetchPath(relatedId),
365
460
  construct: related.construct,
461
+ matchesQuery: related.matchesQuery,
366
462
  });
367
463
  }
368
464
  }
@@ -615,22 +711,10 @@ export class AvroQueryClient {
615
711
  getQueryClient() {
616
712
  return useQueryClient();
617
713
  }
618
- /**
619
- * Fetch an entity from the API, optionally construct it, and surgically
620
- * update all matching React-Query caches (individual + list + infinite).
621
- *
622
- * Shared by socket handlers and mutation `onSuccess` callbacks so the
623
- * sender gets an immediate cache sync and everyone else gets the socket
624
- * update — both use the identical code path.
625
- *
626
- * @returns The fetched (and optionally constructed) item, or `undefined`
627
- * for deletes / entities without a fetchPath.
628
- */
629
714
  async _syncEntity(queryClient, params) {
630
- const { action, entityKey, id, fetchPath, construct } = params;
715
+ const { action, entityKey, id, fetchPath, construct, matchesQuery } = params;
631
716
  const predicate = (q) => matchesEntityKey(q, entityKey);
632
717
  const invalidate = () => queryClient.invalidateQueries({ predicate });
633
- // ─── DELETE ─────────────────────────────────────────
634
718
  if (action === 'delete') {
635
719
  queryClient.removeQueries({ queryKey: [entityKey, id], exact: true });
636
720
  queryClient.setQueriesData({ predicate }, (old) => {
@@ -649,7 +733,6 @@ export class AvroQueryClient {
649
733
  });
650
734
  return undefined;
651
735
  }
652
- // ─── CREATE / UPDATE ────────────────────────────────
653
736
  if (!fetchPath) {
654
737
  invalidate();
655
738
  return undefined;
@@ -662,42 +745,60 @@ export class AvroQueryClient {
662
745
  });
663
746
  const item = construct ? construct(raw) : raw;
664
747
  queryClient.setQueryData([entityKey, id], item);
665
- if (action === 'create') {
666
- queryClient.setQueriesData({ predicate }, (old) => {
667
- if (!old)
668
- return old;
669
- if (old.pages && Array.isArray(old.pages)) {
670
- if (old.pages.some((p) => p.some((x) => x?.id === id)))
748
+ const matchingQueries = queryClient.getQueryCache().findAll({ predicate });
749
+ for (const query of matchingQueries) {
750
+ const queryKey = query.queryKey;
751
+ if (queryKey.length === 2 && queryKey[0] === entityKey)
752
+ continue;
753
+ const verdict = matchesQuery
754
+ ? matchesQuery(queryKey, item)
755
+ : 'match';
756
+ if (verdict === 'unknown') {
757
+ queryClient.invalidateQueries({ queryKey, exact: true });
758
+ continue;
759
+ }
760
+ if (action === 'create') {
761
+ if (verdict === 'nomatch')
762
+ continue;
763
+ queryClient.setQueryData(queryKey, (old) => {
764
+ if (!old)
671
765
  return old;
672
- return {
673
- ...old,
674
- pages: [[item, ...(old.pages[0] || [])], ...old.pages.slice(1)],
675
- };
676
- }
677
- if (Array.isArray(old)) {
678
- if (old.some((x) => x?.id === id))
766
+ if (old.pages && Array.isArray(old.pages)) {
767
+ if (old.pages.some((p) => p.some((x) => x?.id === id)))
768
+ return old;
769
+ return {
770
+ ...old,
771
+ pages: [[item, ...(old.pages[0] || [])], ...old.pages.slice(1)],
772
+ };
773
+ }
774
+ if (Array.isArray(old)) {
775
+ if (old.some((x) => x?.id === id))
776
+ return old;
777
+ return [...old, item];
778
+ }
779
+ return old;
780
+ });
781
+ }
782
+ else {
783
+ queryClient.setQueryData(queryKey, (old) => {
784
+ if (!old)
679
785
  return old;
680
- return [...old, item];
681
- }
682
- return old;
683
- });
684
- }
685
- else {
686
- // UPDATE — replace in every active list / infinite-query cache
687
- queryClient.setQueriesData({ predicate }, (old) => {
688
- if (!old)
786
+ if (old.pages && Array.isArray(old.pages)) {
787
+ return {
788
+ ...old,
789
+ pages: old.pages.map((page) => verdict === 'match'
790
+ ? page.map((x) => (x?.id === id ? item : x))
791
+ : page.filter((x) => x?.id !== id)),
792
+ };
793
+ }
794
+ if (Array.isArray(old)) {
795
+ return verdict === 'match'
796
+ ? old.map((x) => (x?.id === id ? item : x))
797
+ : old.filter((x) => x?.id !== id);
798
+ }
689
799
  return old;
690
- if (old.pages && Array.isArray(old.pages)) {
691
- return {
692
- ...old,
693
- pages: old.pages.map((page) => page.map((x) => (x?.id === id ? item : x))),
694
- };
695
- }
696
- if (Array.isArray(old)) {
697
- return old.map((x) => (x?.id === id ? item : x));
698
- }
699
- return old;
700
- });
800
+ });
801
+ }
701
802
  }
702
803
  return item;
703
804
  }
@@ -1,10 +1,9 @@
1
1
  import { useInfiniteQuery, useQuery, useMutation } from '@tanstack/react-query';
2
- import { AvroQueryClient } from '../../client/QueryClient';
2
+ import { AvroQueryClient, matchesEventsListQuery } from '../../client/QueryClient';
3
3
  import { _Event, Job, LineItemStatus } from '../../types/api';
4
- /** Predicate that matches all 'jobs' queries (list and individual, but NOT 'infinite'). */
5
4
  const isJobsQuery = (q) => q.queryKey[0] === 'jobs';
6
- /** Predicate that matches all 'events' queries (list and individual). */
7
5
  const isEventsQuery = (q) => q.queryKey[0] === 'events';
6
+ const isEventsQueryFor = (item) => (q) => q.queryKey[0] === 'events' && matchesEventsListQuery(q.queryKey, item) === 'match';
8
7
  AvroQueryClient.prototype.useGetEvents = function (body) {
9
8
  const queryClient = this.getQueryClient();
10
9
  const result = useInfiniteQuery({
@@ -102,8 +101,7 @@ AvroQueryClient.prototype.useCreateEvent = function () {
102
101
  return old;
103
102
  });
104
103
  }
105
- // Add optimistic event to all active events queries
106
- queryClient.setQueriesData({ predicate: isEventsQuery, type: 'active' }, (oldData) => {
104
+ queryClient.setQueriesData({ predicate: isEventsQueryFor(optimisticEvent), type: 'active' }, (oldData) => {
107
105
  if (!oldData)
108
106
  return oldData;
109
107
  if (oldData.pages) {
@@ -35,6 +35,21 @@ export declare class Job {
35
35
  getOverdueLabel: () => string;
36
36
  getStatus(): "PENDING_CUSTOMER" | "PENDING_COMPANY" | "ACTIVE" | "ARCHIVED" | "DRAFT" | "PENDING_PAYMENT" | "PENDING_ACTIVATION";
37
37
  getStatusLabel(): "Active" | "Draft" | "Archived" | "Pending Activation" | "Customer Approval" | "Company Approval" | "Awaiting Payment";
38
+ /**
39
+ * Returns the sum of `service` (in seconds) for the tasks attached to a
40
+ * given routeJob. Use this to compute predicted completion time:
41
+ * `routeJob.getPredictedArrival() + job.getServiceDuration(routeJob)`.
42
+ */
43
+ getServiceDuration: (routeJob: RouteJob) => number;
44
+ /**
45
+ * Returns the most relevant event for the job in its current state:
46
+ * the active `current_event` if one exists, otherwise the
47
+ * `last_completed_event`. Falls back to `null`.
48
+ *
49
+ * Most callers historically used `last_completed_event ?? current_event`
50
+ * which inverted the precedence — prefer the live event over a stale one.
51
+ */
52
+ getRouteEvent: () => _Event | null;
38
53
  portionDone: (route: Route) => number;
39
54
  isDone: (route: Route) => boolean;
40
55
  }
@@ -21,6 +21,27 @@ export class Job {
21
21
  }, activeTasks[0]);
22
22
  return mostOverdueTask.getOverdueLabel?.() ?? 'N/A';
23
23
  };
24
+ /**
25
+ * Returns the sum of `service` (in seconds) for the tasks attached to a
26
+ * given routeJob. Use this to compute predicted completion time:
27
+ * `routeJob.getPredictedArrival() + job.getServiceDuration(routeJob)`.
28
+ */
29
+ this.getServiceDuration = (routeJob) => {
30
+ return routeJob.tasks
31
+ .map((tid) => this.tasks.find((t) => t.id === tid)?.service ?? 0)
32
+ .reduce((a, b) => a + b, 0);
33
+ };
34
+ /**
35
+ * Returns the most relevant event for the job in its current state:
36
+ * the active `current_event` if one exists, otherwise the
37
+ * `last_completed_event`. Falls back to `null`.
38
+ *
39
+ * Most callers historically used `last_completed_event ?? current_event`
40
+ * which inverted the precedence — prefer the live event over a stale one.
41
+ */
42
+ this.getRouteEvent = () => {
43
+ return this.current_event ?? this.last_completed_event ?? null;
44
+ };
24
45
  this.portionDone = (route) => {
25
46
  if (!this.tasks || this.tasks.length === 0) {
26
47
  return 0;
@@ -1,4 +1,5 @@
1
1
  import { RouteJob } from '../../types/api/RouteJob';
2
+ import type { Job } from '../../types/api/Job';
2
3
  export declare const FrequencyType: {
3
4
  readonly ONCE: "ONCE";
4
5
  readonly DAILY: "DAILY";
@@ -33,4 +34,16 @@ export declare class Route {
33
34
  constructor(init?: Partial<Route>);
34
35
  getNextOccurrences: (count?: number) => (Date | null)[];
35
36
  getNextOccurrence: (after?: Date) => Date | null;
37
+ /**
38
+ * Computes how far ahead/behind schedule the route is, in seconds, based on
39
+ * stops that have already been completed. Positive = behind schedule,
40
+ * negative = ahead of schedule.
41
+ *
42
+ * The offset is taken from the most recently completed stop (largest
43
+ * `time_ended`), not the last stop in route order. This is what consumers
44
+ * want: "given the latest completed work, how off-schedule are we?".
45
+ *
46
+ * Returns `null` if no stop in this route has a usable completion event.
47
+ */
48
+ getScheduleOffset: (jobs: Job[]) => number | null;
36
49
  }
@@ -43,6 +43,38 @@ export class Route {
43
43
  }
44
44
  return next_occurrence;
45
45
  };
46
+ /**
47
+ * Computes how far ahead/behind schedule the route is, in seconds, based on
48
+ * stops that have already been completed. Positive = behind schedule,
49
+ * negative = ahead of schedule.
50
+ *
51
+ * The offset is taken from the most recently completed stop (largest
52
+ * `time_ended`), not the last stop in route order. This is what consumers
53
+ * want: "given the latest completed work, how off-schedule are we?".
54
+ *
55
+ * Returns `null` if no stop in this route has a usable completion event.
56
+ */
57
+ this.getScheduleOffset = (jobs) => {
58
+ let latestEnd = -Infinity;
59
+ let offset = null;
60
+ for (const rj of this.jobs) {
61
+ const job = jobs.find((j) => j.id === rj.job_id);
62
+ if (!job || !job.isDone(this))
63
+ continue;
64
+ // Offset semantics specifically want a *completed* event, not an
65
+ // in-progress one. Use last_completed_event directly rather than
66
+ // getRouteEvent() (which prefers current_event for display).
67
+ const actualEnd = job.last_completed_event?.time_ended;
68
+ if (typeof actualEnd !== 'number' || actualEnd <= 0)
69
+ continue;
70
+ if (actualEnd <= latestEnd)
71
+ continue;
72
+ const predictedCompletion = rj.getPredictedArrival() + job.getServiceDuration(rj);
73
+ latestEnd = actualEnd;
74
+ offset = actualEnd - predictedCompletion;
75
+ }
76
+ return offset;
77
+ };
46
78
  Object.assign(this, init);
47
79
  if (init?.jobs) {
48
80
  this.jobs = init.jobs.map((j) => new RouteJob(j));
@@ -12,4 +12,11 @@ declare module '../../types/api/RouteJob' {
12
12
  }
13
13
  export declare class RouteJob {
14
14
  constructor(init?: Partial<RouteJob>);
15
+ /**
16
+ * Returns the arrival time the UI should show for this stop:
17
+ * `scheduled_arrival_time` if set (>= 0), otherwise the optimizer's
18
+ * `estimated_arrival_time`. The sentinel value -1 means "no manual
19
+ * schedule, fall back to the optimizer estimate".
20
+ */
21
+ getPredictedArrival: () => number;
15
22
  }
@@ -1,5 +1,16 @@
1
1
  export class RouteJob {
2
2
  constructor(init) {
3
+ /**
4
+ * Returns the arrival time the UI should show for this stop:
5
+ * `scheduled_arrival_time` if set (>= 0), otherwise the optimizer's
6
+ * `estimated_arrival_time`. The sentinel value -1 means "no manual
7
+ * schedule, fall back to the optimizer estimate".
8
+ */
9
+ this.getPredictedArrival = () => {
10
+ return this.scheduled_arrival_time === -1
11
+ ? this.estimated_arrival_time
12
+ : this.scheduled_arrival_time;
13
+ };
3
14
  Object.assign(this, init);
4
15
  }
5
16
  }
@@ -102,12 +102,15 @@ export class Task {
102
102
  if (!this.status || this.status !== TaskStatus.ACTIVE) {
103
103
  return true;
104
104
  }
105
- if (this.frequency > 0) {
106
- return (this.last_completed_event?.time_ended ?? 0) > route.start_time;
107
- }
108
- else {
109
- return this.last_completed_event?.time_ended ? true : false;
110
- }
105
+ // Cutoff: midnight (local time) of the day route.start_time falls on.
106
+ // Counts work completed at any point during the route's day (including
107
+ // an early-start autostart that finishes a few minutes before
108
+ // route.start_time) while still rejecting stale events from previous
109
+ // occurrences. Applies to both recurring and one-shot tasks.
110
+ const routeDay = new Date(route.start_time * 1000);
111
+ routeDay.setHours(0, 0, 0, 0);
112
+ const cutoff = Math.floor(routeDay.getTime() / 1000);
113
+ return (this.last_completed_event?.time_ended ?? 0) >= cutoff;
111
114
  };
112
115
  Object.assign(this, init);
113
116
  if (init?.prepayments) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@go-avro/avro-js",
3
- "version": "0.0.44",
3
+ "version": "0.0.46",
4
4
  "description": "JS client for Avro backend integration.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",