graphqlsp
Version:
https://github.com/microsoft/TypeScript/wiki/Writing-a-Language-Service-Plugin
2 lines (1 loc) • 7.88 kB
JavaScript
;var e=require("typescript/lib/tsserverlibrary"),t=require("typescript"),i=require("graphql-language-service"),n=require("graphql"),r=require("fs"),a=require("path"),s=require("@graphql-codegen/core"),o=require("@graphql-codegen/typescript"),l=require("@graphql-codegen/typescript-operations"),c=require("@graphql-codegen/typed-document-node");function p(e){var t=Object.create(null);return e&&Object.keys(e).forEach((function(i){if("default"!==i){var n=Object.getOwnPropertyDescriptor(e,i);Object.defineProperty(t,i,n.get?n:{enumerable:!0,get:function(){return e[i]}})}})),t.default=e,Object.freeze(t)}var g=p(o),u=p(l),f=p(c);class d{constructor(e,t){this.line=e,this.character=t}setLine(e){this.line=e}setCharacter(e){this.character=e}lessThanOrEqualTo(e){return this.line<e.line||this.line===e.line&&this.character<=e.character}}const m=(e,t)=>{const n=e.getText().slice(1,-1).split("\n"),r=i.onlineParser(),a=r.startState();let s,o=e.pos+1;for(let e=0;e<n.length;e++){const l=o,c=new i.CharacterStream(n[e]);for(;!c.eol();){const i=r.token(c,a),n=c.current();if(n&&l+c.getStartOfToken()<=t&&l+c.getCurrentPosition()>=t){s={line:e,start:c.getStartOfToken()+1,end:c.getCurrentPosition(),string:n,state:a,tokenKind:i};break}}o+=n[e].length+1}return s};function h(t,i){return function t(n){if(i>=n.getStart()&&i<n.getEnd())return e.forEachChild(n,t)||n}(t)}function S(e,t){const i=e.languageService.getProgram();if(i)return i.getSourceFile(t)||void 0}function T(i,n,r){let a=i.template.getText().slice(1,-1);return t.isNoSubstitutionTemplateLiteral(i.template)||0===i.template.templateSpans.length||i.template.templateSpans.forEach((i=>{if(t.isIdentifier(i.expression)){const s=r.languageService.getDefinitionAtPosition(n,i.expression.getStart());if(!s)return;const o=s[0],l=S(r,o.fileName);if(!l)return;const c=h(l,o.textSpan.start);if(!c||!c.parent)return;const p=c.parent;if(e.isVariableDeclaration(p))if(p.initializer&&t.isTaggedTemplateExpression(p.initializer)){const e=T(p.initializer,o.fileName,r);a=a.replace("${"+i.expression.escapedText+"}",e)}else if(p.initializer&&t.isAsExpression(p.initializer)&&t.isTaggedTemplateExpression(p.initializer.expression)){const e=T(p.initializer.expression,o.fileName,r);a=a.replace("${"+i.expression.escapedText+"}",e)}}})),a}function x(o){const l=e=>o.project.projectService.logger.info(`[ts-graphql-plugin] ${e}`);if(l("config: "+JSON.stringify(o.config)),!o.config.schema)throw new Error("Please provide a GraphQL Schema!");o.project.projectService.logger.info("Setting up the GraphQL Plugin");const c=o.config.template||"gql",p=o.config.scalars||{},x=function(e){const t=Object.create(null);for(let i of Object.keys(e.languageService)){const n=e.languageService[i];t[i]=(...t)=>n.apply(e.languageService,t)}return t}(o),y=((e,t)=>{const i={current:null},s=t.endsWith("json"),o=a.resolve(a.dirname(e),t),l=r.readFileSync(o,"utf-8");return r.watchFile(o,(()=>{const e=r.readFileSync(o,"utf-8");return s?n.buildClientSchema(JSON.parse(e)):n.buildSchema(e),i.current=s?n.buildClientSchema(JSON.parse(e)):n.buildSchema(e),i})),i.current=s?n.buildClientSchema(JSON.parse(l)):n.buildSchema(l),i})(o.project.getProjectName(),o.config.schema);return x.getSemanticDiagnostics=l=>{const d=o.languageService.getSemanticDiagnostics(l),m=S(o,l);if(!m)return d;const h=function(i){const n=[];return function i(r){t.isTaggedTemplateExpression(r)||t.isNoSubstitutionTemplateLiteral(r)?n.push(r):e.forEachChild(r,i)}(i),n}(m),x=h.map((e=>{if(t.isNoSubstitutionTemplateLiteral(e)||t.isTemplateExpression(e)){if(!t.isTaggedTemplateExpression(e.parent))return;e=e.parent}return T(e,l,o)})),b=h.map((e=>{let r=e;if(t.isNoSubstitutionTemplateLiteral(r)||t.isTemplateExpression(r)){if(!t.isTaggedTemplateExpression(r.parent))return;r=r.parent}const a=T(r,l,o),s=a.split("\n");let p=r.pos+(c.length+1);const g=i.getDiagnostics(a,y.current).map((e=>{const{start:t,end:i}=e.range;let n=p+t.line;for(let e=0;e<=t.line;e++)n+=e===t.line?t.character:s[e].length;let r=p+i.line;for(let e=0;e<=i.line;e++)r+=e===i.line?i.character:s[e].length;return{...e,start:n+1,length:r-n}})),u=n.parse(a);if(u.definitions.some((e=>e.kind===n.Kind.OPERATION_DEFINITION))){const t=u.definitions.find((e=>e.kind===n.Kind.OPERATION_DEFINITION));t.name||g.push({message:"Operation needs a name for types to be generated.",start:r.pos,length:e.getText().length,range:{},severity:2})}return g})).flat().filter(Boolean).map((t=>({file:m,length:t.length,start:t.start,category:2===t.severity?e.DiagnosticCategory.Warning:e.DiagnosticCategory.Error,code:51001,messageText:t.message.split("\n")[0]})));if(!b.length)try{const e=m.fileName.split("/"),i=e[e.length-1].split(".");if(i[i.length-1]="generated.ts",e[e.length-1]=i.join("."),r.readFileSync(l,"utf-8")!==m.getFullText())return[...b,...d];(async(e,t,i,o)=>{if(!e)return;const l={documents:[{location:"operation.graphql",document:n.parse(i)}],config:{scalars:o,enumsAsTypes:!0,dedupeOperationSuffix:!0,dedupeFragments:!0},filename:t,schema:n.parse(n.printSchema(e)),plugins:[{typescript:{}},{"typescript-operations":{}},{"typed-document-node":{}}],pluginMap:{typescript:g,"typescript-operations":u,"typed-document-node":f}},c=await s.codegen(l);r.writeFile(a.join(t),c,"utf8",(e=>{console.error(e)}))})(y.current,e.join("/"),x.join("\n"),p).then((()=>{h.forEach(((e,r)=>{var a;const s=n.parse(x[r]||""),c=s.definitions.every((e=>e.kind===n.Kind.FRAGMENT_DEFINITION));let p="";if(p=c?s.definitions[0].name.value:(null===(a=s.definitions[0].name)||void 0===a?void 0:a.value)||"",!p)return;p=p.charAt(0).toUpperCase()+p.slice(1);const g=e.parent.getChildren(),u=c?`${p}FragmentDoc`:`${p}Document`,f=` as typeof import('./${i.join(".").replace(".ts","")}').${u}`,d=g.find((e=>t.isImportTypeNode(e)));if(d&&d.getText().includes(u))return;const h={length:1,start:e.end},S=m.text.substring(0,h.start)+f+m.text.substring(h.start+h.length,m.text.length),T=o.project.projectService.getScriptInfo(l),y=T.getSnapshot();m.update(S,{span:h,newLength:f.length}),T.editContent(0,y.getLength(),S),o.languageServiceHost.writeFile(m.fileName,S),T.registerFileUpdate()}))}))}catch(e){}return[...b,...d]},x.getCompletionsAtPosition=(e,r,a)=>{const s=o.languageService.getCompletionsAtPosition(e,r,a)||{isGlobalCompletion:!1,isMemberCompletion:!1,isNewIdentifierLocation:!1,entries:[]},l=S(o,e);if(!l)return s;let p=h(l,r);if(!p)return s;for(;t.isNoSubstitutionTemplateLiteral(p)||t.isToken(p)||t.isTemplateExpression(p);)p=p.parent;if(t.isTaggedTemplateExpression(p)){const{template:a,tag:l}=p;if(!t.isIdentifier(l)||l.text!==c)return s;const g=T(p,e,o),u=m(a,r);if(!u||!y.current)return s;const f=i.getAutocompleteSuggestions(y.current,g,new d(u.line,u.start));let h=[];try{h=n.parse(g).definitions.filter((e=>e.kind===n.Kind.FRAGMENT_DEFINITION))}catch(e){}return{isGlobalCompletion:!1,isMemberCompletion:!1,isNewIdentifierLocation:!1,entries:[...f.map((e=>({kind:t.ScriptElementKind.variableElement,name:e.label,kindModifiers:"declare",sortText:e.sortText||"0"}))),...h.map((e=>({kind:t.ScriptElementKind.variableElement,name:e.name.value,insertText:"..."+e.name.value,kindModifiers:"declare",sortText:"0"}))),...s.entries]}}return s},x.getQuickInfoAtPosition=(n,r)=>{const a=o.languageService.getQuickInfoAtPosition(n,r),s=S(o,n);if(!s)return a;let l=h(s,r);if(!l)return a;for(;t.isNoSubstitutionTemplateLiteral(l)||t.isToken(l)||t.isTemplateExpression(l);)l=l.parent;if(t.isTaggedTemplateExpression(l)){const{template:s,tag:p}=l;if(!t.isIdentifier(p)||p.text!==c)return a;const g=T(l,n,o),u=m(s,r);if(!u||!y.current)return a;const f=i.getHoverInformation(y.current,g,new d(u.line,u.start));return{kind:e.ScriptElementKind.string,textSpan:{start:r,length:1},kindModifiers:"",displayParts:Array.isArray(f)?f.map((e=>({kind:"",text:e}))):[{kind:"",text:f}]}}return a},l("proxy: "+JSON.stringify(x)),x}module.exports=()=>({create:x});