@go-avro/avro-js 0.0.34 → 0.0.36

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.
@@ -216,6 +216,7 @@ export class AvroQueryClient {
216
216
  return;
217
217
  }
218
218
  const entityPredicate = (q) => matchesEntityKey(q, entityKey);
219
+ let fetchedItem;
219
220
  switch (action) {
220
221
  // ─── CREATE ─────────────────────────────────
221
222
  case 'create': {
@@ -226,6 +227,7 @@ export class AvroQueryClient {
226
227
  queryFn: () => client.get({ path: fetchPath(id) }),
227
228
  staleTime: 0,
228
229
  });
230
+ fetchedItem = item;
229
231
  queryClient.setQueriesData({ predicate: entityPredicate, type: 'active' }, (old) => {
230
232
  if (!old)
231
233
  return old;
@@ -270,6 +272,7 @@ export class AvroQueryClient {
270
272
  queryFn: () => client.get({ path: fetchPath(id) }),
271
273
  staleTime: 0,
272
274
  });
275
+ fetchedItem = item;
273
276
  // Patch it into every active list / infinite-query cache
274
277
  queryClient.setQueriesData({ predicate: entityPredicate, type: 'active' }, (old) => {
275
278
  if (!old)
@@ -323,7 +326,7 @@ export class AvroQueryClient {
323
326
  // Refetch & patch related entities (e.g. event → parent job)
324
327
  if (relatedRefetch) {
325
328
  for (const related of relatedRefetch) {
326
- const relatedId = data?.[related.idField];
329
+ const relatedId = data?.[related.idField] ?? fetchedItem?.[related.idField];
327
330
  if (!relatedId || typeof relatedId !== 'string')
328
331
  continue;
329
332
  try {
@@ -1,6 +1,10 @@
1
1
  import { useInfiniteQuery, useQuery, useMutation } from '@tanstack/react-query';
2
2
  import { AvroQueryClient } from '../../client/QueryClient';
3
- import { _Event, LineItemStatus } from '../../types/api';
3
+ import { _Event, Job, LineItemStatus } from '../../types/api';
4
+ /** Predicate that matches all 'jobs' queries (list and individual, but NOT 'infinite'). */
5
+ const isJobsQuery = (q) => q.queryKey[0] === 'jobs';
6
+ /** Predicate that matches all 'events' queries (list and individual). */
7
+ const isEventsQuery = (q) => q.queryKey[0] === 'events';
4
8
  AvroQueryClient.prototype.useGetEvents = function (body) {
5
9
  const queryClient = this.getQueryClient();
6
10
  const result = useInfiniteQuery({
@@ -54,70 +58,67 @@ AvroQueryClient.prototype.useCreateEvent = function () {
54
58
  },
55
59
  onMutate: async ({ eventData }) => {
56
60
  await queryClient.cancelQueries({ queryKey: ['events'] });
57
- const previousEvents = queryClient.getQueryData(['events']);
58
61
  const previousJob = queryClient.getQueryData(['jobs', eventData.job_id]);
59
- const previousJobs = queryClient.getQueryData(['jobs']);
60
62
  const optimisticEvent = new _Event({
61
63
  ...eventData,
62
64
  id: Math.random().toString(36).substring(2, 11),
63
65
  company_id: this.companyId,
64
66
  });
65
67
  if (previousJob) {
66
- const updatedJob = {
68
+ const updatedJob = new Job({
67
69
  ...previousJob,
68
70
  current_event: optimisticEvent,
69
71
  last_completed_event: (optimisticEvent.time_ended ?? -1) > -1 ? optimisticEvent : previousJob.last_completed_event,
70
- };
71
- updatedJob.tasks = previousJob.tasks.map((task) => {
72
- if (eventData.tasks?.includes(task.id ?? "")) {
73
- return {
74
- ...task,
75
- current_event: optimisticEvent,
76
- last_completed_event: (optimisticEvent.time_ended ?? -1) > -1 ? optimisticEvent : task.last_completed_event,
77
- };
78
- }
79
- return task;
72
+ tasks: previousJob.tasks.map((task) => {
73
+ if (eventData.tasks?.includes(task.id ?? "")) {
74
+ return {
75
+ ...task,
76
+ current_event: optimisticEvent,
77
+ last_completed_event: (optimisticEvent.time_ended ?? -1) > -1 ? optimisticEvent : task.last_completed_event,
78
+ };
79
+ }
80
+ return task;
81
+ }),
82
+ });
83
+ // Update individual job cache AND every active jobs list/query
84
+ queryClient.setQueriesData({ predicate: isJobsQuery, type: 'active' }, (old) => {
85
+ if (!old)
86
+ return old;
87
+ if (Array.isArray(old))
88
+ return old.map((j) => j?.id === updatedJob.id ? updatedJob : j);
89
+ if (old?.id === updatedJob.id)
90
+ return updatedJob;
91
+ return old;
80
92
  });
81
- const updatedJobs = previousJobs?.map((job) => job.id === updatedJob.id ? updatedJob : job);
82
- queryClient.setQueryData(['jobs', previousJob.id], updatedJob);
83
- queryClient.setQueryData(['jobs'], updatedJobs);
84
93
  }
85
- queryClient.setQueryData(['events'], (oldData) => {
94
+ // Add optimistic event to all active events queries
95
+ queryClient.setQueriesData({ predicate: isEventsQuery, type: 'active' }, (oldData) => {
86
96
  if (!oldData)
87
- return [];
97
+ return oldData;
88
98
  if (oldData.pages) {
89
99
  const firstPage = oldData.pages[0] || [];
90
100
  return {
91
101
  ...oldData,
92
102
  pages: [
93
- [
94
- optimisticEvent,
95
- ...firstPage,
96
- ],
103
+ [optimisticEvent, ...firstPage],
97
104
  ...oldData.pages.slice(1),
98
105
  ],
99
106
  };
100
107
  }
101
108
  if (Array.isArray(oldData)) {
102
- return [
103
- optimisticEvent,
104
- ...oldData,
105
- ];
109
+ return [optimisticEvent, ...oldData];
106
110
  }
107
111
  return oldData;
108
112
  });
109
- return { previousEvents, previousJob, previousJobs };
113
+ return { previousJob };
110
114
  },
111
115
  onError: (err, variables, context) => {
112
- if (context?.previousEvents) {
113
- queryClient.setQueryData(['events'], context.previousEvents);
114
- }
116
+ // Restore individual job; invalidate lists to refetch clean state
115
117
  if (context?.previousJob) {
116
118
  queryClient.setQueryData(['jobs', context.previousJob.id], context.previousJob);
117
119
  }
118
- if (context?.previousJobs) {
119
- queryClient.setQueryData(['jobs'], context.previousJobs);
120
- }
120
+ queryClient.invalidateQueries({ predicate: isJobsQuery });
121
+ queryClient.invalidateQueries({ predicate: isEventsQuery });
121
122
  },
122
123
  });
123
124
  };
@@ -134,30 +135,52 @@ AvroQueryClient.prototype.useUpdateEvent = function () {
134
135
  onMutate: async ({ eventId, updates }) => {
135
136
  await queryClient.cancelQueries({ queryKey: ['events', eventId] });
136
137
  await queryClient.cancelQueries({ queryKey: ['events'] });
137
- const previousEvent = queryClient.getQueryData(['events', eventId]);
138
- const previousEvents = queryClient.getQueryData(['events']);
138
+ // Try individual cache first; fall back to scanning all active events queries
139
+ let previousEvent = queryClient.getQueryData(['events', eventId]);
140
+ if (!previousEvent) {
141
+ const allEventsData = queryClient.getQueriesData({ predicate: isEventsQuery });
142
+ outer: for (const [, data] of allEventsData) {
143
+ const pages = data?.pages ?? (Array.isArray(data) ? [data] : undefined);
144
+ if (pages) {
145
+ for (const page of pages) {
146
+ const found = page.find((e) => e.id === eventId);
147
+ if (found) {
148
+ previousEvent = found;
149
+ break outer;
150
+ }
151
+ }
152
+ }
153
+ }
154
+ }
139
155
  const previousJob = queryClient.getQueryData(['jobs', previousEvent?.job_id]);
140
- const previousJobs = queryClient.getQueryData(['jobs']);
141
156
  if (previousJob) {
142
- const updatedJob = {
157
+ const isEnding = (updates.time_ended ?? -1) > -1;
158
+ const mergedEvent = previousEvent ? new _Event({ ...previousEvent, ...updates }) : null;
159
+ const updatedJob = new Job({
143
160
  ...previousJob,
144
- current_event: previousEvent ? { ...previousEvent, ...updates } : previousJob.current_event,
145
- last_completed_event: (updates.time_ended ?? -1) > -1 && previousEvent ? { ...previousEvent, ...updates } : previousJob.last_completed_event,
146
- };
147
- updatedJob.tasks = previousJob.tasks.map((task) => {
148
- if (updates.tasks?.includes(task.id ?? "")) {
149
- return {
150
- ...task,
151
- current_event: previousEvent ? { ...previousEvent, ...updates } : task.current_event,
152
- last_completed_event: (updates.time_ended ?? -1) > -1 ? (previousEvent ? { ...previousEvent, ...updates } : task.last_completed_event) : task.last_completed_event,
153
- overdue_time: -(task.frequency ?? 0) - (task.delay ?? 0),
154
- };
155
- }
156
- return task;
161
+ current_event: isEnding ? null : (mergedEvent ?? previousJob.current_event),
162
+ last_completed_event: isEnding && mergedEvent ? mergedEvent : previousJob.last_completed_event,
163
+ tasks: previousJob.tasks.map((task) => {
164
+ if (updates.tasks?.includes(task.id ?? "")) {
165
+ return {
166
+ ...task,
167
+ current_event: isEnding ? null : (previousEvent ? { ...previousEvent, ...updates } : task.current_event),
168
+ last_completed_event: isEnding ? (previousEvent ? { ...previousEvent, ...updates } : task.last_completed_event) : task.last_completed_event,
169
+ overdue_time: isEnding ? -(task.frequency ?? 0) - (task.delay ?? 0) : task.overdue_time,
170
+ };
171
+ }
172
+ return task;
173
+ }),
174
+ });
175
+ queryClient.setQueriesData({ predicate: isJobsQuery, type: 'active' }, (old) => {
176
+ if (!old)
177
+ return old;
178
+ if (Array.isArray(old))
179
+ return old.map((j) => j?.id === updatedJob.id ? updatedJob : j);
180
+ if (old?.id === updatedJob.id)
181
+ return updatedJob;
182
+ return old;
157
183
  });
158
- const updatedJobs = previousJobs?.map((job) => job.id === updatedJob.id ? updatedJob : job);
159
- queryClient.setQueryData(['jobs', previousJob.id], updatedJob);
160
- queryClient.setQueryData(['jobs'], updatedJobs);
161
184
  }
162
185
  queryClient.setQueryData(['events', eventId], (oldData) => oldData ? { ...oldData, ...updates } : undefined);
163
186
  queryClient.setQueriesData({ queryKey: ['events'] }, (oldData) => {
@@ -172,22 +195,18 @@ AvroQueryClient.prototype.useUpdateEvent = function () {
172
195
  }
173
196
  return oldData;
174
197
  });
175
- return { previousEvent, previousEvents, previousJob, previousJobs };
198
+ return { previousEvent, previousJob };
176
199
  },
177
200
  onError: (_err, variables, context) => {
178
201
  const { eventId } = variables;
179
202
  if (context?.previousEvent) {
180
203
  queryClient.setQueryData(['events', eventId], context.previousEvent);
181
204
  }
182
- if (context?.previousEvents) {
183
- queryClient.setQueryData(['events'], context.previousEvents);
184
- }
185
205
  if (context?.previousJob) {
186
206
  queryClient.setQueryData(['jobs', context.previousJob.id], context.previousJob);
187
207
  }
188
- if (context?.previousJobs) {
189
- queryClient.setQueryData(['jobs'], context.previousJobs);
190
- }
208
+ queryClient.invalidateQueries({ predicate: isJobsQuery });
209
+ queryClient.invalidateQueries({ predicate: isEventsQuery });
191
210
  },
192
211
  });
193
212
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@go-avro/avro-js",
3
- "version": "0.0.34",
3
+ "version": "0.0.36",
4
4
  "description": "JS client for Avro backend integration.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",