Skip to content

Commit

Permalink
(MongoDB) ObjectID Scalar Type/Commit message convention (Urigo#243)
Browse files Browse the repository at this point in the history
* feat(objectid-scalar): mongodb object id scalar type

Adds mongodb object id scalar type.

* style(editorconfig): editorconfig to help format code

Adds [editorconfig](https://editorconfig.org/) to helps maintain coding style for developers.

* style(commitlint): git commit message linting

Enforces commit message standards on subsequent contributors to this project.

* docs(mongodb-objectid): documents the usage of the mongodb objectid

Documents the usage of the mongodb objectid scalar type.

* feat(mongodb-objectid): mongodb objectid scalar type

Adds mongodb objectid scalar type

* feat(mongodb-objectid): mongodb objectid scalar type

Adds a mongodb objectid scalar type definition to the already existing list of definitions.

* conflict resolution (Urigo#1)

package.json rebased

* feat(objectid-scalar): mongodb object id scalar type

Adds mongodb object id scalar type.

* docs(mongodb-objectid): documents the usage of the mongodb objectid

Documents the usage of the mongodb objectid scalar type.

* git rebase (Urigo#2)

conflict resolution -package.json

* feat(objectid-scalar): mongodb object id scalar type

Adds mongodb object id scalar type.

* style(editorconfig): editorconfig to help format code

Adds [editorconfig](https://editorconfig.org/) to helps maintain coding style for developers.

* style(commitlint): git commit message linting

Enforces commit message standards on subsequent contributors to this project.

* docs(mongodb-objectid): documents the usage of the mongodb objectid

Documents the usage of the mongodb objectid scalar type.

* feat(mongodb-objectid): mongodb objectid scalar type

Adds a mongodb objectid scalar type definition to the already existing list of definitions.

* build: remove package-lock.json
  • Loading branch information
toondaey authored Mar 12, 2020
1 parent 5cfbd90 commit 4e3a278
Show file tree
Hide file tree
Showing 11 changed files with 197 additions and 14 deletions.
8 changes: 8 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
## General
[*]
indent_style=space
indent_size=2
end_of_line=lf
charset=utf-8
trim_trailing_whitespace=true
insert_final_newline=true
9 changes: 9 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Issues and Pull Requests are always welcome.

Please read OK Grow's global [contribution guidelines](https://github.com/okgrow/guides/blob/master/open-source/contributing.md).

If you are interested in becoming a maintainer, get in touch with us by sending an email or opening an issue. You should already have code merged into the project. Active contributors are encouraged to get in touch.

Please note that all interactions in @okgrow's repos should follow our [Code of Conduct](https://github.com/okgrow/guides/blob/master/open-source/CODE_OF_CONDUCT.md).

All commit messages should follow the [conventional commit](https://www.conventionalcommits.org/en/v1.0.0/) message guidelines. In order to assist with this you can run `npm run-scripts commit` as a command has been added to the scripts section of the `package.json` file which will help guide formulation of a proper commit message.
27 changes: 18 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ scalar UnsignedInt

scalar URL

scalar ObjectID

scalar BigInt

scalar Long
Expand Down Expand Up @@ -126,13 +128,16 @@ import {
USCurrencyResolver,
JSONResolver,
JSONObjectResolver,
ObjectIDResolver,
} from 'graphql-scalars';
```

Then make sure they're in the root resolver map like this:

```javascript
const myResolverMap = {
ObjectID: ObjectIDResolver,

DateTime: DateTimeResolver,

NonPositiveInt: NonPositiveIntResolver,
Expand All @@ -147,27 +152,27 @@ const myResolverMap = {
UnsignedInt: UnsignedIntResolver,
BigInt: BigIntResolver,
Long: LongResolver,

EmailAddress: EmailAddressResolver,
URL: URLResolver,
PhoneNumber: PhoneNumberResolver,
PostalCode: PostalCodeResolver,

GUID: GUIDResolver,

HexColorCode: HexColorCodeResolver,
HSL: HSLResolver,
HSLA: HSLAResolver,
RGB: RGBResolver,
RGBA: RGBAResolver,

IPv4: IPv4Resolver,
IPv6: IPv6Resolver,
MAC: MACResolver,
Port: PortResolver,

ISBN: ISBNResolver,

USCurrency: USCurrencyResolver,
JSON: JSONResolver,
JSONObject: JSONObjectResolver,
Expand Down Expand Up @@ -482,6 +487,10 @@ The very powerful
_that_ format, parse and display it in whatever display format you want. It can also be used to
parse user input and _get_ the E.164 format to pass _into_ a schema.

### ObjectID

A field whose value conforms to the mongodb object id format as explained in the [documentation](https://docs.mongodb.com/manual/reference/method/ObjectId/#ObjectId)

### PostalCode

We're going to start with a limited set as suggested [here](http://www.pixelenvision.com/1708/zip-postal-code-validation-regex-php-code-for-12-countries/)
Expand Down Expand Up @@ -509,7 +518,7 @@ In the future we might expand this list and use the more comprehensive list foun

### BigInt

A long integer type for [graphql-js](https://github.com/graphql/graphql-js). This implementation gives you more than 32 bits rather than the default 32-bit GraphQLInt. [It uses native `BigInt` implementation of JavaScript.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt)
A long integer type for [graphql-js](https://github.com/graphql/graphql-js). This implementation gives you more than 32 bits rather than the default 32-bit GraphQLInt. [It uses native `BigInt` implementation of JavaScript.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt)
The [GraphQL spec](https://facebook.github.io/graphql/#sec-Int) limits its Int type to 32-bits. Maybe you've seen this error before:
[Issue on graphql-js](https://github.com/graphql/graphql-js/issues/292)
```
Expand Down Expand Up @@ -704,13 +713,13 @@ can use them too if needed.

## License

Released under the [MIT license](https://github.com/Urigo/graphql-scalars/blob/master/LICENSE).
Released under the [MIT license](./LICENSE).

## Contributing

Issues and Pull Requests are always welcome.

Please read our [contribution guidelines](https://github.com/Urigo/graphql-scalars/blob/master/CONTRIBUTING.md).
Please read our [contribution guidelines](./CONTRIBUTING.md).

## Thanks

Expand Down
3 changes: 3 additions & 0 deletions commitlint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
extends: ['@commitlint/config-conventional'],
};
17 changes: 14 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,19 @@
"src"
]
},
"husky": {
"hooks": {
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
},
"prettier": {
"singleQuote": true,
"trailingComma": "all",
"printWidth": 80
},
"dependencies": {},
"scripts": {
"commit": "commit",
"clean": "rm -rf dist",
"prebuild": "yarn clean",
"prepack": "",
Expand All @@ -37,18 +43,23 @@
"bundlesize": "yarn build && cd bundle-test/ && yarn && yarn test"
},
"devDependencies": {
"@types/node": "13.9.0",
"@ardatan/bob": "0.2.7",
"@commitlint/cli": "8.3.5",
"@commitlint/config-conventional": "8.3.4",
"@commitlint/prompt-cli": "8.3.5",
"@types/node": "13.9.0",
"@types/jest": "25.1.4",
"graphql": "14.6.0",
"graphql-tools": "4.0.7",
"husky": "4.2.3",
"jest": "25.1.0",
"lint-staged": "10.0.8",
"merge-graphql-schemas": "1.7.6",
"semver": "7.1.3",
"ts-jest": "25.2.1",
"tslint": "6.1.0",
"typescript": "3.8.3"
"typescript": "3.8.3",
"yarn": "1.22.0"
},
"peerDependencies": {
"graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0"
Expand All @@ -72,4 +83,4 @@
"resolutions": {
"set-value": "3.0.1"
}
}
}
3 changes: 3 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export {
JSON as JSONDefinition,
JSONObject as JSONObjectDefinition,
IBAN as IBANTypeDefinition,
ObjectID as ObjectIDTypeDefinition
} from './typeDefs';

export { default as typeDefs } from './typeDefs';
Expand Down Expand Up @@ -70,6 +71,7 @@ export {
JSON as JSONResolver,
JSONObject as JSONObjectResolver,
IBAN as IBANResolver,
ObjectID as ObjectIDResolver,
} from './resolvers';

import * as resolvers from './resolvers';
Expand Down Expand Up @@ -111,6 +113,7 @@ export {
JSON as JSONMock,
JSONObject as JSONObjectMock,
IBAN as IBANMock,
ObjectID as ObjectIDMock
} from './mocks';

export { mocks };
Expand Down
1 change: 1 addition & 0 deletions src/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const NonNegativeInt = () => 123;
export const NonPositiveFloat = () => -123.45;
export const NonPositiveInt = () => -123;
export const PhoneNumber = () => '+17895551234';
export const ObjectID = () => '5e5677d71bdc2ae76344968c';
export const PositiveFloat = () => 123.45;
export const PositiveInt = () => 123;
export const PostalCode = () => '60031';
Expand Down
41 changes: 41 additions & 0 deletions src/resolvers/ObjectID.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { ValueNode } from 'graphql/language';
import { Kind, GraphQLError, GraphQLScalarType } from 'graphql';

const MONGODB_OBJECTID_REGEX: RegExp = new RegExp(/^[A-Fa-f0-9]{24}$/);

export default new GraphQLScalarType({
name: 'ObjectID',

description:
'A field whose value conforms with the standard mongodb object ID as described here: https://docs.mongodb.com/manual/reference/method/ObjectId/#ObjectId. Example: 5e5677d71bdc2ae76344968c',

serialize(value: string) {
if (!MONGODB_OBJECTID_REGEX.test(value)) {
throw new TypeError(`Value is not a valid mongodb object id of form: ${value}`);
}

return value;
},

parseValue(value: string) {
if (!MONGODB_OBJECTID_REGEX.test(value)) {
throw new TypeError(`Value is not a valid mongodb object id of form: ${value}`);
}

return value;
},

parseLiteral(ast: ValueNode) {
if (ast.kind !== Kind.STRING) {
throw new GraphQLError(
`Can only validate strings as mongodb object id but got a: ${ast.kind}`,
);
}

if (!MONGODB_OBJECTID_REGEX.test(ast.value)) {
throw new TypeError(`Value is not a valid mongodb object id of form: ${ast.value}`);
}

return ast.value;
},
});
4 changes: 3 additions & 1 deletion src/resolvers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import RGBA from './RGBA';
import USCurrency from './USCurrency';
import { JSON, JSONObject } from './JSON';
import IBAN from './IBAN';
import ObjectID from './ObjectID';

const BigIntResolver = BigIntFactory('BigInt');
const LongResolver = BigIntFactory('Long');
Expand Down Expand Up @@ -70,5 +71,6 @@ export {
USCurrency,
JSON,
JSONObject,
IBAN
IBAN,
ObjectID,
};
4 changes: 3 additions & 1 deletion src/typeDefs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const USCurrency = `scalar USCurrency`;
export const UnsignedFloat = 'scalar UnsignedFloat';
export const UnsignedInt = 'scalar UnsignedInt';
export const Long = 'scalar Long';
export const ObjectID = 'scalar ObjectID';

export default [
DateTime,
Expand Down Expand Up @@ -66,5 +67,6 @@ export default [
USCurrency,
JSON,
JSONObject,
IBAN
IBAN,
ObjectID,
];
94 changes: 94 additions & 0 deletions tests/ObjectID.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/* global describe, test, expect */

import { Kind } from 'graphql/language';

import ObjectID from '../src/resolvers/ObjectID';

describe('ObjectId', () => {
describe('valid', () => {
test('serialize', () => {
expect(ObjectID.serialize('5e5677d71bdc2ae76344968c')).toBe('5e5677d71bdc2ae76344968c');
});

test('parseValue', () => {
expect(ObjectID.parseValue('5e5677d71bdc2ae76344968c')).toBe('5e5677d71bdc2ae76344968c');
});

test('parseLiteral', () => {
expect(
ObjectID.parseLiteral({ value: '5e5677d71bdc2ae76344968c', kind: Kind.STRING }, undefined), // undefined as prescribed by the Maybe<T> type
).toBe('5e5677d71bdc2ae76344968c');
});
});

describe('invalid', () => {
describe('not a mongodb object id', () => {
test('serialize', () => {
const invalid = '5e5677d71bdc2ae76344968z';
expect(() => ObjectID.serialize(invalid)).toThrow(
new RegExp(`Value is not a valid mongodb object id of form: ${invalid}`),
);
});

test('parseValue', () => {
const invalid = '5e5677d71bdc2ae76344968z';
expect(() => ObjectID.parseValue(invalid)).toThrow(
new RegExp(`Value is not a valid mongodb object id of form: ${invalid}`),
);
});

test('parseLiteral', () => {
const invalid = '5e5677d71bdc2ae76344968z';
expect(() =>
ObjectID.parseLiteral({ value: invalid, kind: Kind.STRING }, undefined), // undefined as prescribed by the Maybe<T> type
).toThrow(new RegExp(`Value is not a valid mongodb object id of form: ${invalid}`));
});
});

describe('too short', () => {
test('serialize', () => {
const invalid = '5e5677d71bdc2ae';
expect(() => ObjectID.serialize(invalid)).toThrow(
new RegExp(`Value is not a valid mongodb object id of form: ${invalid}`),
);
});

test('parseValue', () => {
const invalid = '5e5677d71bdc2ae';
expect(() => ObjectID.parseValue(invalid)).toThrow(
new RegExp(`Value is not a valid mongodb object id of form: ${invalid}`),
);
});

test('parseLiteral', () => {
const invalid = '5e5677d71bdc2ae';
expect(() =>
ObjectID.parseLiteral({ value: invalid, kind: Kind.STRING }, undefined), // undefined as prescribed by the Maybe<T> type
).toThrow(new RegExp(`Value is not a valid mongodb object id of form: ${invalid}`));
});
});

describe('too long', () => {
test('serialize', () => {
const invalid = '5e5677d71bdc2ae76344968c5';
expect(() => ObjectID.serialize(invalid)).toThrow(
new RegExp(`Value is not a valid mongodb object id of form: ${invalid}`),
);
});

test('parseValue', () => {
const invalid = '5e5677d71bdc2ae76344968c5';
expect(() => ObjectID.parseValue(invalid)).toThrow(
new RegExp(`Value is not a valid mongodb object id of form: ${invalid}`),
);
});

test('parseLiteral', () => {
const invalid = '5e5677d71bdc2ae76344968c5';
expect(() =>
ObjectID.parseLiteral({ value: invalid, kind: Kind.STRING }, undefined), // undefined as prescribed by the Maybe<T> type
).toThrow(new RegExp(`Value is not a valid mongodb object id of form: ${invalid}`));
});
});
});
});

0 comments on commit 4e3a278

Please sign in to comment.