From 95a6c5df5d945f59866f997a24ad399a0d0bf9c2 Mon Sep 17 00:00:00 2001 From: danielabdelsamed Date: Sun, 24 Feb 2019 16:41:19 -0500 Subject: [PATCH] Added more hashing methods --- README.md | 14 ++++++++++++++ src/ExtractGQL.ts | 45 ++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 43550ff..03e7af9 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,20 @@ It is also possible to extract GraphQL queries from JavaScript files using `--ex persistgraphql src/index.js --js --extension=js ``` +## Setting the Hash Type + +By default, the IDs for the queries will be set in sequential order by when they are found. If you want to use something other than this, a few options are available by using `--hash=[type]`. These include: + +`sequential` (default) creates a numberical id for each query + +`md5` creates a hash based on the query that is found in the file + +`sha1` identical to md5, except uses the sha1 hashing algorithm + +`uuid` creates a uuidv4 for each query + + + # Apollo Client Network Interface This package provides an implementation of an Apollo Client network interface that provides persisted query support. It serves as a drop-in replacement for the standard network interface and uses the query map given by `persistgraphql` in order to send only query hashes/ids to the serverather than the query document. diff --git a/src/ExtractGQL.ts b/src/ExtractGQL.ts index cf1f93f..c2d4153 100644 --- a/src/ExtractGQL.ts +++ b/src/ExtractGQL.ts @@ -1,5 +1,5 @@ // This file implements the extractgql CLI tool. - +import crypto = require('crypto'); import fs = require('fs'); import path = require('path'); @@ -41,12 +41,17 @@ import { import _ = require('lodash'); +export type HashTypeOption = 'md5' | 'sha1' | 'sequential' | 'uuid'; + +export const HASH_TYPES: HashTypeOption[] = ['md5', 'sha1', 'sequential', 'uuid']; + export type ExtractGQLOptions = { inputFilePath: string, outputFilePath?: string, queryTransformers?: QueryTransformer[], extension?: string, inJsCode?: boolean, + hashType?: HashTypeOption, }; export class ExtractGQL { @@ -66,6 +71,9 @@ export class ExtractGQL { // Whether to look for standalone .graphql files or template literals in JavaScript code public inJsCode: boolean = false; + // What type of hash/id should be used + public hashType: HashTypeOption; + // The template literal tag for GraphQL queries in JS code public literalTag: string = 'gql'; @@ -111,12 +119,14 @@ export class ExtractGQL { queryTransformers = [], extension = 'graphql', inJsCode = false, + hashType = 'sequential', }: ExtractGQLOptions) { this.inputFilePath = inputFilePath; this.outputFilePath = outputFilePath; this.queryTransformers = queryTransformers; this.extension = extension; this.inJsCode = inJsCode; + this.hashType = hashType; } // Add a query transformer to the end of the list of query transformers. @@ -153,7 +163,7 @@ export class ExtractGQL { const transformedQueryWithFragments = this.getQueryFragments(transformedDocument, transformedDefinition); transformedQueryWithFragments.definitions.unshift(transformedDefinition); const docQueryKey = this.getQueryDocumentKey(transformedQueryWithFragments); - result[docQueryKey] = this.getQueryId(); + result[docQueryKey] = this.getQueryId(docQueryKey); }); return result; } @@ -290,9 +300,26 @@ export class ExtractGQL { } // Returns unique query ids. - public getQueryId() { - this.queryId += 1; - return this.queryId; + public getQueryId(documentQuery: string) { + switch (this.hashType) { + case 'md5': + return crypto.createHash('md5').update(documentQuery, 'utf8').digest('hex'); + case 'sha1': + return crypto.createHash('sha1').update(documentQuery, 'utf8').digest('hex'); + case 'uuid': + const randomBytes = crypto.randomBytes(32).toString('hex'); + return ( + randomBytes.substr(0, 8) + '-' + + randomBytes.substr(8, 4) + '-' + + randomBytes.substr(12, 4) + '-' + + randomBytes.substr(16, 4) + '-' + + randomBytes.substr(20, 12) + ); + case 'sequential': + default: + this.queryId += 1; + return this.queryId; + } } // Writes an OutputMap to a given file path. @@ -370,5 +397,13 @@ export const main = (argv: YArgsv) => { options.extension = argv['extension']; } + if (argv['hash']) { + if (HASH_TYPES.indexOf(argv['hash']) === -1) { + console.log(`Invalid hash operation. Must be one of [${HASH_TYPES.join(', ')}]`); + process.exit(1); + } + options.hashType = argv['hash']; + } + new ExtractGQL(options).extract(); };