From 32ddbf6e48d86fa604dce705d989ec361b3cb42e Mon Sep 17 00:00:00 2001 From: Petter Machado Date: Tue, 12 Nov 2024 10:10:54 +0100 Subject: [PATCH] fix: Null locations (#17) * fix: Handle null/deactivated locations * fix: Handle null/deactivated locations in UI --- app/components/columns/zone.tsx | 2 +- app/types.ts | 2 +- lib/soundtrack-api/client.ts | 22 +++++++++++++++++----- lib/soundtrack-api/index.ts | 22 ++++++++++++++++++++-- lib/soundtrack-api/types.ts | 4 ++-- 5 files changed, 41 insertions(+), 11 deletions(-) diff --git a/app/components/columns/zone.tsx b/app/components/columns/zone.tsx index 2e7b761..487eedb 100644 --- a/app/components/columns/zone.tsx +++ b/app/components/columns/zone.tsx @@ -57,7 +57,7 @@ export const columns: ColumnDef[] = [ { id: "location", header: "Location", - accessorFn: ({ zone }) => zone?.location.name, + accessorFn: ({ zone }) => zone?.location?.name, meta: { filter: "select", }, diff --git a/app/types.ts b/app/types.ts index 2004fad..5e4668a 100644 --- a/app/types.ts +++ b/app/types.ts @@ -63,7 +63,7 @@ export type Account = { export type Zone = { id: string; name: string; - location: Location; + location: Location | null; account: { id: string }; }; diff --git a/lib/soundtrack-api/client.ts b/lib/soundtrack-api/client.ts index a860be6..7c5bd9c 100644 --- a/lib/soundtrack-api/client.ts +++ b/lib/soundtrack-api/client.ts @@ -6,9 +6,17 @@ import { getLogger } from "../logger/index.js"; const logger = getLogger("lib/soundtrack-api/client"); const semaphore = new Semaphore(3); +type GraphQLErrorPathSegment = string | number; +type GraphQLErrorType = { + message: string; + path: GraphQLErrorPathSegment[] | null | undefined; + extensions: { code: string } | null | undefined; +}; +type ErrorType = GraphQLErrorType; + type QueryResponse = { data: T; - errors?: unknown[]; + errors?: ErrorType[]; }; type TokenType = "Bearer" | "Basic"; @@ -140,12 +148,16 @@ async function request( const { data, errors } = (await res.json()) as QueryResponse; if (errors && opts.errorPolicy !== "all") { - errors.forEach((error, i) => { - const msg = `(${i + 1}/${errors.length}) ${inspect(error)}`; - logger.error(`GraphQL request returned error: ${msg}`); - }); + logGraphQLErrors(errors); throw new Error("GraphQL request retured errors"); } return { data, errors }; } + +export function logGraphQLErrors(errors: GraphQLErrorType[]) { + errors.forEach((error, i) => { + const msg = `(${i + 1}/${errors.length}) ${inspect(error)}`; + logger.error(`GraphQL request returned error: ${msg}`); + }); +} diff --git a/lib/soundtrack-api/index.ts b/lib/soundtrack-api/index.ts index ea778bd..0ecf5b5 100644 --- a/lib/soundtrack-api/index.ts +++ b/lib/soundtrack-api/index.ts @@ -1,4 +1,9 @@ -import { runMutation, RunOptions, runQuery } from "./client.js"; +import { + logGraphQLErrors, + runMutation, + RunOptions, + runQuery, +} from "./client.js"; import { Semaphore } from "@shopify/semaphore"; import { Account, @@ -185,8 +190,21 @@ export class Api { const res = await runQuery( accountZonesQuery, { id: accountId, cursor }, - await this.runOptions(), + await this.runOptions({ errorPolicy: "all" }), ); + if (res.errors && res.errors.length > 0) { + logGraphQLErrors(res.errors); + const onlyMissingLocationErrors = res.errors.every((error) => { + const code = error.extensions?.code; + const lastPath = error.path?.[error.path.length - 1]; + return code === "NOT_FOUND" && lastPath === "location"; + }); + if (onlyMissingLocationErrors) { + logger.warn("Request returned zones without locations"); + } else { + throw new Error("GraphQL request returned errors"); + } + } const zoneFn = toZoneFn(accountId); const zones: Zone[] = acc.concat( res.data.account.soundZones.edges.map(({ node }) => zoneFn(node)), diff --git a/lib/soundtrack-api/types.ts b/lib/soundtrack-api/types.ts index 26058d4..9c69ce5 100644 --- a/lib/soundtrack-api/types.ts +++ b/lib/soundtrack-api/types.ts @@ -11,14 +11,14 @@ export type Location = { export type AccountZone = { id: string; name: string; - location: Location; + location: Location | null; }; export type Zone = { id: string; name: string; account: { id: string }; - location: Location; + location: Location | null; }; export type AccountLibrary = {