Skip to content

Commit

Permalink
update implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
RomanHotsiy committed Jul 17, 2017
1 parent 6a1ecf3 commit c19205e
Show file tree
Hide file tree
Showing 9 changed files with 3,002 additions and 50 deletions.
1 change: 0 additions & 1 deletion custom.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
declare module 'graphql/*'
declare module 'valid-url'
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,6 @@
"dependencies": {
"graphql": "0.7.1 - 1.0.0",
"graphql-request": "^1.2.0",
"valid-url": "^1.0.9"
"minimatch": "^3.0.4"
}
}
10 changes: 7 additions & 3 deletions src/GraphQLConfig.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { relative } from 'path'

import {
GraphQLConfigData,
} from './types'

import {
findConfigPath,
readConfig,
isFileInDirs,
matchesGlobs,
validateConfig,
} from './utils'

Expand All @@ -30,19 +32,21 @@ export class GraphQLConfig {
getConfigForFile(filePath: string): GraphQLProjectConfig | null {
const { projects } = this.config

filePath = relative(this.configPath, filePath)
if (!projects || Object.keys(projects).length === 0) {
const config = new GraphQLProjectConfig(this.configPath, undefined, this.config)
return config.includesFile(filePath) ? config : null
}

Object.entries(projects).forEach(([projectName, project]) => {
if (
isFileInDirs(filePath, project.includeDirs) &&
!isFileInDirs(filePath, project.excludeDirs)
matchesGlobs(filePath, project.include) &&
!matchesGlobs(filePath, project.exclude)
) {
return this.getProjectConfig(projectName)
}
})

return null
}

Expand Down
30 changes: 16 additions & 14 deletions src/GraphQLProjectConfig.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { join as joinPaths, dirname } from 'path'
import { join as joinPaths, dirname, relative } from 'path'

import {
GraphQLSchema,
Expand All @@ -17,21 +17,25 @@ import {
isPathToConfig,
findConfigPath,
readConfig,
isFileInDirs,
matchesGlobs,
validateConfig,
mergeConfigs,
readSchema,
querySchema,
GRAPHQL_CONFIG_NAME,
} from './utils'


/*
* this class can be used for simple usecases where there is no need in per-file API
*/
export class GraphQLProjectConfig {
public config: GraphQLProjectConfigData
public configPath: string

constructor(
path: string = process.cwd(),
public projectName: string = process.env.GRAPHQL_PROJECT,
configData?: GraphQLConfigData // for cases when data is already parsed
configData?: GraphQLConfigData // in case the data is already parsed
) {
if (isPathToConfig(path)) {
this.configPath = path
Expand All @@ -52,16 +56,12 @@ export class GraphQLProjectConfig {
}

resolveSchema(env?: string): Promise<GraphQLSchema> {
const {schemaPath, schemaUrl} = this.getConfig(env)
const { schemaPath } = this.getConfig(env)

if (schemaPath) {
return readSchema(this.resolveConfigPath(schemaPath))
}
if (schemaUrl) {
return querySchema(schemaUrl)
}
// FIXME
throw new Error('')
throw new Error(`"schemaPath" is required but not provided in ${GRAPHQL_CONFIG_NAME}`)
}

resolveIntrospection(env?: string): Promise<any> {
Expand All @@ -88,8 +88,8 @@ export class GraphQLProjectConfig {
const selectedEnvConfig = env[envName]
if (!selectedEnvConfig) {
const possibleNames = Object.keys(env)
// FIXME
throw new Error(`${possibleNames}`)
throw new Error(`Wrong value provided for GRAPHQL_ENV. ` +
`The following values are valid: ${possibleNames.join(', ')}`)
}

return mergeConfigs(configBase, selectedEnvConfig)
Expand All @@ -104,9 +104,10 @@ export class GraphQLProjectConfig {
}

includesFile(filePath: string): boolean {
filePath = relative(this.configPath, filePath)
return (
isFileInDirs(filePath, this.config.includeDirs) &&
!isFileInDirs(filePath, this.config.excludeDirs)
matchesGlobs(filePath, this.config.include) &&
!matchesGlobs(filePath, this.config.exclude)
)
}
}
Expand All @@ -121,6 +122,7 @@ function loadProjectConfig(
return config
}

// TODO: try checking GRAPHQL_CONFIG_PROJECT env var ?
if (!projectName) {
throw new Error('Project name must be specified for multiproject config')
}
Expand Down
8 changes: 4 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
export {
GraphQLProjectConfig
} from './GraphQLProjectConfig';

export {
GraphQLConfig
} from './GraphQLConfig';

export {
GraphQLProjectConfig
} from './GraphQLProjectConfig';

export * from './types';

export {
Expand Down
21 changes: 15 additions & 6 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
type GraphQLConfigurationExtension = {
export type ServerExtensionConfig = {
url: string
headers: { [name: string]: string }
}

export type GraphQLConfigExtensions = {
server?: ServerExtensionConfig,
'server-query'?: ServerExtensionConfig,
'server-mutation'?: ServerExtensionConfig,
'server-subscription'?: ServerExtensionConfig,

[name: string]: any
}

export type GraphQLResolvedConfigData = {
schemaPath?: string,
schemaUrl?: string,
schemaPath: string,

includeDirs?: Array<string>,
excludeDirs?: Array<string>,
include?: Array<string>,
exclude?: Array<string>,

extensions?: { [name: string]: GraphQLConfigurationExtension }
extensions?: GraphQLConfigExtensions;
}

export type GraphQLProjectConfigData = GraphQLResolvedConfigData & {
Expand Down
35 changes: 14 additions & 21 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
import { readFile, readFileSync, existsSync } from 'fs'
import { resolve, join as joinPaths, dirname, sep, extname } from 'path'
import { buildSchema, buildClientSchema, introspectionQuery } from 'graphql'
import { request } from 'graphql-request'
import { resolve, join as joinPaths, dirname, extname } from 'path'
import { buildSchema, buildClientSchema } from 'graphql'
import { GraphQLConfigData } from './types'
import * as minimatch from 'minimatch'

export const GRAPHQL_CONFIG_NAME = '.graphqlconfig'
export const GRAPHQL_CONFIG_NAME = '.graphqlrc'

function isRootDir(path: string): boolean {
return dirname(path) === path
}

function isSubPath(from: string, to: string): boolean {
from = resolve(from)
to = resolve(to)
return (from === to || to.startsWith(from + sep))
}

export function isPathToConfig(path: string) {
return (extname(path) === GRAPHQL_CONFIG_NAME)
}
Expand Down Expand Up @@ -43,18 +37,21 @@ export function readConfig(configPath: string): GraphQLConfigData {
const config = JSON.parse(rawConfig)
return config
} catch (error) {
// FIXME: prefix error
// console.error('Parsing JSON in .graphqlrc file has failed.')
throw new Error(error)
error.message = 'Parsing JSON in .graphqlrc file has failed.\n' + error.message
throw error
}
}

export function isFileInDirs(filePath: string, dirs?: string[]): boolean {
return (dirs || []).some(dir => isSubPath(dir, filePath))
function matchesGlob(filePath: string, pattern: string): boolean {
return minimatch(filePath, pattern, {matchBase: true})
}

export function matchesGlobs(filePath: string, globs?: string[]): boolean {
return (globs || []).some(pattern => matchesGlob(filePath, pattern))
}

export function validateConfig(config: GraphQLConfigData) {
// FIXME:
// FIXME: implement
}

export function mergeConfigs(
Expand Down Expand Up @@ -87,11 +84,7 @@ export function readSchema(path) {
case '.json':
return buildClientSchema(JSON.parse(data).data)
default:
throw new Error('Unsupported schema file extention')
throw new Error('Unsupported schema file extention. Only ".graphql" and ".json" are supported')
}
})
}

export function querySchema(url: string, options?) {
return request(url, introspectionQuery)
}
File renamed without changes.
Loading

0 comments on commit c19205e

Please sign in to comment.