-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Work with multiple projects and/or support GraphQL Config #247
Comments
I tried the following to at least get support for the main project const graphqlConfig = require("./graphql.config");
const defaultSchema = graphqlConfig.projects.default.schema;
module.exports = {
client: {
service: {
// can be a string pointing to a single file or an array of strings
localSchemaFile: defaultSchema,
},
includes: Array.from(
new Set(
Array.from(
new Set(
// Object.values(graphqlConfig.projects)
// Somehow native and frontend are causing the extension to crash
[
graphqlConfig.projects.dashboard,
graphqlConfig.projects["server-rendering"],
graphqlConfig.projects["work-order-asset-snapshots"],
]
.filter((p) => p.schema === defaultSchema)
.flatMap((p) => p.documents || []),
),
),
),
),
excludes: ["*.gen.*"],
},
}; Not sure why, but if I include files from the frontend or native projects the extension crashes with this error /Users/micfer/.vscode/extensions/apollographql.vscode-apollo-2.5.1/lib/language-server/server.js:1084
`)}t(Dor,"dedentBlockStringValue");function kor(i){let r=null;for(let s=1;s<i.length;s++){let c=i[s],u=Mqt(c);if(u!==c.length&&(r===null||u<r)&&(r=u,r===0))break}return r===null?0:r}t(kor,"getBlockStringIndentation");function Mqt(i){let r=0;for(;r<i.length&&(i[r]===" "||i[r]===" ");)r++;return r}t(Mqt,"leadingWhitespace");function Rqt(i){return Mqt(i)===i.length}t(Rqt,"isBlank");var Qqt=jo(Fo(),1);function jqt(i){return i&&typeof i=="object"&&"kind"in i&&i.kind===Qqt.Kind.DOCUMENT}t(jqt,"isDocumentNode");function Uqt(i,r,s){let c=xor([...r,...i].filter(yz),s);return s&&s.sort&&c.sort(sM),c}t(Uqt,"mergeArguments");function xor(i,r){return i.reduce((s,c)=>{let u=s.findIndex(_=>_.name.value===c.name.value);return u===-1?s.concat([c]):(r?.reverseArguments||(s[u]=c),s)},[])}t(xor,"deduplicateArguments");function wor(i,r){return!!i.find(s=>s.name.value===r.name.value)}t(wor,"directiveAlreadyExists");function qqt(i,r){return!!r?.[i.name.value]?.repeatable}t(qqt,"isRepeatableDirective");function Vqt(i,r){return r.some(({value:s})=>s===i.value)}t(Vqt,"nameAlreadyExists");function Jqt(i,r){let s=[...r];for(let c of i){let u=s.findIndex(_=>_.name.value===c.name.value);if(u>-1){let _=s[u];if(_.value.kind==="ListValue"){let g=_.value.values,b=c.value.values;_.value.values=Wqt(g,b,(I,w)=>{let L=I.value;return!L||!w.some(V=>V.value===L)})}else _.value=c.value}else s.push(c)}return s}t(Jqt,"mergeArguments");function Nor(i,r){return i.map((s,c,u)=>{let _=u.findIndex(g=>g.name.value===s.name.value);if(_!==c&&!qqt(s,r)){let g=u[_];return s.arguments=Jqt(s.arguments,g.arguments),null}return s}).filter(yz)}t(Nor,"deduplicateDirectives");function iv(i=[],r=[],s,c){let u=s&&s.reverseDirectives,_=u?i:r,g=u?r:i,b=Nor([..._],c);for(let I of g)if(wor(b,I)&&!qqt(I,c)){let w=b.findIndex(V=>V.name.value===I.name.value),L=b[w];b[w].arguments=Jqt(I.arguments||[],L.arguments||[])}else b.push(I);return b}t(iv,"mergeDirectives");function Gqt(i,r){return r?{...i,arguments:Wqt(r.arguments||[],i.arguments||[],(s,c)=>!Vqt(s.name,c.map(u=>u.name))),locations:[...r.locations,...i.locations.filter(s=>!Vqt(s,r.locations))]}:i}t(Gqt,"mergeDirective");function Wqt(i,r,s){return i.concat(r.filter(c=>s(c,i)))}t(Wqt,"deduplicateLists");function Hqt(i,r,s,c){if(s?.consistentEnumMerge){let g=[];i&&g.push(...i),i=r,r=g}let u=new Map;if(i)for(let g of i)u.set(g.name.value,g);if(r)for(let g of r){let b=g.name.value;if(u.has(b)){let I=u.get(b);I.description=g.description||I.description,I.directives=iv(g.directives,I.directives,c)}else u.set(b,g)}let _=[...u.values()];return s&&s.sort&&_.sort(sM),_}t(Hqt,"mergeEnumValues");var zqt=jo(Fo(),1);function $qt(i,r,s,c){return r?{name:i.name,description:i.description||r.description,kind:s?.convertExtensions||i.kind==="EnumTypeDefinition"||r.kind==="EnumTypeDefinition"?"EnumTypeDefinition":"EnumTypeExtension",loc:i.loc,directives:iv(i.directives,r.directives,s,c),values:Hqt(i.values,r.values,s)}:s?.convertExtensions?{...i,kind:zqt.Kind.ENUM_TYPE_DEFINITION}:i}t($qt,"mergeEnum");var d9=jo(Fo(),1);function Yqt(i){return typeof i=="string"}t(Yqt,"isStringTypes");function Kqt(i){return i instanceof d9.Source}t(Kqt,"isSourceTypes");function hXe(i){let r=i;for(;r.kind===d9.Kind.LIST_TYPE||r.kind==="NonNullType";)r=r.type;return r}t(hXe,"extractType");function gXe(i){return i.kind!==d9.Kind.NAMED_TYPE}t(gXe,"isWrappingTypeNode");function FCe(i){return i.kind===d9.Kind.LIST_TYPE}t(FCe,"isListTypeNode");function lM(i){return i.kind===d9.Kind.NON_NULL_TYPE}t(lM,"isNonNullTypeNode");function Lae(i){return FCe(i)?`[${Lae(i.type)}]`:lM(i)?`${Lae(i.type)}!`:i.name.value}t(Lae,"printTypeNode");var cM;(function(i){i[i.A_SMALLER_THAN_B=-1]="A_SMALLER_THAN_B",i[i.A_EQUALS_B=0]="A_EQUALS_B",i[i.A_GREATER_THAN_B=1]="A_GREATER_THAN_B"})(cM||(cM={}));function Xqt(i,r){return i==null&&r==null?cM.A_EQUALS_B:i==null?cM.A_SMALLER_THAN_B:r==null?cM.A_GREATER_THAN_B:i<r?cM.A_SMALLER_THAN_B:i>r?cM.A_GREATER_THAN_B:cM.A_EQUALS_B}t(Xqt,"defaultStringComparator");function Por(i,r){let s=i.findIndex(c=>c.name.value===r.name.value);return[s>-1?i[s]:null,s]}t(Por,"fieldAlreadyExists");function Ez(i,r,s,c,u){let _=[];if(s!=null&&_.push(...s),r!=null)for(let g of r){let[b,I]=Por(_,g);if(b&&!c?.ignoreFieldConflicts){let w=c?.onFieldTypeConflict&&c.onFieldTypeConflict(b,g,i,c?.throwOnConflict)||Oor(i,b,g,c?.throwOnConflict);w.arguments=Uqt(g.arguments||[],b.arguments||[],c),w.directives=iv(g.directives,b.directives,c,u),w.description=g.description||b.description,_[I]=w}else _.push(g)}if(c&&c.sort&&_.sort(sM),c&&c.exclusions){let g=c.exclusions;return _.filter(b=>!g.includes(`${i.name.value}.${b.name.value}`))}return _}t(Ez,"mergeFields");function Oor(i,r,s,c=!1){let u=Lae(r.type),_=Lae(s.type);if(u!==_){let g=hXe(r.type),b=hXe(s.type);if(g.name.value!==b.name.value)throw new Error(`Field "${s.name.value}" already defined with a different type. Declared as "${g.name.value}", but you tried to override with "${b.name.value}"`);if(!Mae(r.type,s.type,!c))throw new Error(`Field '${i.name.value}.${r.name.value}' changed type from '${u}' to '${_}'`)}return lM(s.type)&&!lM(r.type)&&(r.type=s.type),r}t(Oor,"preventConflicts");function Mae(i,r,s=!1){if(!gXe(i)&&!gXe(r))return i.toString()===r.toString();if(lM(r)){let c=lM(i)?i.type:i;return Mae(c,r.type)}return lM(i)?Mae(r,i,s):FCe(i)?FCe(r)&&Mae(i.type,r.type)||lM(r)&&Mae(i,r.type):!1}t(Mae,"safeChangeForFieldType");var Zqt=jo(Fo(),1);function eJt(i,r,s,c){if(r)try{return{name:i.name,description:i.description||r.description,kind:s?.convertExtensions||i.kind==="InputObjectTypeDefinition"||r.kind==="InputObjectTypeDefinition"?"InputObjectTypeDefinition":"InputObjectTypeExtension",loc:i.loc,fields:Ez(i,i.fields,r.fields,s),directives:iv(i.directives,r.directives,s,c)}}catch(u){throw new Error(`Unable to merge GraphQL input type "${i.name.value}": ${u.message}`)}return s?.convertExtensions?{...i,kind:Zqt.Kind.INPUT_OBJECT_TYPE_DEFINITION}:i}t(eJt,"mergeInputType");var tJt=jo(Fo(),1);function For(i,r){return!!i.find(s=>s.name.value===r.name.value)}t(For,"alreadyExists");function Sz(i=[],r=[],s={}){let c=[...r,...i.filter(u=>!For(r,u))];return s&&s.sort&&c.sort(sM),c}t(Sz,"mergeNamedTypeArray");function nJt(i,r,s,c){if(r)try{return{name:i.name,description:i.description||r.description,kind:s?.convertExtensions||i.kind==="InterfaceTypeDefinition"||r.kind==="InterfaceTypeDefinition"?"InterfaceTypeDefinition":"InterfaceTypeExtension",loc:i.loc,fields:Ez(i,i.fields,r.fields,s,c),directives:iv(i.directives,r.directives,s,c),interfaces:i.interfaces?Sz(i.interfaces,r.interfaces,s):void 0}}catch(u){throw new Error(`Unable to merge GraphQL interface "${i.name.value}": ${u.message}`)}return s?.convertExtensions?{...i,kind:tJt.Kind.INTERFACE_TYPE_DEFINITION}:i}t(nJt,"mergeInterface");var cb=jo(Fo(),1),lJt=jo(dx(),1);var rJt=jo(Fo(),1);function iJt(i,r,s,c){return r?{name:i.name,description:i.description||r.description,kind:s?.convertExtensions||i.kind==="ScalarTypeDefinition"||r.kind==="ScalarTypeDefinition"?"ScalarTypeDefinition":"ScalarTypeExtension",loc:i.loc,directives:iv(i.directives,r.directives,s,c)}:s?.convertExtensions?{...i,kind:rJt.Kind.SCALAR_TYPE_DEFINITION}:i}t(iJt,"mergeScalar");var Tz=jo(Fo(),1);var RCe={query:"Query",mutation:"Mutation",subscription:"Subscription"};function Ror(i=[],r=[]){let s=[];for(let c in RCe){let u=i.find(_=>_.operation===c)||r.find(_=>_.operation===c);u&&s.push(u)}return s}t(Ror,"mergeOperationTypes");function sJt(i,r,s,c){return r?{kind:i.kind===Tz.Kind.SCHEMA_DEFINITION||r.kind===Tz.Kind.SCHEMA_DEFINITION?Tz.Kind.SCHEMA_DEFINITION:Tz.Kind.SCHEMA_EXTENSION,description:i.description||r.description,directives:iv(i.directives,r.directives,s,c),operationTypes:Ror(i.operationTypes,r.operationTypes)}:s?.convertExtensions?{...i,kind:Tz.Kind.SCHEMA_DEFINITION}:i}t(sJt,"mergeSchemaDefs");var oJt=jo(Fo(),1);function aJt(i,r,s,c){if(r)try{return{name:i.name,description:i.description||r.description,kind:s?.convertExtensions||i.kind==="ObjectTypeDefinition"||r.kind==="ObjectTypeDefinition"?"ObjectTypeDefinition":"ObjectTypeExtension",l[Error - 12:02:36 PM] Server process exited with code 1.
[Info - 12:02:36 PM] Connection to server got closed. Server will restart.
true |
For what it's worth, right now you can have multiple configurations in multiple folders, and it should find all of those. As for that crash: do you get any more information than that? Could you rename the config file to end in |
I didn't know you could have apollo.config.js in multiple folders, I'm gonna try that right now. As for the error, I cloned this repo and launch the extension in debug and I was able to get the actual error message
|
Alright as for multi repos I got it working with multiple apollo.config.js files Now I'm facing another issue where the extension doesn't seem to pick up my local schema files in the include. Since my original issue is solved do you want me to open different issues for this and the duplicate definition error ? |
Yeah, let's keep this in a bunch of separate issues. That said, don't expect too many "schema editing" functionality - what you are creating here are client projects, so the focus is on client development - it mostly just reads the schema in and uses that as a starting point. From the back of my mind, I'm not sure how many features we have enabled in schemas. For schema development, you would create a rover project - those even have federation and connectors support, but the functionality is currently still a preview feature: https://www.apollographql.com/docs/graphos/schema-design/connectors/vs-code |
Worth mentioning that in 1 project I need to call into multiple different graphql services I had to move the various apollo.config.mjs files to the root of the project in a folder structure like so
This feels a bit convoluted and I'm not sure why I couldn't put all my graphql projects into 1 apollo.config file considering the extension does support multiple configs through discoverability |
In the end the work around to have multiple apollo.config.js files worked. |
In our project, we're working with multiple different graphs.
Sometimes these graphs are actually external services we do not control but we write queries to target them.
We've been using VS Code GraphQL: Language Feature Support extension for GraphQL LSP
I've been setting up GraphQL Config https://the-guild.dev/graphql/config to tell the VS Code extension which files should use which schema
Here's the config we are currently using
graphql.config.js
You'll notice that we have multiple "client" applications targeting the same schema which allows to better understand which fragments belongs to which project.
Also at the end you'll notice that have a local copy of the
gpl
project that is an external api we call and themetal
project has an sdk providing the schema that we're using as well.Worth noting that we have a separate config for GraphQL Codegen, because the VS Code GraphQL LSP extension doesn't support multiple schema files even though the GraphQL Config standard supports it. So we stitch all our schemas into 1 big schema file and pipe this into the extension instead
Since we are starting to look into Federation, we are investigating better extension to empower our devs and was hoping Apollo's extension would support the GraphQL Config for a more standardized way to provide a great GraphQL experience to our developpers.
The text was updated successfully, but these errors were encountered: