Skip to content

Commit

Permalink
Refactor GitLoader (#1796)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielrearden committed Jul 18, 2020
1 parent 49d61ab commit 479892b
Show file tree
Hide file tree
Showing 9 changed files with 1,161 additions and 29 deletions.
11 changes: 2 additions & 9 deletions packages/loaders/git/package.json
Expand Up @@ -17,17 +17,10 @@
},
"dependencies": {
"@graphql-tools/utils": "6.0.14",
"@graphql-tools/graphql-tag-pluck": "6.0.14",
"simple-git": "2.13.1"
},
"buildOptions": {
"external": [
"simple-git",
"simple-git/promise"
]
"@graphql-tools/graphql-tag-pluck": "6.0.14"
},
"publishConfig": {
"access": "public",
"directory": "dist"
}
}
}
17 changes: 5 additions & 12 deletions packages/loaders/git/src/index.ts
Expand Up @@ -34,11 +34,9 @@ export type GitLoaderOptions = SingleFileOptions & {
/**
* Additional options to pass to `graphql-tag-pluck`
*/
pluckConfig: GraphQLTagPluckOptions;
pluckConfig?: GraphQLTagPluckOptions;
};

const createInvalidExtensionError = (path: string) => new Error(`Invalid file extension: ${path}`);

/**
* This loader loads a file from git.
*
Expand Down Expand Up @@ -72,7 +70,10 @@ export class GitLoader implements UniversalLoader {

const rawSDL = await gqlPluckFromCodeString(pointer, content, options.pluckConfig);

return ensureSource({ rawSDL, pointer, path });
return {
location: pointer,
rawSDL,
};
}

loadSync(pointer: string, options: GitLoaderOptions) {
Expand All @@ -86,17 +87,9 @@ export class GitLoader implements UniversalLoader {

const rawSDL = gqlPluckFromCodeStringSync(pointer, content, options.pluckConfig);

return ensureSource({ rawSDL, pointer, path });
}
}

function ensureSource({ rawSDL, pointer, path }: { rawSDL: string; pointer: string; path: string }) {
if (rawSDL) {
return {
location: pointer,
rawSDL,
};
}

throw createInvalidExtensionError(path);
}
21 changes: 13 additions & 8 deletions packages/loaders/git/src/load-git.ts
@@ -1,20 +1,26 @@
import simplegit from 'simple-git/promise';
import simplegitSync from 'simple-git';
import { exec, execSync } from 'child_process';

type Input = { ref: string; path: string };

const createLoadError = (error: any) => new Error('Unable to load schema from git: ' + error);
const createLoadError = (error: any) => new Error('Unable to load file from git: ' + error);
const createCommand = ({ ref, path }: Input) => {
return [`${ref}:${path}`];
return `git show ${ref}:${path}`;
};

/**
* @internal
*/
export async function loadFromGit(input: Input): Promise<string | never> {
try {
const git = simplegit();
return await git.show(createCommand(input));
return await new Promise((resolve, reject) => {
exec(createCommand(input), { encoding: 'utf-8' }, (error, stdout) => {
if (error) {
reject(error);
} else {
resolve(stdout);
}
});
});
} catch (error) {
throw createLoadError(error);
}
Expand All @@ -25,8 +31,7 @@ export async function loadFromGit(input: Input): Promise<string | never> {
*/
export function loadFromGitSync(input: Input): string | never {
try {
const git = simplegitSync();
return git.show(createCommand(input));
return execSync(createCommand(input), { encoding: 'utf-8' });
} catch (error) {
throw createLoadError(error);
}
Expand Down
78 changes: 78 additions & 0 deletions packages/loaders/git/tests/loader.spec.ts
@@ -0,0 +1,78 @@
import { execSync } from 'child_process';

import { Source } from '@graphql-tools/utils';

import { GitLoader } from '../src';
import { runTests } from '../../../testing/utils';

describe('GitLoader', () => {
const loader = new GitLoader();
const lastCommit = execSync('git rev-parse HEAD', { encoding: 'utf-8' }).replace(/\n/g, '');
const getPointer = (fileName: string) => {
return `git:${lastCommit}:packages/loaders/git/tests/test-files/${fileName}`;
};

describe('loaderId', () => {
it('should return a loader id', () => {
expect(loader.loaderId()).toBeDefined();
});
});

describe('canLoad', () => {
runTests({
async: loader.canLoad.bind(loader),
sync: loader.canLoadSync.bind(loader),
})(canLoad => {
it('should return true for a valid pointer', async () => {
expect(canLoad(getPointer('some-file.graphql'))).resolves.toBe(true);
});

it('should return false if pointer does not begin with "git:"', async () => {
expect(canLoad(getPointer('some-file.graphql').substring(4))).resolves.toBe(false);
});

it('should return false if pointer is not a string', async () => {
expect(canLoad(42 as any)).resolves.toBe(false);
});
});
});

describe('load', () => {
runTests({
async: loader.load.bind(loader),
sync: loader.loadSync.bind(loader),
})(load => {
it('should load document from a .graphql file', async () => {
const result: Source = await load(getPointer('type-defs.graphql'), {});
expect(result.document).toBeDefined();
});

it('should load introspection data from a .json file', async () => {
const result: Source = await load(getPointer('introspection.json'), {});
expect(result.schema).toBeDefined();
});

it('should load type definitions from a .json file', async () => {
const result: Source = await load(getPointer('type-defs.json'), {});
expect(result.document).toBeDefined();
});

it('should load type definitions from a pluckable file', async () => {
const result: Source = await load(getPointer('pluckable.ts'), {});
expect(result.rawSDL).toBeDefined();
});

it('should throw when pointer is malformed', async () => {
await expect(load(getPointer('foo:graphql'), {})).rejects.toThrowError(
'Schema pointer should match "git:branchName:path/to/file"'
);
});

it('should throw when the file does not exist', async () => {
await expect(load(getPointer('wrong-filename.graphql'), {})).rejects.toThrowError(
'Unable to load file from git'
);
});
});
});
});
3 changes: 3 additions & 0 deletions packages/loaders/git/tests/test-files/bad-extension.garphql
@@ -0,0 +1,3 @@
type Query {
hello: String
}

0 comments on commit 479892b

Please sign in to comment.