Closed rogchap closed 7 years ago
Great! I think a require hook could be a good first step - then you can just require .graphql files.
@stubailo Yea that would be awesome. I'll have a crack at putting this PR together.
For the "hook", there is only one way to do this but it's technically depreciated: https://nodejs.org/api/globals.html#globals_require_extensions
Since the module system is locked, this feature will probably never go away. However, it may have subtle bugs and complexities that are best left untouched.
Other modules are still using this, are we ok with this, I don't know of an alternative?
Also, is there a suitable place to have this extension initiated?
i think i saw webpack plugin which gives you the ability to just import
them..
but that was for graphql-tag
client side.
maybe we should add such loader to graphql-tools?
So, this should be straightforward however, it does not play nice with TypeScript.
Problem 1: [ts] Can't find module myRootQuery.graphql
- This can be resolved by using require
instead of import
Problem 2: TypeScript has no --copy-files
, therefore won't copy any non-ts/js files to the output dir
Anybody have any smart idea's?
Don't want to have to use a build script / gulp etc.
This is what I've been doing on the server to "import" a graphql file. Not as pretty, but easy enough:
// read schema.graphql file in same folder as this module
const schema = [fs.readFileSync(path.join(__dirname, "schema.graphql"), "utf8")];
I've been using require-text for this.
It's a good temp solution @bman654 Thanks!
With TS > 2.0 you can use a wildcard when declaring a module type:
declare module "*.graphql" {
const value: any;
export default value;
}
Then you can import it just like a .ts
file. (Edit: a loader is still required)
@abdulhaq-e whoa - do you have to use that with require-text
as well, or does it just work?
Sorry I just tried it and a loader is required.
typings.d.ts
:
declare module "*.graphql" {
const value: any;
export default value;
}
code:
import * as query from query.graphql
For this to work, a loader such as raw-loader
for those using webpack will work.
module: {
rules: [
{ test: /\.json$/, loader: 'json-loader' },
{ test: /\.html$/, loader: 'raw-loader' },
{ test: /\.graphql$/, loader: 'raw-loader' },
]
A loader is required if you build your server with Webpack. If you're just using Node.js directly (as you probably should in case of a GraphQL/API endpoint), loaders don't help.
We should suggest a solution in the docs that doesn't require a loader. Most people don't want to use webpack or similar on the server for good reasons.
@helfer im not familiar with that most people prefere not to use webpack for server side as well, can you give example of the good reasons?
A much more complex build process, more difficult debugging and deploying, and little if any added benefits for GraphQL/API type servers.
What are you bundling, after all?
well, bundling gives you alot of power when you go from typescript to javascript... for example, how much output(s) do you want? where? also, being able to hook the output gives more values (for example, i've written a plugin which instruments the whole output, so you know exactly how much code is covered out of the whole product you are going to deploy) maybe it's just me who's appreciate those things..
These are great things, but I think they're rather better left for the CI and not hidden inside webpack.config..js files..
As for transpiling from TypeScript, I admit I have no experience with that as of yet, so I don't know. I do know that using webpack should be optional.
Meteor now has a loader for this that allows you to simply import the schema file:
import schema from './schema.graphql'
Underwater this uses the webpack loader from graphql-tag
which doesn't return a string, but a parsed schema. It works for the server and client.
Sadly, makeExecutableSchema
only accepts strings, so now I need to parse it back again before passing it on:
import schema from './schema.graphql'
import { print } from 'graphql/language/printer';
const schema = makeExecutableSchema({
typeDefs: print(schema),
resolvers,
});
What do you all expect from a loader or a require hook to return when importing .graphql
files? A string, or the result of parsed schema like the webpack loader in graphql-tag
returns? If the latter, then makeExecutableSchema
shouldn't just allow strings.
Perhaps this should be discussed in a separate issue, but support for a schema object, and not only a string, would be great.
@jamiter actually it might be nice if makeExecutableSchema
could accept Schema ASTs just as well as strings, it would just be a matter of running print
.
Cool, I'll make a PR for that!
@stubailo, see https://github.com/apollographql/graphql-tools/pull/300
Just merged #300 which should make this possible.
I am still unclear on the best way to use static schema files on a typescript + node server without webpack. Is there currently a solution to this Problem?
@Isigiel right now there isn't really anything in graphql-tools
preventing you from doing that, sounds like you are looking for some kind of static file loader for node. Basically you need something that will let you import or read .graphql
files, and then you should just pass the resulting strings into makeExecutableSchema
?
Yeah right, but I'm unclear on how to import them, webpack seems overkill and just fs.rading them does not work because tsc does not copy the files. Right now to me, the best option seems to be, have a second gulp task running that will watch the files and copy the graphql files. I was mainly wondering if someone had come up with a more elegant solution.
@Isigiel https://github.com/quadric/babel-plugin-inline-import seems like a good option, if you're already using Babel.
One issue you have using babel-plugin-inline-import is when you use nodemon
. Even if you tell it to monitor .graphql
files, the changes to the schema will not be reloaded from file when nodemon is triggered. One must make a change to the file importing the schema in order for that to happen. Developers suggest disabling babel cache, but that doesn't seem like a wise idea.
Maybe this tool can also work? https://github.com/graphcool/graphql-import
Here's a quick way to assemble .graphql
strings as one to load into makeExecutableSchema
that I've been using: https://gist.github.com/ericnograles/d59e32f244c9ea04e69f66a7caa96940
It'll sweep through .graphql files in a folder and assemble all of them, leaving Query.graphql
for the last concat, and finally export out the finished string for usage.
@stubailo graphql-import is definitely the way to go -- it's also included in https://github.com/graphcool/graphql-yoga, which I would suggest anyone check out.
graphql-import def looks slick, will need to check that out!
I am trying to make use of graphql-import
with typescript, It loads files fine but I still have to find a way to copy the .qraphql
files to a dist folder... which mean involving some more complex build steps. And the idea of maintain both a AST
version and AST.ts
string version is not ideal.
I'm considering trying out something like the following: Folder structure for a singe entity
- Book
-- index.ts
-- query.qraphql
-- query.qraphql.ts
-- resolver.ts
-- schema.qraphql
-- schema.qraphql.ts
*.qraphql.ts
import { importSchema } from "graphql-import"
export const Query:string = importSchema(__dirname + '/' + __filename.replace('.ts',''));
when i build i want to take the *.qraphql
content and replace the importSchema
with the actual qraphql string. so that the dist folder will contain a baked version of the qraphql
at build time.
Thoughts?
@iamlothian I think it's fair to assume that if you take your query to https://github.com/graphcool/graphql-import (open an issue there), the maintainer could help you with that.
@vincenzo thanks, here is a link for reference
In a similar vein to @ericnograles's solution, if you are using webpack for Node.js, you can use raw-loader for .graphql
files, then use webpack's require.context
to load them all as a string:
// ./graphql/index.js
const importer = require.context('./', true, /\.graphql$/);
const keys = importer.keys();
const root = './Query.graphql';
module.exports = [
...keys
.filter(key => key !== root)
.reduce(
(typeDefs, key) => typeDefs.add(importer(key)),
new Set([importer(root)])
),
].join('\n');
You can then import this and pass it to makeExecutableSchema
:
import { makeExecutableSchema } from 'graphql-tools';
import typeDefs from './graphql';
makeExecutableSchema({ typeDefs });
You could also take a very dumb approach and copy your .graphql files to your /dist
folder with webpack plugin, like: https://github.com/webpack-contrib/copy-webpack-plugin
Hi, In case you are still looking for an option I use "copyfiles" node module for this.
package.json
"scripts": {
"build": "yarn run build-ts && copyfiles -u 1 src/*.json src/*.yml src/config/*.* dist"
}
You could easily add your ".graphql" files.
GraphQL Import works great with importing .graphql
const typeDefs = importSchema('./schema.graphql')
but it requires a Node.js environment & won't work for the front end. The only solution for the browser side is using a Webpack loader for .graphql files, but I hadn't been able to get the loader working with a CRA Typescript version yet.
I didn't want to use webpack
just to copy .graphql
files to the dist
folder.
I used cpx package to copy my .graphql
files keeping same file tree structure. It works fine.
Here's my package.json
"scripts": {
"copy-schemas": "$(npm bin)/cpx src/**/*.graphql dist",
"start": "tsc && npm run copy-schemas && node ./dist/index.js"
}
Hi I'm use merge-graphql-schemas I think it cover many folder structure
import { fileLoader, mergeTypes, } from 'merge-graphql-schemas'
const typesArray = fileLoader(path.join(__dirname, 'graphql/**/*.graphql'))
const typeDefs = mergeTypes(typesArray, { all: true })
Hi I'm use merge-graphql-schemas I think it cover many folder structure
import { fileLoader, mergeTypes, } from 'merge-graphql-schemas' const typesArray = fileLoader(path.join(__dirname, 'graphql/**/*.graphql')) const typeDefs = mergeTypes(typesArray, { all: true })
This package is now not maintainable.
I didn't want to use
webpack
just to copy.graphql
files to thedist
folder. I used cpx package to copy my.graphql
files keeping same file tree structure. It works fine.Here's my
package.json
"scripts": { "copy-schemas": "$(npm bin)/cpx src/**/*.graphql dist", "start": "tsc && npm run copy-schemas && node ./dist/index.js" }
Thank you so much!!! I tweaked it a bit for my project(not using typescript) and it works brilliantly.
"scripts": {
"copy-schemas": "cpx src/**/*.graphql dist",
"start": "npm run copy-schemas && node ./dist/app.js",
},
thank you @nutboltu. In my case I needed to copy .gql
files and it looks like files contained deeper in project than in your case, so I changed also output directory:
"copy-schemas": "$(npm bin)/cpx src/**/*.gql dist/src"
This was breifly mentioned by @stubailo here: https://github.com/apollographql/graphql-tools/issues/124#issuecomment-245037518
What I've found is that as my project grows it's increasingly harder to read my schema as it's formatted as a single string. (especially when you're diligently adding descriptions for everything).
We want all of this: https://dev-blog.apollodata.com/5-benefits-of-static-graphql-queries-b7fa90b0b69a but on the server.