{"_id":"@ambler/graphql-shield","_rev":"1-c11149f20fd308e1f76c5eac2fb2da35","name":"@ambler/graphql-shield","dist-tags":{"latest":"2.2.7-ambler.0"},"versions":{"2.2.7-ambler.0":{"name":"@ambler/graphql-shield","description":"GraphQL Server permissions as another layer of abstraction!","version":"2.2.7-ambler.0","main":"dist/index.js","typings":"dist/index.d.ts","author":{"name":"Matic Zavadlal","email":"matic.zavadlal@gmail.com"},"scripts":{"prepublish":"npm run test","build":"rimraf dist && tsc -d","lint":"tslint --project tsconfig.json {src}/**/*.ts","test":"npm run lint && npm run build && ava --verbose","semantic-release":"semantic-release","postinstall":"opencollective postinstall"},"dependencies":{"object-hash":"^1.3.0","opencollective":"1.0.3"},"devDependencies":{"@types/graphql":"0.13.4","@types/node":"9.6.27","@types/object-hash":"1.2.0","ava":"0.25.0","graphql":"0.13.2","graphql-middleware":"1.4.2","graphql-tools":"3.0.5","prettier":"1.13.7","prettier-check":"2.0.0","rimraf":"2.6.2","semantic-release":"15.5.5","tslint":"5.10.0","tslint-config-prettier":"1.13.0","tslint-config-standard":"7.0.0","typescript":"2.9.2"},"peerDependencies":{"graphql":"^0.11.0 || ^0.12.0 || ^0.13.0","graphql-middleware":"^1.3.2"},"release":{"branch":"master"},"homepage":"https://github.com/maticzav/graphql-shield","repository":{"type":"git","url":"https://github.com/maticzav/graphql-shield.git"},"bugs":{"url":"https://github.com/maticzav/graphql-shield/issues"},"keywords":["graphql","permissions","shield","server"],"license":"MIT","collective":{"type":"opencollective","url":"https://opencollective.com/graphql-shield","logo":"https://opencollective.com/graphql-shield/logo.txt"},"_id":"@ambler/graphql-shield@2.2.7-ambler.0","dist":{"shasum":"c1a14cc7599ba8ee56b439e6ccffce11ae697d93","integrity":"sha512-Z+5Mset9tL009jXCXMKdJ2wTIdu1vzV6rFFkQpk5caTZ5y7GdIvfq6mJOnd19cb0ibSxvjNr4opCNejaQqsDUA==","tarball":"https://registry.npmjs.org/@ambler/graphql-shield/-/graphql-shield-2.2.7-ambler.0.tgz","fileCount":10,"unpackedSize":35078,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIBlWAk2CZBRDMlWEBmlDNnlFmFU3CpEoxz4vl8f7ba1WAiEA8Fw7ul3fN1kqMyhXjey1nkOhoj0Q89P9VX/MbnkdYjU="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJihmI6ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmq5TQ/+IVXHoH3b4tdwCwjIoRkagsv4rMj/H5r/1VmhyOEnelmA0Y8r\r\nk2NHJz3O81EmmSprlfmdBQKbeI8JRSics+d+j++yI7mXB7OK1K/TdVZbqYPp\r\nwOiOwOG/bjIuHGSTYZ22Ze9A9OACZpkaWCSmY4gXo1YZWOlazZ2fPhqM9gJQ\r\nLsa6Z9nb7LnY6ab1V0H1Cwm01XjYB3veRGXFJL0ERseOScfKascvMXHFs06h\r\nLG0ocu/Pv7QuTRXo040XUcDdcscrky450t4enoynErGiIBsZtzd/Ltc1So2a\r\nFM1lVJg110YsdAa1Ih74Be613Ay8wmBmaSoINBWNIzw8Oy3IrhRZQn9wtuwh\r\nKqARLPd4MLBhd+/UyTCWNNnyVA8LRk6I3ltfkaJlhlwZ9AGZJbeDAwiY7Dv+\r\nxyjv/0qzpelmq72e3rU6oDrIYc8dklNTPvXqhUSu3N+MGN5/aVpNLLlo6hL0\r\nd4tQN2cNo3nVFmsaeErGXJnhNnoiDxCp/t2S/ZNtIG0RIQ8Sfo5cBVz18Afl\r\nm6z5WQbqeZcOqMZtQsYZl1n6aig+XR1Zhq4QrW/EOoaA+01yjBwVuUxNLwSL\r\nTKdaWnlnA+tLARk86T9iL8uP9fxFsHjPBMSf36P67AVqnTPABWb7WZ9E7r3J\r\n60RU2IiczQPENydpjU3ggyBM69WIkjJtCYY=\r\n=zxrj\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"chabou","email":"chabup@delean.fr"},"directories":{},"maintainers":[{"name":"chabou","email":"chabup@delean.fr"},{"name":"nbarray","email":"nbarray@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/graphql-shield_2.2.7-ambler.0_1652974138444_0.8362594759560493"},"_hasShrinkwrap":false}},"time":{"created":"2022-05-19T15:28:58.275Z","2.2.7-ambler.0":"2022-05-19T15:28:58.588Z","modified":"2022-05-19T19:03:46.646Z"},"maintainers":[{"email":"seb91.lm@gmail.com","name":"rhaven"},{"email":"chabup@delean.fr","name":"chabou"},{"email":"nbarray@gmail.com","name":"nbarray"}],"description":"GraphQL Server permissions as another layer of abstraction!","homepage":"https://github.com/maticzav/graphql-shield","keywords":["graphql","permissions","shield","server"],"repository":{"type":"git","url":"https://github.com/maticzav/graphql-shield.git"},"author":{"name":"Matic Zavadlal","email":"matic.zavadlal@gmail.com"},"bugs":{"url":"https://github.com/maticzav/graphql-shield/issues"},"license":"MIT","readme":"<p align=\"center\"><img src=\"https://imgur.com/DX1VKtn.png\" width=\"150\" /></p>\n\n# graphql-shield\n\n[![CircleCI](https://circleci.com/gh/maticzav/graphql-shield/tree/master.svg?style=shield)](https://circleci.com/gh/maticzav/graphql-shield/tree/master) [![npm version](https://badge.fury.io/js/graphql-shield.svg)](https://badge.fury.io/js/graphql-shield)\n[![Backers on Open Collective](https://opencollective.com/graphql-shield/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/graphql-shield/sponsors/badge.svg)](#sponsors)\n\n> GraphQL Server permissions as another layer of abstraction!\n\n## Overview\n\nGraphQL Shield helps you create a permission layer for your application. Using an intuitive rule-API, you'll gain the power of the shield engine on every request and reduce the load time of every request with smart caching. This way you can make sure your application will remain quick, and no internal data will be exposed.\n\n[![Sponsored By GraphCMS](https://github.com/maticzav/graphql-shield/raw/master/media/graphcms.svg?sanitize=true)](https://graphcms.com/?ref=maticzav)\n\nTry building a groceries shop to better understand the benefits of GraphQL Shield! [Banana &Co.](https://medium.com/@maticzavadlal/graphql-shield-9d1e02520e35) 🍏🍌🍓.\n\n## Features\n\n* ✂️ **Flexible:** Based on [GraphQL Middleware](https://github.com/prismagraphql/graphql-middleware).\n* 😌 **Easy to use:** Just add permissions to your [Yoga](https://github.com/prismagraphql/graphql-yoga) `middlewares` set, and you are ready to go!\n* 🤝 **Compatible:** Works with all GraphQL Servers.\n* 🚀 **Smart:** Intelligent V8 Shield engine caches all your request to prevent any unnecessary load.\n* 🎯 **Per-Type:** Write permissions for your schema, types or specific fields (check the example below).\n* 💯 **Tested:** Very well [tested](https://github.com/maticzav/graphql-shield/tree/master/test.js) functionalities!\n\n## Install\n\n```bash\nyarn add graphql-shield\n```\n\n## Example\n\n### GraphQL Yoga\n\n```ts\nimport { GraphQLServer } from 'graphql-yoga'\nimport { rule, shield, and, or, not } from 'graphql-shield'\n\nconst typeDefs = `\n  type Query {\n    frontPage: [Fruit!]!\n    fruits: [Fruit!]!\n    customers: [Customer!]!\n  }\n\n  type Mutation {\n    addFruitToBasket: Boolean!\n  }\n\n  type Fruit {\n    name: String!\n    count: Int!\n  }\n\n  type Customer {\n    id: ID!\n    basket: [Fruit!]!\n  }\n`\n\nconst resolvers = {\n  Query: {\n    frontPage: () => [{name: \"orange\", count: 10}, {name: \"apple\", count: 1}]\n  }\n}\n\n// Auth\n\nconst users = {\n  mathew: {\n    id: 1,\n    name: \"Mathew\",\n    role: \"admin\"\n  },\n  george: {\n    id: 2,\n    name: \"George\",\n    role: \"editor\"\n  },\n  johnny: {\n    id: 3,\n    name: \"Johnny\",\n    role: \"customer\"\n  }\n}\n\nfunction getUser(req) {\n  const auth = req.get('Authorization')\n  if (users[auth]) {\n    return users[auth]\n  } else {\n    return null\n  }\n}\n\n// Rules\n\nconst isAuthenticated = rule()(async (parent, args, ctx, info) => {\n  return ctx.user !== null\n})\n\nconst isAdmin = rule()(async (parent, args, ctx, info) => {\n  return ctx.user.role === 'admin'\n})\n\nconst isEditor = rule()(async (parent, args, ctx, info) => {\n  return ctx.user.role === 'editor'\n})\n\n\n// Permissions\n\nconst permissions = shield({\n  Query: {\n    frontPage: not(isAuthenticated),\n    fruits: and(isAuthenticated, or(isAdmin, isEditor)),\n    customers: and(isAuthenticated, isAdmin)\n  },\n  Mutation: {\n    addFruitToBasket: isAuthenticated,\n  },\n  Fruit: isAuthenticated,\n  Customer: isAdmin\n})\n\nconst server = GraphQLServer({\n  typeDefs,\n  resolvers,\n  middlewares: [permissions],\n  context: req => ({\n    ...req,\n    user: getUser(req)\n  })\n})\n\nserver.start(() => console.log('Server is running on http://localhost:4000'))\n```\n\n### Others\n\n```ts\n// Permissions...\n\n// Apply permissions middleware with applyMiddleware\n// Giving any schema (instance of GraphQLSchema)\n\nimport { applyMiddleware } from 'graphql-middleware';\n// schema definition...\nschema = applyMiddleware(schema, permissions);\n```\n\n## API\n\n### Types\n\n```ts\n// Rule\nfunction rule(name?: string, options?: IRuleOptions)(func: IRuleFunction): Rule\n\ntype IRuleFunction = (\n  parent: any,\n  args: any,\n  context: any,\n  info: GraphQLResolveInfo,\n) => Promise<boolean>\n\nexport type ICache = 'strict' | 'contextual' | 'no_cache'\n\nexport interface IRuleOptions {\n  cache?: ICache\n}\n\n// Logic\nfunction and(...rules: IRule[]): LogicRule\nfunction or(...rules: IRule[]): LogicRule\nfunction not(rule: IRule): LogicRule\n\n// Predefined rules\nconst allow: Rule\nconst deny: Rule\n\ntype IRule = Rule | LogicRule\n\ninterface IRuleFieldMap {\n  [key: string]: IRule\n}\n\ninterface IRuleTypeMap {\n  [key: string]: IRule | IRuleFieldMap\n}\n\ntype IRules = IRule | IRuleTypeMap\n\nfunction shield(rules?: IRules, options?: IOptions): IMiddleware\n\nexport interface IOptions {\n  debug?: boolean\n  allowExternalErrors?: boolean\n}\n```\n\n### `shield(rules?, options?)`\n\n> Generates GraphQL Middleware layer from your rules.\n\n#### `rules`\n\nA rule map must match your schema definition. All rules must be created using the `rule` function to ensure caches are made correctly. You can apply your `rule` accross entire schema, Type scoped, or field specific.\n\n##### Limitations\n\n* All rules must have a distinct name. Usually, you won't have to care about this as all names are by default automatically generated to prevent such problems. In case your function needs additional variables from other parts of the code and is defined as a function, you'll set a specific name to your rule to avoid name generation.\n\n```jsx\n// Normal\nconst admin = rule({ cache: 'contextual' })(async (parent, args, ctx, info) => true)\n\n// With external data\nconst admin = bool =>\n  rule(`name`, { cache: 'contextual' })(async (parent, args, ctx, info) => bool)\n```\n\n* Cache is enabled by default accross all rules. To prevent `cache` generation, set `{ cache: 'no_cache' }` when generating a rule.\n* By default, no rule is executed more than once in complete query execution. This accounts for significantly better load times and quick responses.\n\n##### Cache\n\nYou can choose from three different cache options.\n\n1. `no_cache` - prevents rules from being cached.\n1. `contextual` - use when rule only relies on `ctx` parameter.\n1. `strict` - use when rule relies on `parent` or `args` parameter as well.\n\n```ts\n// Contextual\nconst admin = rule({ cache: 'contextual' })(async (parent, args, ctx, info) => {\n  return ctx.user.isAdmin\n})\n\n// Strict\nconst admin = rule({ cache: 'strict' })(async (parent, args, ctx, info) => {\n  return ctx.user.isAdmin || args.code === 'secret' || parent.id === 'theone'\n})\n```\n\n> Backward compatiblity: `{ cache: false }` converts to `no_cache`, and `{ cache: true }` converts to `strict`.\n\n#### `options`\n\n| Property            | Required | Default | Description                                 |\n| ------------------- | -------- | ------- | ------------------------------------------- |\n| allowExternalErrors | false    | false    | Toggles catching internal resolvers errors. |\n\nBy default `shield` ensures no internal data is exposed to client if it was not meant to be. Therefore, all thrown errors during execution resolve in `Not Authenticated!` error message if not otherwise specified using `CustomError`. This can be turned off by setting `allowExternalErrors` option to true.\n\n### `allow`, `deny`\n\n> GraphQL Shield predefined rules.\n\n`allow` and `deny` rules do exactly what their names describe.\n\n### `and`, `or`, `not`\n\n> `and`, `or` and `not` allow you to nest rules in logic operations.\n\n* Nested rules fail by default if error is thrown.\n\n#### And Rule\n\n`And` rule allows access only if all sub rules used return `true`.\n\n#### Or Rule\n\n`Or` rule allows access if at least one sub rule returns `true` and no rule throws an error.\n\n#### Not\n\n`Not` works as usual not in code works.\n\n```tsx\nimport { shield, rule, and, or } from 'graphql-shield'\n\nconst isAdmin = rule()(async (parent, args, ctx, info) => {\n  return ctx.user.role === 'admin'\n})\n\nconst isEditor = rule()(async (parent, args, ctx, info) => {\n  return ctx.user.role === 'editor'\n})\n\nconst isOwner = rule()(async (parent, args, ctx, info) => {\n  return ctx.user.items.some(id => id === parent.id)\n})\n\nconst permissions = shield({\n  Query: {\n    users: or(isAdmin, isEditor)\n  },\n  Mutation: {\n    createBlogPost: or(isAdmin, and(isOwner, isEditor))\n  },\n  User: {\n    secret: isOwner\n  },\n})\n```\n\n### `Custom Errors`\n\nShield, by default, catches all errors thrown during resolver execution. This way we can be 100% sure none of your internal logic will be exposed to the client if it was not meant to be.\n\nNevertheless, you can use `CustomError` error types to report your custom error messages to your users.\n\n```tsx\nimport { CustomError } from 'graphql-shield'\n\nconst typeDefs = `\n  type Query {\n    customError: String!\n  }\n`\n\nconst resolvers = {\n  Query: {\n    customError: () => {\n      throw new CustomError('customErrorResolver')\n    },\n  }\n}\n\nconst permissions = shield()\n\nconst server = GraphQLServer({\n  typeDefs,\n  resolvers,\n  middlewares: [permissions]\n})\n```\n\n## Contributors\n\nThis project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].\n<a href=\"https://github.com/maticzav/graphql-shield/graphs/contributors\"><img src=\"https://opencollective.com/graphql-shield/contributors.svg?width=890&button=false\" /></a>\n\n## Backers\n\nThank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/graphql-shield#backer)]\n\n<a href=\"https://opencollective.com/graphql-shield#backers\" target=\"_blank\"><img src=\"https://opencollective.com/graphql-shield/backers.svg?width=890\"></a>\n\n## Sponsors\n\nSupport this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/graphql-shield#sponsor)]\n\n<a href=\"https://opencollective.com/graphql-shield/sponsor/0/website\" target=\"_blank\"><img src=\"https://opencollective.com/graphql-shield/sponsor/0/avatar.svg\"></a>\n<a href=\"https://opencollective.com/graphql-shield/sponsor/1/website\" target=\"_blank\"><img src=\"https://opencollective.com/graphql-shield/sponsor/1/avatar.svg\"></a>\n<a href=\"https://opencollective.com/graphql-shield/sponsor/2/website\" target=\"_blank\"><img src=\"https://opencollective.com/graphql-shield/sponsor/2/avatar.svg\"></a>\n<a href=\"https://opencollective.com/graphql-shield/sponsor/3/website\" target=\"_blank\"><img src=\"https://opencollective.com/graphql-shield/sponsor/3/avatar.svg\"></a>\n<a href=\"https://opencollective.com/graphql-shield/sponsor/4/website\" target=\"_blank\"><img src=\"https://opencollective.com/graphql-shield/sponsor/4/avatar.svg\"></a>\n<a href=\"https://opencollective.com/graphql-shield/sponsor/5/website\" target=\"_blank\"><img src=\"https://opencollective.com/graphql-shield/sponsor/5/avatar.svg\"></a>\n<a href=\"https://opencollective.com/graphql-shield/sponsor/6/website\" target=\"_blank\"><img src=\"https://opencollective.com/graphql-shield/sponsor/6/avatar.svg\"></a>\n<a href=\"https://opencollective.com/graphql-shield/sponsor/7/website\" target=\"_blank\"><img src=\"https://opencollective.com/graphql-shield/sponsor/7/avatar.svg\"></a>\n<a href=\"https://opencollective.com/graphql-shield/sponsor/8/website\" target=\"_blank\"><img src=\"https://opencollective.com/graphql-shield/sponsor/8/avatar.svg\"></a>\n<a href=\"https://opencollective.com/graphql-shield/sponsor/9/website\" target=\"_blank\"><img src=\"https://opencollective.com/graphql-shield/sponsor/9/avatar.svg\"></a>\n\n## Contributing\n\nWe are always looking for people to help us grow `graphql-shield`! If you have an issue, feature request, or pull request, let us know!\n\n## License\n\nMIT @ Matic Zavadlal\n","readmeFilename":"README.md"}