mirror of
https://github.com/samuelthomas2774/nxapi.git
synced 2026-03-21 18:04:10 -05:00
Strict GraphQL query error handling
This commit is contained in:
parent
bdf72352fb
commit
d23a65ba2e
|
|
@ -37,12 +37,25 @@ const AUTH_ERROR_CODES = {
|
|||
|
||||
const REPLAY_CODE_REGEX = /^[A-Z0-9]{16}$/;
|
||||
|
||||
export const RequestIdSymbol = Symbol('RequestId');
|
||||
export const VariablesSymbol = Symbol('Variables');
|
||||
|
||||
export type PersistedQueryResult<T> = GraphQLSuccessResponse<T> & PersistedQueryResultData;
|
||||
|
||||
export interface PersistedQueryResultData {
|
||||
[ResponseSymbol]: Response;
|
||||
[RequestIdSymbol]: KnownRequestId;
|
||||
[VariablesSymbol]: {};
|
||||
}
|
||||
|
||||
export default class SplatNet3Api {
|
||||
onTokenShouldRenew: ((remaining: number, res: Response) => Promise<SplatNet3AuthData | void>) | null = null;
|
||||
onTokenExpired: ((res: Response) => Promise<SplatNet3AuthData | void>) | null = null;
|
||||
/** @internal */
|
||||
_renewToken: Promise<void> | null = null;
|
||||
|
||||
graphql_strict = process.env.NXAPI_SPLATNET3_STRICT !== '0';
|
||||
|
||||
protected constructor(
|
||||
public bullet_token: string,
|
||||
public version: string,
|
||||
|
|
@ -121,7 +134,7 @@ export default class SplatNet3Api {
|
|||
/** @private */
|
||||
_Variables extends (V extends object ? V : _Id extends KnownRequestId ? VariablesTypes[_Id] : unknown) =
|
||||
(V extends object ? V : _Id extends KnownRequestId ? VariablesTypes[_Id] : unknown),
|
||||
>(id: _Id, variables: _Variables) {
|
||||
>(id: _Id, variables: _Variables): Promise<PersistedQueryResult<_Result>> {
|
||||
const req: GraphQLRequest<_Variables> = {
|
||||
variables,
|
||||
extensions: {
|
||||
|
|
@ -135,12 +148,19 @@ export default class SplatNet3Api {
|
|||
const data = await this.fetch<GraphQLResponse<_Result>>('/graphql', 'POST', JSON.stringify(req), undefined,
|
||||
'graphql query ' + id);
|
||||
|
||||
if (!('data' in data)) {
|
||||
throw new ErrorResponse('[splatnet3] GraphQL error: ' + data.errors.map(e => e.message).join(', '),
|
||||
if (!('data' in data) || (this.graphql_strict && data.errors?.length)) {
|
||||
throw new ErrorResponse('[splatnet3] GraphQL error: ' + data.errors!.map(e => e.message).join(', '),
|
||||
data[ResponseSymbol], data);
|
||||
}
|
||||
|
||||
return data;
|
||||
for (const error of data.errors ?? []) {
|
||||
debugGraphQl('GraphQL error in query %s: %s', id, error.message, error);
|
||||
}
|
||||
|
||||
Object.defineProperty(data, RequestIdSymbol, {value: id});
|
||||
Object.defineProperty(data, VariablesSymbol, {value: variables});
|
||||
|
||||
return data as PersistedQueryResult<_Result>;
|
||||
}
|
||||
|
||||
/** * */
|
||||
|
|
|
|||
|
|
@ -3,12 +3,12 @@ import * as fs from 'node:fs/promises';
|
|||
import createDebug from 'debug';
|
||||
import mkdirp from 'mkdirp';
|
||||
import fetch from 'node-fetch';
|
||||
import { PhotoAlbumResult, RequestId } from 'splatnet3-types/splatnet3';
|
||||
import { PhotoAlbumResult } from 'splatnet3-types/splatnet3';
|
||||
import type { Arguments as ParentArguments } from '../splatnet3.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getBulletToken } from '../../common/auth/splatnet3.js';
|
||||
import SplatNet3Api from '../../api/splatnet3.js';
|
||||
import SplatNet3Api, { RequestIdSymbol } from '../../api/splatnet3.js';
|
||||
import { ResponseSymbol } from '../../api/util.js';
|
||||
import { timeoutSignal } from '../../util/misc.js';
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ export async function dumpAlbumPhotos(
|
|||
debug('Writing %s', filename);
|
||||
await fs.writeFile(file, JSON.stringify({
|
||||
result: results.data.photoAlbum,
|
||||
query: refresh ? RequestId.PhotoAlbumRefetchQuery : RequestId.PhotoAlbumQuery,
|
||||
query: results[RequestIdSymbol],
|
||||
app_version: splatnet.version,
|
||||
be_version: results[ResponseSymbol].headers.get('x-be-version'),
|
||||
}, null, 4) + '\n', 'utf-8');
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import type { Arguments as ParentArguments } from '../splatnet3.js';
|
|||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getBulletToken } from '../../common/auth/splatnet3.js';
|
||||
import SplatNet3Api from '../../api/splatnet3.js';
|
||||
import SplatNet3Api, { RequestIdSymbol } from '../../api/splatnet3.js';
|
||||
import { ResponseSymbol } from '../../api/util.js';
|
||||
|
||||
const debug = createDebug('cli:splatnet3:dump-records');
|
||||
|
|
@ -62,7 +62,7 @@ export async function dumpFestRecords(splatnet: SplatNet3Api, directory: string,
|
|||
await fs.writeFile(file, JSON.stringify({
|
||||
result: records.data.festRecords,
|
||||
player: records.data.currentPlayer,
|
||||
query: RequestId.FestRecordQuery,
|
||||
query: records[RequestIdSymbol],
|
||||
app_version: splatnet.version,
|
||||
be_version: records[ResponseSymbol].headers.get('x-be-version'),
|
||||
}, null, 4) + '\n', 'utf-8');
|
||||
|
|
@ -77,7 +77,7 @@ export async function dumpFestRecords(splatnet: SplatNet3Api, directory: string,
|
|||
|
||||
const filename = 'splatnet3-fest-' + id + '-' +
|
||||
(fest_record.state !== FestState.CLOSED ? Date.now() + '-' : '') +
|
||||
RequestId.DetailFestRecordDetailQuery + '.json';
|
||||
records[RequestIdSymbol] + '.json';
|
||||
const file = path.join(directory, filename);
|
||||
|
||||
let record: Fest_detail | null = null;
|
||||
|
|
@ -96,7 +96,7 @@ export async function dumpFestRecords(splatnet: SplatNet3Api, directory: string,
|
|||
await fs.writeFile(file, JSON.stringify({
|
||||
result: result.data.fest,
|
||||
player: result.data.currentPlayer,
|
||||
query: RequestId.DetailFestRecordDetailQuery,
|
||||
query: result[RequestIdSymbol],
|
||||
app_version: splatnet.version,
|
||||
be_version: result[ResponseSymbol].headers.get('x-be-version'),
|
||||
}, null, 4) + '\n', 'utf-8');
|
||||
|
|
@ -121,7 +121,7 @@ export async function dumpFestRecords(splatnet: SplatNet3Api, directory: string,
|
|||
debug('Writing %s', filename);
|
||||
await fs.writeFile(file, JSON.stringify({
|
||||
result: result.data.fest,
|
||||
query: RequestId.DetailVotingStatusQuery,
|
||||
query: result[RequestIdSymbol],
|
||||
app_version: splatnet.version,
|
||||
be_version: result[ResponseSymbol].headers.get('x-be-version'),
|
||||
}, null, 4) + '\n', 'utf-8');
|
||||
|
|
@ -151,7 +151,7 @@ export async function dumpFestRecords(splatnet: SplatNet3Api, directory: string,
|
|||
debug('Writing %s', filename);
|
||||
await fs.writeFile(file, JSON.stringify({
|
||||
result: result.data.fest,
|
||||
query: RequestId.DetailFestRecordDetailQuery,
|
||||
query: result[RequestIdSymbol],
|
||||
app_version: splatnet.version,
|
||||
be_version: result[ResponseSymbol].headers.get('x-be-version'),
|
||||
}, null, 4) + '\n', 'utf-8');
|
||||
|
|
|
|||
|
|
@ -2,12 +2,11 @@ import * as path from 'node:path';
|
|||
import * as fs from 'node:fs/promises';
|
||||
import createDebug from 'debug';
|
||||
import mkdirp from 'mkdirp';
|
||||
import { RequestId } from 'splatnet3-types/splatnet3';
|
||||
import type { Arguments as ParentArguments } from '../splatnet3.js';
|
||||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getBulletToken } from '../../common/auth/splatnet3.js';
|
||||
import SplatNet3Api from '../../api/splatnet3.js';
|
||||
import SplatNet3Api, { RequestIdSymbol } from '../../api/splatnet3.js';
|
||||
import { ResponseSymbol } from '../../api/util.js';
|
||||
|
||||
const debug = createDebug('cli:splatnet3:dump-records');
|
||||
|
|
@ -96,7 +95,7 @@ export async function dumpHistoryRecords(splatnet: SplatNet3Api, directory: stri
|
|||
await fs.writeFile(file, JSON.stringify({
|
||||
result: results.data.playHistory,
|
||||
player: results.data.currentPlayer,
|
||||
query: refresh ? RequestId.HistoryRecordRefetchQuery : RequestId.HistoryRecordQuery,
|
||||
query: results[RequestIdSymbol],
|
||||
app_version: splatnet.version,
|
||||
be_version: results[ResponseSymbol].headers.get('x-be-version'),
|
||||
}, null, 4) + '\n', 'utf-8');
|
||||
|
|
@ -114,7 +113,7 @@ export async function dumpHeroRecords(splatnet: SplatNet3Api, directory: string)
|
|||
debug('Writing %s', filename);
|
||||
await fs.writeFile(file, JSON.stringify({
|
||||
result: results.data.heroRecord,
|
||||
query: RequestId.HeroHistoryQuery,
|
||||
query: results[RequestIdSymbol],
|
||||
app_version: splatnet.version,
|
||||
be_version: results[ResponseSymbol].headers.get('x-be-version'),
|
||||
}, null, 4) + '\n', 'utf-8');
|
||||
|
|
@ -134,7 +133,7 @@ export async function dumpCatalogRecords(splatnet: SplatNet3Api, directory: stri
|
|||
debug('Writing %s', filename);
|
||||
await fs.writeFile(file, JSON.stringify({
|
||||
result: results.data.catalog,
|
||||
query: refresh ? RequestId.CatalogRefetchQuery : RequestId.CatalogQuery,
|
||||
query: results[RequestIdSymbol],
|
||||
app_version: splatnet.version,
|
||||
be_version: results[ResponseSymbol].headers.get('x-be-version'),
|
||||
}, null, 4) + '\n', 'utf-8');
|
||||
|
|
@ -154,7 +153,7 @@ export async function dumpStageStats(splatnet: SplatNet3Api, directory: string,
|
|||
debug('Writing %s', filename);
|
||||
await fs.writeFile(file, JSON.stringify({
|
||||
result: results.data.stageRecords,
|
||||
query: refresh ? RequestId.StageRecordsRefetchQuery : RequestId.StageRecordQuery,
|
||||
query: results[RequestIdSymbol],
|
||||
app_version: splatnet.version,
|
||||
be_version: results[ResponseSymbol].headers.get('x-be-version'),
|
||||
}, null, 4) + '\n', 'utf-8');
|
||||
|
|
@ -174,7 +173,7 @@ export async function dumpWeaponStats(splatnet: SplatNet3Api, directory: string,
|
|||
debug('Writing %s', filename);
|
||||
await fs.writeFile(file, JSON.stringify({
|
||||
result: results.data.weaponRecords,
|
||||
query: refresh ? RequestId.WeaponRecordsRefetchQuery : RequestId.WeaponRecordQuery,
|
||||
query: results[RequestIdSymbol],
|
||||
app_version: splatnet.version,
|
||||
be_version: results[ResponseSymbol].headers.get('x-be-version'),
|
||||
}, null, 4) + '\n', 'utf-8');
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import type { Arguments as ParentArguments } from '../splatnet3.js';
|
|||
import { ArgumentsCamelCase, Argv, YargsArguments } from '../../util/yargs.js';
|
||||
import { initStorage } from '../../util/storage.js';
|
||||
import { getBulletToken } from '../../common/auth/splatnet3.js';
|
||||
import SplatNet3Api from '../../api/splatnet3.js';
|
||||
import SplatNet3Api, { RequestIdSymbol } from '../../api/splatnet3.js';
|
||||
import { ResponseSymbol } from '../../api/util.js';
|
||||
import { dumpCatalogRecords, dumpHistoryRecords } from './dump-records.js';
|
||||
|
||||
|
|
@ -101,7 +101,7 @@ export async function dumpResults(
|
|||
await fs.writeFile(file, JSON.stringify({
|
||||
player: player ? {
|
||||
result: player.data.currentPlayer,
|
||||
query: RequestId.BattleHistoryCurrentPlayerQuery,
|
||||
query: player[RequestIdSymbol],
|
||||
be_version: player[ResponseSymbol].headers.get('x-be-version'),
|
||||
} : undefined,
|
||||
latestBattleHistories: {
|
||||
|
|
@ -109,23 +109,30 @@ export async function dumpResults(
|
|||
fest: battles.data.currentFest,
|
||||
player: 'currentPlayer' in battles.data ?
|
||||
(battles.data as LatestBattleHistoriesRefetchResult<true>).currentPlayer : undefined,
|
||||
query: refresh ? RequestId.LatestBattleHistoriesRefetchQuery : RequestId.LatestBattleHistoriesQuery,
|
||||
query: battles[RequestIdSymbol],
|
||||
be_version: battles[ResponseSymbol].headers.get('x-be-version'),
|
||||
},
|
||||
regularBattleHistories: {
|
||||
result: battles_regular.data.regularBattleHistories,
|
||||
player: 'currentPlayer' in battles_regular.data ?
|
||||
(battles_regular.data as RegularBattleHistoriesRefetchResult<true>).currentPlayer : undefined,
|
||||
query: refresh ? RequestId.RegularBattleHistoriesRefetchQuery : RequestId.RegularBattleHistoriesQuery,
|
||||
query: battles_regular[RequestIdSymbol],
|
||||
be_version: battles_regular[ResponseSymbol].headers.get('x-be-version'),
|
||||
},
|
||||
bankaraBattleHistories: {
|
||||
result: battles_anarchy.data.bankaraBattleHistories,
|
||||
player: 'currentPlayer' in battles_anarchy.data ?
|
||||
(battles_anarchy.data as BankaraBattleHistoriesRefetchResult<true>).currentPlayer : undefined,
|
||||
query: refresh ? RequestId.BankaraBattleHistoriesRefetchQuery : RequestId.BankaraBattleHistoriesQuery,
|
||||
query: battles_anarchy[RequestIdSymbol],
|
||||
be_version: battles_anarchy[ResponseSymbol].headers.get('x-be-version'),
|
||||
},
|
||||
xBattleHistories: {
|
||||
result: battles_xmatch.data.xBattleHistories,
|
||||
player: 'currentPlayer' in battles_xmatch.data ?
|
||||
(battles_xmatch.data as XBattleHistoriesRefetchResult<true>).currentPlayer : undefined,
|
||||
query: battles_xmatch[RequestIdSymbol],
|
||||
be_version: battles_xmatch[ResponseSymbol].headers.get('x-be-version'),
|
||||
},
|
||||
privateBattleHistories: {
|
||||
result: battles_private.data.privateBattleHistories,
|
||||
player: 'currentPlayer' in battles_private.data ?
|
||||
|
|
@ -164,7 +171,7 @@ export async function dumpResults(
|
|||
debug('Writing %s', filename);
|
||||
await fs.writeFile(file, JSON.stringify({
|
||||
result: result.data.vsHistoryDetail,
|
||||
query: RequestId.VsHistoryDetailQuery,
|
||||
query: result[RequestIdSymbol],
|
||||
app_version: splatnet.version,
|
||||
be_version: result[ResponseSymbol].headers.get('x-be-version'),
|
||||
}, null, 4) + '\n', 'utf-8');
|
||||
|
|
@ -201,7 +208,7 @@ export async function dumpResults(
|
|||
debug('Writing %s', filename);
|
||||
await fs.writeFile(file, JSON.stringify({
|
||||
result: result.data.vsHistoryDetail,
|
||||
query: RequestId.VsHistoryDetailQuery,
|
||||
query: result[RequestIdSymbol],
|
||||
app_version: splatnet.version,
|
||||
be_version: result[ResponseSymbol].headers.get('x-be-version'),
|
||||
}, null, 4) + '\n', 'utf-8');
|
||||
|
|
@ -243,7 +250,7 @@ export async function dumpCoopResults(
|
|||
debug('Writing %s', filename);
|
||||
await fs.writeFile(file, JSON.stringify({
|
||||
result: results.data.coopResult,
|
||||
query: refresh ? RequestId.RefetchableCoopHistory_CoopResultQuery : RequestId.CoopHistoryQuery,
|
||||
query: results[RequestIdSymbol],
|
||||
app_version: splatnet.version,
|
||||
be_version: results[ResponseSymbol].headers.get('x-be-version'),
|
||||
}, null, 4) + '\n', 'utf-8');
|
||||
|
|
@ -272,7 +279,7 @@ export async function dumpCoopResults(
|
|||
debug('Writing %s', filename);
|
||||
await fs.writeFile(file, JSON.stringify({
|
||||
result: result.data.coopHistoryDetail,
|
||||
query: RequestId.CoopHistoryDetailQuery,
|
||||
query: result[RequestIdSymbol],
|
||||
app_version: splatnet.version,
|
||||
be_version: result[ResponseSymbol].headers.get('x-be-version'),
|
||||
}, null, 4) + '\n', 'utf-8');
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user