{"id":15463255,"url":"https://github.com/thuoe/gql-util-directives","last_synced_at":"2026-02-05T21:03:24.881Z","repository":{"id":218403241,"uuid":"746302618","full_name":"thuoe/gql-util-directives","owner":"thuoe","description":"A simple utility package of GraphQL schema directives","archived":false,"fork":false,"pushed_at":"2024-05-02T22:27:58.000Z","size":948,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"next","last_synced_at":"2025-08-17T09:39:51.779Z","etag":null,"topics":["apollo-graphql","apollo-server","directives","graphql","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thuoe.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-01-21T17:05:37.000Z","updated_at":"2024-05-02T22:28:02.000Z","dependencies_parsed_at":"2024-02-10T00:26:13.087Z","dependency_job_id":"44446a42-cbb2-444b-af98-69508f14e55d","html_url":"https://github.com/thuoe/gql-util-directives","commit_stats":null,"previous_names":["thuoe/util-directives"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/thuoe/gql-util-directives","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thuoe%2Fgql-util-directives","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thuoe%2Fgql-util-directives/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thuoe%2Fgql-util-directives/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thuoe%2Fgql-util-directives/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thuoe","download_url":"https://codeload.github.com/thuoe/gql-util-directives/tar.gz/refs/heads/next","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thuoe%2Fgql-util-directives/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29134243,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-05T20:50:26.975Z","status":"ssl_error","status_checked_at":"2026-02-05T20:49:26.082Z","response_time":65,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apollo-graphql","apollo-server","directives","graphql","typescript"],"created_at":"2024-10-02T00:08:13.477Z","updated_at":"2026-02-05T21:03:22.328Z","avatar_url":"https://github.com/thuoe.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003egql-util-directives\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/thuoe/gql-util-directives/actions/workflows/ci.yml\"\u003e\n    \u003cimg src=\"https://github.com/thuoe/gql-util-directives/actions/workflows/ci.yml/badge.svg?branch=next\" alt=\"CI status\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://badge.fury.io/js/@thuoe%2Fgql-util-directives\"\u003e\n    \u003cimg src=\"https://badge.fury.io/js/@thuoe%2Fgql-util-directives.svg\" alt=\"npm version\" height=\"18\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003ch3 align=\"center\"\u003e\nSimple utility library for custom GraphQL schema directives\n\u003c/h3\u003e\n\n- [Get started](#get-started)\n- [Local Development](#local-development)\n- [Directives](#directives)\n  - [@encode](#encode)\n  - [@regex](#regex)\n  - [@cache](#cache)\n    - [Overriding in-memory cache](#overriding-in-memory-cache)\n  - [@currency](#currency)\n  - [@log](#log)\n    - [Logging to file](#logging-to-file)\n\n# Get started\n\nInstall package:\n\n```sh\nnpm install --save @thuoe/gql-util-directives\n```\n\nExample of importing the `@regex` directive \u0026 instantiating with Apollo Server:\n\n```typescript\nimport { ApolloServer } from \"@apollo/server\";\nimport { startStandaloneServer } from \"@apollo/server/standalone\";\nimport { makeExecutableSchema } from \"@graphql-tools/schema\";\nimport directives from \"@thuoe/gql-util-directives\";\n\nconst typeDefs = String.raw`#graphql\n  type User {\n    firstName: String\n    lastName: String @regex(pattern: \"\\\\b[A-Z]\\\\w+\\\\b\")\n    age: Int\n  }\n\n  type Query {\n    user: User\n  }\n`;\n\nconst resolvers = {\n  Query: {\n    user: () =\u003e ({\n      firstName: \"Michael\",\n      lastName: \"Jordan\",\n      age: 61,\n    }),\n  },\n};\n\nconst { regexDirective } = directives;\nconst { regexDirectiveTypeDefs, regexDirectiveTransformer } =\n  regexDirective(\"regex\");\n\nconst transformers = [regexDirectiveTransformer];\n\nlet schema = makeExecutableSchema({\n  typeDefs: [regexDirectiveTypeDefs, typeDefs],\n  resolvers,\n});\n\nschema = transformers.reduce(\n  (curSchema, transformer) =\u003e transformer(curSchema),\n  schema,\n);\n\nconst server = new ApolloServer({\n  schema,\n});\n\nstartStandaloneServer(server, {\n  listen: { port: 4000 },\n}).then(({ url }) =\u003e {\n  console.log(`🚀 Server ready at: ${url}`);\n});\n```\n\nHere are the possible directive functions that are exposed as part of this util package:\n\n`regexDirective | encodingDirective | cacheDirective`\n\n# Local Development\n\nInstall local dependencies:\n\n```sh\nnpm install\n```\n\nRun local environment (Apollo Studio):\n\n```sh\nnpm run dev\n```\n\nLink to Apollo Studio can be found on http://localhost:4000 to perform mutations and queries.\n\n# Directives\n\n## @encode\n\n`encodingDirective(directiveName?: string)`\n\nYou can use the `@encode` directive on fields defined using the `String` scalar type.\n\nFollowing encoding methods:\n\n`ascii | utf8 | utf16le | ucs2 | base64 | base64url | latin1 | binary | hex`\n\n```graphql\ntype User {\n  firstName: String @encode(method: \"hex\")\n  lastName: String @encode(method: \"base64\")\n}\n```\n\n## @regex\n\n`regexDirective(directiveName?: string)`\n\nYou can use the `@regex` directive to validate fields using the `String` scalar type. It will throw an\n`ValidationError` in the event that the pattern defined has a syntax if no matches are found against the field value.\n\n```graphql\ntype User {\n  firstName: String @regex(pattern: \"(John|Micheal)\")\n  lastName: String @regex(pattern: \"\\\\b[A-Z]\\\\w+\\\\b\")\n}\n```\n\n⚠️ Escaping characters\n\nIf you are defining a regex pattern using backslashes must escape them (`//`) **and** pattern invoke the function `String.raw()` to the schema so that the escape characters are not ignored:\n\n```typescript\nconst typeDefs = String.raw`\n  type User {\n    firstName: String @regex(pattern: \"(Eddie|Sam)\")\n    lastName: String @regex(pattern: \"\\\\b[A-Z]\\\\w+\\\\b\")\n    age: Int\n  }\n\n  type Query {\n    user: User\n  }\n`;\n```\n\n## @cache\n\n`cacheDirective({ directiveName, cache }?: { directiveName?: string, cache?: CachingImpl })`\n\nYou can use `@cache` directive to take advantage of a in-memory cache for a field value\n\n```graphql\ntype Book {\n  name: String\n  price: String @cache(key: \"book_price\", ttl: 3000)\n}\n```\n\n`key` - represents the unique key for field value you wish to cache\n\n`ttl` - time-to-live argument for how long the field value should exist within the cache before expiring (in milliseconds)\n\n### Overriding in-memory cache\n\nIf you wish to take leverage something more powerful (for example [Redis](https://redis.io/)), you can override the in-memory solution with your own implementation.\n\nExample:\n\n```typescript\nimport Redis from 'ioredis'\n\nconst redis = new Redis()\n....\nconst cache = {\n  has: (key: string) =\u003e redis.exists(key),\n  get: (key: string) =\u003e redis.get(key),\n  delete:(key: string) =\u003e redis.delete(key),\n  set: async (key: string, value: string) =\u003e {\n    await redis.set(key, value)\n  },\n}\n...\nconst { cacheDirectiveTypeDefs, cacheDirectiveTransformer } = cacheDirective({ cache: callback })\n```\n\nYou must confirm to this set of function signatures to make this work:\n\n- `has: (key: string) =\u003e Promise\u003cboolean\u003e` Checks if a key exists in the cache.\n- `get: (key: string) =\u003e Promise\u003cstring\u003e` Retrieves the value associated with a key from the cache.\n- `set: (key: string, value: string) =\u003e Promise\u003cvoid\u003e` Sets a key-value pair in the cache.\n- `delete: (key: string) =\u003e Promise\u003cboolean\u003e` Deletes a key and its associated value from the cache.\n\n## @currency\n\n`currencyDirective(directiveName?: string)`\n\nYou can use the `@currency` directive to fetch the latest exchange rate of a given amount\n\n```graphql\ntype Car {\n  make: String\n  model: String\n  price: String @currency(from: GBP, to: USD)\n}\n```\n\nThe field can either be resolved with scalar types `String` or `Float`\n\nThe valid currency codes to use as part of the directive's arguments can be found [here](./src/types.ts).\n\n## @log\n\n`logDirective({ directiveName, filePath }?: { directiveName?: string, filePath?: string })`\n\nUse the `@log` directive to log fields, queries and mutations once they are resolved.\n\nFor example, this graphql schema with the directive on the query:\n\n```graphql\n  type User {\n    firstName: String\n    lastName: String \n    age: Int \n    amount: String\n  }\n\n  type Query {\n    user(firstName: String!): User @log(level: INFO)\n  }\n```\n\nWill log to the console in the following format:\n\n`[\u003cTIMESTAMP\u003e] [INFO] @log - Operation Type: query, Arguments: [{\"firstName\":\"Eddie\"}], Return Type: User`\n\nThe following log levels are valid:\n\n- `INFO`\n- `DEBUG`\n- `WARN`\n- `ERROR`\n\n### Logging to file\n\nIn order to migrate logs to a custom log file, you can define a filepath with the appropriate file name:\n\n```typescript\n  const { logDirectiveTypeDefs, logDirectiveTransformer } = logDirective({\n    filePath: path.join(__dirname, 'logs', 'application.log')\n  })\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthuoe%2Fgql-util-directives","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthuoe%2Fgql-util-directives","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthuoe%2Fgql-util-directives/lists"}