Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ scalar BigInt

scalar Long

scalar SafeInt

scalar GUID

scalar HexColorCode
Expand Down Expand Up @@ -125,6 +127,7 @@ import {
URLResolver,
BigIntResolver,
LongResolver,
SafeIntResolver,
GUIDResolver,
HexColorCodeResolver,
HSLResolver,
Expand Down Expand Up @@ -168,6 +171,7 @@ const myResolverMap = {
UnsignedInt: UnsignedIntResolver,
BigInt: BigIntResolver,
Long: LongResolver,
SafeInt: SafeIntResolver,

EmailAddress: EmailAddressResolver,
URL: URLResolver,
Expand Down Expand Up @@ -603,6 +607,10 @@ GraphQLError: Argument "num" has invalid value 9007199254740990.
In order to support `BigInt` in `JSON.parse` and `JSON.stringify`, it is recommended to install this npm package together with this scalar. Otherwise, JavaScript will serialize the value as string.
[json-bigint-patch](https://github.com/ardatan/json-bigint-patch)

### SafeInt

This scalar behaves just like the native GraphQLInt scalar, but it allows integers that require more than 32-bits. Any integer that is considered "safe" in JavaScript (i.e. ± 9,007,199,254,740,991) is considered a valid value.

### GUID

A field whose value is a generic [Globally Unique Identifier](https://en.wikipedia.org/wiki/Universally_unique_identifier).
Expand Down
6 changes: 6 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
GraphQLBigInt,
GraphQLByte,
GraphQLLong,
GraphQLSafeInt,
GraphQLGUID,
GraphQLHexadecimal,
GraphQLHexColorCode,
Expand Down Expand Up @@ -67,6 +68,7 @@ export {
BigInt as BigIntTypeDefinition,
Byte as ByteTypeDefinition,
Long as LongTypeDefinition,
SafeInt as SafeIntDefinition,
GUID as GUIDDefinition,
Hexadecimal as HexadecimalTypeDefinition,
HexColorCode as HexColorCodeDefinition,
Expand Down Expand Up @@ -113,6 +115,7 @@ export {
GraphQLBigInt as BigIntResolver,
GraphQLByte as ByteResolver,
GraphQLLong as LongResolver,
GraphQLSafeInt as SafeIntResolver,
GraphQLGUID as GUIDResolver,
GraphQLHexadecimal as HexadecimalResolver,
GraphQLHexColorCode as HexColorCodeResolver,
Expand Down Expand Up @@ -157,6 +160,7 @@ export const resolvers = {
BigInt: GraphQLBigInt,
Byte: GraphQLByte,
Long: GraphQLLong,
SafeInt: GraphQLSafeInt,
GUID: GraphQLGUID,
Hexadecimal: GraphQLHexadecimal,
HexColorCode: GraphQLHexColorCode,
Expand Down Expand Up @@ -201,6 +205,7 @@ export {
BigInt as BigIntMock,
Byte as ByteMock,
Long as LongMock,
SafeInt as SafeIntMock,
GUID as GUIDMock,
Hexadecimal as HexadecimalMock,
HexColorCode as HexColorCodeMock,
Expand Down Expand Up @@ -249,6 +254,7 @@ export {
GraphQLBigInt,
GraphQLByte,
GraphQLLong,
GraphQLSafeInt,
GraphQLGUID,
GraphQLHexadecimal,
GraphQLHexColorCode,
Expand Down
1 change: 1 addition & 0 deletions src/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export const JSON = () => ({});
export const JSONObject = () => ({});
export const IBAN = () => 'NL55INGB4789170233';
export const Void = (): null => null;
export const SafeInt = () => Number.MAX_SAFE_INTEGER;

export {
DateMock as Date,
Expand Down
82 changes: 82 additions & 0 deletions src/scalars/SafeInt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import {
GraphQLError,
GraphQLScalarType,
GraphQLScalarTypeConfig,
Kind,
print,
} from 'graphql';

// eslint-disable-next-line @typescript-eslint/ban-types
function isObjectLike(value: any): value is Object {
return typeof value === 'object' && value !== null;
}

function serializeObject(outputValue: any): any {
if (isObjectLike(outputValue)) {
if (typeof outputValue.valueOf === 'function') {
const valueOfResult = outputValue.valueOf();
if (!isObjectLike(valueOfResult)) {
return valueOfResult;
}
}
if (typeof outputValue.toJSON === 'function') {
return outputValue.toJSON();
}
}
return outputValue;
}

function serializeSafeIntValue(outputValue: any): number {
const coercedValue = serializeObject(outputValue);

if (typeof coercedValue === 'boolean') {
return coercedValue ? 1 : 0;
}

let num = coercedValue;
if (typeof coercedValue === 'string' && coercedValue !== '') {
num = Number(coercedValue);
}

if (!Number.isSafeInteger(num)) {
throw new GraphQLError(
`SafeInt cannot represent non-safe-integer value: ${num}`,
);
}
return num;
}

function parseSafeIntValue(inputValue: any): number {
if (!Number.isSafeInteger(inputValue)) {
throw new GraphQLError(
`SafeInt cannot represent non-safe-integer value: ${inputValue}`,
);
}
return inputValue;
}

export const GraphQLSafeIntConfig: GraphQLScalarTypeConfig<
number | string,
number
> = {
name: 'SafeInt',
description:
'The `SafeInt` scalar type represents non-fractional signed whole numeric values that are ' +
'considered safe as defined by the ECMAScript specification.',
specifiedByUrl:
'https://www.ecma-international.org/ecma-262/#sec-number.issafeinteger',
serialize: serializeSafeIntValue,
parseValue: parseSafeIntValue,
parseLiteral(ast) {
if (ast.kind !== Kind.INT) {
throw new GraphQLError(
`SafeInt cannot represent non-integer value: ${print(ast)}`,
ast,
);
}
const num = parseInt(ast.value, 10);
return parseSafeIntValue(num);
},
};

export const GraphQLSafeInt = new GraphQLScalarType(GraphQLSafeIntConfig);
1 change: 1 addition & 0 deletions src/scalars/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export { GraphQLURL } from './URL';
export { GraphQLBigInt } from './BigInt';
export { GraphQLByte } from './Byte';
export { GraphQLLong } from './Long';
export { GraphQLSafeInt } from './SafeInt';
export { GraphQLGUID } from './GUID';
export { GraphQLHexadecimal } from './Hexadecimal';
export { GraphQLHexColorCode } from './HexColorCode';
Expand Down
2 changes: 2 additions & 0 deletions src/typeDefs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export const PositiveInt = 'scalar PositiveInt';
export const PostalCode = 'scalar PostalCode';
export const RGB = `scalar RGB`;
export const RGBA = `scalar RGBA`;
export const SafeInt = `scalar SafeInt`;
export const URL = 'scalar URL';
export const USCurrency = `scalar USCurrency`;
export const Currency = `scalar Currency`;
Expand Down Expand Up @@ -77,6 +78,7 @@ export const typeDefs = [
Port,
RGB,
RGBA,
SafeInt,
USCurrency,
Currency,
JSON,
Expand Down
Loading