diff --git a/api/package.json b/api/package.json index b077adc3e..04e108585 100644 --- a/api/package.json +++ b/api/package.json @@ -115,6 +115,7 @@ "ini": "^5.0.0", "ip": "^2.0.1", "jose": "^6.0.0", + "json-bigint-patch": "^0.0.8", "lodash-es": "^4.17.21", "multi-ini": "^2.3.2", "mustache": "^4.2.0", diff --git a/api/src/cli.ts b/api/src/cli.ts index b4165e0eb..e84372137 100644 --- a/api/src/cli.ts +++ b/api/src/cli.ts @@ -1,4 +1,5 @@ import '@app/dotenv.js'; +import 'json-bigint-patch'; import { execa } from 'execa'; import { CommandFactory } from 'nest-commander'; diff --git a/api/src/index.ts b/api/src/index.ts index 2664ce643..4c272944d 100644 --- a/api/src/index.ts +++ b/api/src/index.ts @@ -1,5 +1,6 @@ import 'reflect-metadata'; import 'global-agent/bootstrap.js'; +import 'json-bigint-patch'; import '@app/dotenv.js'; import { type NestFastifyApplication } from '@nestjs/platform-fastify'; diff --git a/api/src/unraid-api/graph/graph.module.ts b/api/src/unraid-api/graph/graph.module.ts index 1eb87564d..06a666029 100644 --- a/api/src/unraid-api/graph/graph.module.ts +++ b/api/src/unraid-api/graph/graph.module.ts @@ -4,7 +4,7 @@ import { Module } from '@nestjs/common'; import { GraphQLModule } from '@nestjs/graphql'; import { NoUnusedVariablesRule } from 'graphql'; -import { JSONResolver, URLResolver } from 'graphql-scalars'; +import { GraphQLBigInt, JSONResolver, URLResolver } from 'graphql-scalars'; import { ENVIRONMENT } from '@app/environment.js'; import { getters } from '@app/store/index.js'; @@ -14,7 +14,6 @@ import { } from '@app/unraid-api/graph/directives/use-permissions.directive.js'; import { ResolversModule } from '@app/unraid-api/graph/resolvers/resolvers.module.js'; import { sandboxPlugin } from '@app/unraid-api/graph/sandbox-plugin.js'; -import { GraphQLLong } from '@app/unraid-api/graph/scalars/graphql-type-long.js'; import { PrefixedID as PrefixedIDScalar } from '@app/unraid-api/graph/scalars/graphql-type-prefixed-id.js'; import { PluginModule } from '@app/unraid-api/plugin/plugin.module.js'; @@ -50,7 +49,7 @@ import { PluginModule } from '@app/unraid-api/plugin/plugin.module.js'; }, resolvers: { JSON: JSONResolver, - Long: GraphQLLong, + Long: GraphQLBigInt, URL: URLResolver, }, buildSchemaOptions: { diff --git a/api/src/unraid-api/graph/resolvers/array/array.model.ts b/api/src/unraid-api/graph/resolvers/array/array.model.ts index e68d33f0d..3918542f1 100644 --- a/api/src/unraid-api/graph/resolvers/array/array.model.ts +++ b/api/src/unraid-api/graph/resolvers/array/array.model.ts @@ -1,9 +1,9 @@ import { Field, InputType, Int, ObjectType, registerEnumType } from '@nestjs/graphql'; import { IsEnum } from 'class-validator'; +import { GraphQLBigInt } from 'graphql-scalars'; import { Node } from '@app/unraid-api/graph/resolvers/base.model.js'; -import { GraphQLLong } from '@app/unraid-api/graph/scalars/graphql-type-long.js'; import { PrefixedID } from '@app/unraid-api/graph/scalars/graphql-type-prefixed-id.js'; @ObjectType() @@ -43,7 +43,7 @@ export class ArrayDisk extends Node { @Field(() => String, { nullable: true }) device?: string; - @Field(() => GraphQLLong, { description: '(KB) Disk Size total', nullable: true }) + @Field(() => GraphQLBigInt, { description: '(KB) Disk Size total', nullable: true }) size?: number | null; @Field(() => ArrayDiskStatus, { nullable: true }) @@ -58,40 +58,40 @@ export class ArrayDisk extends Node { }) temp?: number | null; - @Field(() => GraphQLLong, { + @Field(() => GraphQLBigInt, { nullable: true, description: 'Count of I/O read requests sent to the device I/O drivers. These statistics may be cleared at any time.', }) numReads?: number | null; - @Field(() => GraphQLLong, { + @Field(() => GraphQLBigInt, { nullable: true, description: 'Count of I/O writes requests sent to the device I/O drivers. These statistics may be cleared at any time.', }) numWrites?: number | null; - @Field(() => GraphQLLong, { + @Field(() => GraphQLBigInt, { nullable: true, description: 'Number of unrecoverable errors reported by the device I/O drivers. Missing data due to unrecoverable array read errors is filled in on-the-fly using parity reconstruct (and we attempt to write this data back to the sector(s) which failed). Any unrecoverable write error results in disabling the disk.', }) numErrors?: number | null; - @Field(() => GraphQLLong, { + @Field(() => GraphQLBigInt, { nullable: true, description: '(KB) Total Size of the FS (Not present on Parity type drive)', }) fsSize?: number | null; - @Field(() => GraphQLLong, { + @Field(() => GraphQLBigInt, { nullable: true, description: '(KB) Free Size on the FS (Not present on Parity type drive)', }) fsFree?: number | null; - @Field(() => GraphQLLong, { + @Field(() => GraphQLBigInt, { nullable: true, description: '(KB) Used Size on the FS (Not present on Parity type drive)', }) @@ -243,13 +243,13 @@ export class Share extends Node { @Field(() => String, { description: 'Display name', nullable: true }) name?: string | null; - @Field(() => GraphQLLong, { description: '(KB) Free space', nullable: true }) + @Field(() => GraphQLBigInt, { description: '(KB) Free space', nullable: true }) free?: number | null; - @Field(() => GraphQLLong, { description: '(KB) Used Size', nullable: true }) + @Field(() => GraphQLBigInt, { description: '(KB) Used Size', nullable: true }) used?: number | null; - @Field(() => GraphQLLong, { description: '(KB) Total size', nullable: true }) + @Field(() => GraphQLBigInt, { description: '(KB) Total size', nullable: true }) size?: number | null; @Field(() => [String], { description: 'Disks that are included in this share', nullable: true }) diff --git a/api/src/unraid-api/graph/resolvers/info/info.model.ts b/api/src/unraid-api/graph/resolvers/info/info.model.ts index d0271659b..4002d38b4 100644 --- a/api/src/unraid-api/graph/resolvers/info/info.model.ts +++ b/api/src/unraid-api/graph/resolvers/info/info.model.ts @@ -8,7 +8,7 @@ import { registerEnumType, } from '@nestjs/graphql'; -import { GraphQLJSON } from 'graphql-scalars'; +import { GraphQLBigInt, GraphQLJSON } from 'graphql-scalars'; import { Node } from '@app/unraid-api/graph/resolvers/base.model.js'; import { ThemeName } from '@app/unraid-api/graph/resolvers/customization/theme.model.js'; @@ -290,7 +290,7 @@ export class Display extends Node { @ObjectType({ implements: () => Node }) export class MemoryLayout extends Node { - @Field(() => Int) + @Field(() => GraphQLBigInt) size!: number; @Field(() => String, { nullable: true }) @@ -326,34 +326,34 @@ export class MemoryLayout extends Node { @ObjectType({ implements: () => Node }) export class InfoMemory extends Node { - @Field(() => Int) + @Field(() => GraphQLBigInt) max!: number; - @Field(() => Int) + @Field(() => GraphQLBigInt) total!: number; - @Field(() => Int) + @Field(() => GraphQLBigInt) free!: number; - @Field(() => Int) + @Field(() => GraphQLBigInt) used!: number; - @Field(() => Int) + @Field(() => GraphQLBigInt) active!: number; - @Field(() => Int) + @Field(() => GraphQLBigInt) available!: number; - @Field(() => Int) + @Field(() => GraphQLBigInt) buffcache!: number; - @Field(() => Int) + @Field(() => GraphQLBigInt) swaptotal!: number; - @Field(() => Int) + @Field(() => GraphQLBigInt) swapused!: number; - @Field(() => Int) + @Field(() => GraphQLBigInt) swapfree!: number; @Field(() => [MemoryLayout]) diff --git a/api/src/unraid-api/graph/scalars/graphql-type-long.ts b/api/src/unraid-api/graph/scalars/graphql-type-long.ts deleted file mode 100644 index e2e45c15b..000000000 --- a/api/src/unraid-api/graph/scalars/graphql-type-long.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type { ASTNode } from 'graphql'; -import { GraphQLScalarType } from 'graphql'; -import { Kind } from 'graphql/language/index.js'; - -const MAX_LONG = Number.MAX_SAFE_INTEGER; -const MIN_LONG = Number.MIN_SAFE_INTEGER; - -const coerceLong = (value) => { - if (value === '') - throw new TypeError('Long cannot represent non 52-bit signed integer value: (empty string)'); - const num = Number(value); - if (num == num && num <= MAX_LONG && num >= MIN_LONG) { - if (num < 0) { - return Math.ceil(num); - } - return Math.floor(num); - } - throw new TypeError('Long cannot represent non 52-bit signed integer value: ' + String(value)); -}; - -const parseLiteral = (ast: ASTNode) => { - if (ast.kind === Kind.INT) { - const num = parseInt(ast.value, 10); - if (num <= MAX_LONG && num >= MIN_LONG) return num; - } - return null; -}; - -export const GraphQLLong = new GraphQLScalarType({ - name: 'Long', - description: 'The `Long` scalar type represents 52-bit integers', - serialize: coerceLong, - parseValue: coerceLong, - parseLiteral: parseLiteral, -}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7613ad7ff..f61bb3022 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -222,6 +222,9 @@ importers: jose: specifier: ^6.0.0 version: 6.0.10 + json-bigint-patch: + specifier: ^0.0.8 + version: 0.0.8 lodash-es: specifier: ^4.17.21 version: 4.17.21 @@ -8285,6 +8288,9 @@ packages: engines: {node: '>=6'} hasBin: true + json-bigint-patch@0.0.8: + resolution: {integrity: sha512-xa0LTQsyaq8awYyZyuUsporWisZFiyqzxGW8CKM3t7oouf0GFAKYJnqAm6e9NLNBQOCtOLvy614DEiRX/rPbnA==} + json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} @@ -20855,6 +20861,8 @@ snapshots: jsesc@3.1.0: {} + json-bigint-patch@0.0.8: {} + json-buffer@3.0.1: {} json-parse-better-errors@1.0.2: {}