@go-avro/avro-js 0.0.65 → 0.0.67

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.
@@ -359,7 +359,8 @@ declare module '../client/QueryClient' {
359
359
  }): UseQueryResult<CheckIn[], StandardError>;
360
360
  useCheckIn(): ReturnType<typeof useMutation<{
361
361
  msg: string;
362
- id: string;
362
+ id: string | null;
363
+ job_id: string | null;
363
364
  }, StandardError, {
364
365
  jobId: string;
365
366
  teamId?: string | null;
@@ -367,16 +368,19 @@ declare module '../client/QueryClient' {
367
368
  useCheckOut(): ReturnType<typeof useMutation<{
368
369
  msg: string;
369
370
  id: string;
371
+ job_id: string | null;
370
372
  }, StandardError, {
371
373
  checkinId: string;
372
374
  }>>;
373
375
  checkInToJob(jobId: string, teamId?: string | null): Promise<{
374
376
  msg: string;
375
- id: string;
377
+ id: string | null;
378
+ job_id: string | null;
376
379
  }>;
377
380
  checkOut(checkinId: string): Promise<{
378
381
  msg: string;
379
382
  id: string;
383
+ job_id: string | null;
380
384
  }>;
381
385
  useImportBillsFromIntuit(): ReturnType<typeof useMutation<{
382
386
  msg: string;
@@ -213,9 +213,38 @@ const SOCKET_EVENT_CONFIG = {
213
213
  },
214
214
  delete_bill: { entityKey: 'bills', action: 'delete', fetchPath: null },
215
215
  update_bills: { invalidateKeys: [['bills']] },
216
- // ── Check-ins ──
217
- create_checkin: { invalidateKeys: [['checkins']] },
218
- update_checkin: { invalidateKeys: [['checkins']] },
216
+ // ── Check-ins (also refresh the job — its payload embeds
217
+ // current_checkins for the on-site indicator) ──
218
+ create_checkin: {
219
+ entityKey: 'checkins',
220
+ action: 'create',
221
+ fetchPath: null,
222
+ alsoInvalidate: [['checkins']],
223
+ relatedRefetch: [
224
+ {
225
+ entityKey: 'jobs',
226
+ idField: 'job_id',
227
+ fetchPath: (id) => `/job/${id}`,
228
+ construct: (d) => new Job(d),
229
+ matchesQuery: matchesJobsListQuery,
230
+ },
231
+ ],
232
+ },
233
+ update_checkin: {
234
+ entityKey: 'checkins',
235
+ action: 'update',
236
+ fetchPath: null,
237
+ alsoInvalidate: [['checkins']],
238
+ relatedRefetch: [
239
+ {
240
+ entityKey: 'jobs',
241
+ idField: 'job_id',
242
+ fetchPath: (id) => `/job/${id}`,
243
+ construct: (d) => new Job(d),
244
+ matchesQuery: matchesJobsListQuery,
245
+ },
246
+ ],
247
+ },
219
248
  // ── Sessions ──
220
249
  create_session: {
221
250
  entityKey: 'sessions',
@@ -301,7 +330,18 @@ const SOCKET_EVENT_CONFIG = {
301
330
  },
302
331
  // ── Scheduling ──
303
332
  schedule_complete: {
304
- invalidateKeys: [['routes'], ['jobs'], ['infinite', 'jobs'], ['companies']],
333
+ invalidateKeys: [
334
+ ['routes'],
335
+ ['jobs'],
336
+ ['infinite', 'jobs'],
337
+ ['companies'],
338
+ ['/company/list'],
339
+ ],
340
+ },
341
+ // Terminal failure of a scheduling run: refetch companies so the
342
+ // "scheduling in progress" banner (company.schedule_locked) clears
343
+ scheduling_error: {
344
+ invalidateKeys: [['companies'], ['/company/list']],
305
345
  },
306
346
  // ── Location ──
307
347
  location_update: { invalidateKeys: [['teams']] },
@@ -753,11 +793,11 @@ export class AvroQueryClient {
753
793
  return undefined;
754
794
  }
755
795
  try {
756
- const raw = await queryClient.fetchQuery({
757
- queryKey: [entityKey, id],
758
- queryFn: () => this.get({ path: fetchPath }),
759
- staleTime: 0,
760
- });
796
+ // Direct fetch, not fetchQuery: fetchQuery would return an
797
+ // already-in-flight (older) request for the same entity,
798
+ // losing the newer state when socket events arrive in a
799
+ // burst (e.g. auto-checkout followed by check-in)
800
+ const raw = await this.get({ path: fetchPath });
761
801
  const item = construct ? construct(raw) : raw;
762
802
  queryClient.setQueryData([entityKey, id], item);
763
803
  const matchingQueries = queryClient.getQueryCache().findAll({ predicate });
@@ -1,5 +1,29 @@
1
1
  import { useMutation, useQuery } from '@tanstack/react-query';
2
2
  import { AvroQueryClient } from '../../client/QueryClient';
3
+ import { Job } from '../../types/api/Job';
4
+ /**
5
+ * Refresh the caches a check-in mutation touches. Socket events cover
6
+ * connected clients, but the raw helpers run headless (background
7
+ * location task) where the socket is usually down — sync directly.
8
+ */
9
+ const syncCheckinCaches = async (client, jobId) => {
10
+ const queryClient = client.getQueryClient();
11
+ queryClient.invalidateQueries({ queryKey: ['checkins'] });
12
+ if (!jobId)
13
+ return;
14
+ try {
15
+ await client._syncEntity(queryClient, {
16
+ action: 'update',
17
+ entityKey: 'jobs',
18
+ id: jobId,
19
+ fetchPath: `/job/${jobId}`,
20
+ construct: (d) => new Job(d),
21
+ });
22
+ }
23
+ catch {
24
+ // Cache sync is best-effort; the mutation itself succeeded
25
+ }
26
+ };
3
27
  AvroQueryClient.prototype.useJobCheckins = function (jobId, params) {
4
28
  return useQuery({
5
29
  queryKey: ['checkins', jobId, params?.since ?? 'today'],
@@ -30,17 +54,21 @@ AvroQueryClient.prototype.useCheckOut = function () {
30
54
  });
31
55
  };
32
56
  // Raw helpers, safe outside React (headless background location task)
33
- AvroQueryClient.prototype.checkInToJob = function (jobId, teamId) {
34
- return this.post({
57
+ AvroQueryClient.prototype.checkInToJob = async function (jobId, teamId) {
58
+ const result = await this.post({
35
59
  path: `/job/${jobId}/checkin`,
36
60
  data: JSON.stringify(teamId ? { team_id: teamId } : {}),
37
61
  headers: { 'Content-Type': 'application/json' },
38
62
  });
63
+ await syncCheckinCaches(this, result.job_id ?? jobId);
64
+ return result;
39
65
  };
40
- AvroQueryClient.prototype.checkOut = function (checkinId) {
41
- return this.post({
66
+ AvroQueryClient.prototype.checkOut = async function (checkinId) {
67
+ const result = await this.post({
42
68
  path: `/checkin/${checkinId}/checkout`,
43
69
  data: JSON.stringify({}),
44
70
  headers: { 'Content-Type': 'application/json' },
45
71
  });
72
+ await syncCheckinCaches(this, result.job_id);
73
+ return result;
46
74
  };
@@ -44,7 +44,7 @@ AvroQueryClient.prototype.useGetActiveCompanySessions = function (params = {}) {
44
44
  for (const session of pageSessions) {
45
45
  const isOpen = session.time_ended == null ||
46
46
  session.time_ended <= 0 ||
47
- session.time_ended <= session.time_started;
47
+ session.time_ended < session.time_started;
48
48
  if (isOpen)
49
49
  openSessions.push(session);
50
50
  }
@@ -40,6 +40,7 @@ export interface Company {
40
40
  num_jobs: number;
41
41
  num_routes: number;
42
42
  schedule_locked: boolean;
43
+ schedule_locked_since: number | null;
43
44
  num_teams: number;
44
45
  num_skills: number;
45
46
  bills: Bill[];
@@ -1,5 +1,6 @@
1
1
  import { Task } from '../../types/api/Task';
2
2
  import { _Event } from '../../types/api/_Event';
3
+ import type { CheckIn } from '../../types/api';
3
4
  import { RouteJob } from '../../types/api/RouteJob';
4
5
  import { Subscription } from '../../types/api/Subscription';
5
6
  import { Route } from '../../types/api/Route';
@@ -25,6 +26,7 @@ declare module '../../types/api/Job' {
25
26
  manual_emails: string[][];
26
27
  last_completed_event: _Event | null;
27
28
  current_event: _Event | null;
29
+ current_checkins: CheckIn[];
28
30
  labels: string[];
29
31
  owner: string | null;
30
32
  }
@@ -229,6 +229,7 @@ export interface CheckIn {
229
229
  session_id: string;
230
230
  team_id: string | null;
231
231
  company_id: string;
232
+ event_id: string | null;
232
233
  time_checked_in: number;
233
234
  time_checked_out: number | null;
234
235
  time_created: number | null;
@@ -237,8 +238,8 @@ export interface CheckIn {
237
238
  /** Wire shape for per-participant entries on an event update. */
238
239
  export interface EventUserUpdate {
239
240
  user_id: string;
240
- time_started?: number;
241
- time_ended?: number;
241
+ time_started?: number | null;
242
+ time_ended?: number | null;
242
243
  }
243
244
  /** Event update payload: _Event fields, but users use the wire shape. */
244
245
  export type EventUpdatePayload = Partial<Omit<_Event, 'users'>> & {
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const AVRO_JS_VERSION = "0.0.65";
1
+ export declare const AVRO_JS_VERSION = "0.0.67";
package/dist/version.js CHANGED
@@ -1,3 +1,3 @@
1
1
  // AUTO-GENERATED by scripts/gen-version.js — do not edit by hand.
2
2
  // Regenerated from package.json by the `prebuild` npm hook.
3
- export const AVRO_JS_VERSION = '0.0.65';
3
+ export const AVRO_JS_VERSION = '0.0.67';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@go-avro/avro-js",
3
- "version": "0.0.65",
3
+ "version": "0.0.67",
4
4
  "description": "JS client for Avro backend integration.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",