UNPKG

@gqty/cli

Version:

Interactive codegen for GQty

168 lines (146 loc) • 11.4 kB
#! /usr/bin/env node import{SchemaUnionsKey as Re,parseSchemaType as ee}from"gqty";import*as te from"graphql";import{defaultConfig as d}from"./config.mjs";import"@commander-js/extra-typings";import{codegen as we}from"@graphql-codegen/core";import*as Ae from"@graphql-codegen/typescript";import{printSchemaWithDirectives as Me}from"@graphql-tools/utils";import"@graphql-tools/wrap";import"@inquirer/prompts";import"cosmiconfig";import"cross-fetch";import"fast-glob";import I from"lodash-es/sortBy.js";import"prettier";import{formatPrettier as De}from"./prettier.mjs";const{isEnumType:Fe,isInputObjectType:Ve,isInterfaceType:xe,isNullableType:ne,isObjectType:Qe,isScalarType:He,isUnionType:Ue,lexicographicSortSchema:Ge,parse:Ie,isSchema:qe,assertSchema:Le}=te;async function Pe(h,{enumsAsConst:re,enumsAsStrings:se,enumStyle:g=re?"assertion":se?"string":d.enumStyle,introspection:oe=d.introspections,endpoint:A=oe?.endpoint??d.endpoint,javascriptOutput:l=d.javascriptOutput,preImport:ie=d.preImport,react:b=d.react,frameworks:q=d.frameworks,scalarTypes:ae=d.scalarTypes,subscriptions:y=d.subscriptions,transformSchema:L=d.transformSchema}={},{ignoreArgs:C}={}){l&&(g!=="string"&&g!==d.enumStyle&&console.warn('"enumStyle" must be string unions with "javascriptOutput" enabled.'),g="string");const{format:M}=De({parser:"typescript"});if(h=Ge(Le(h)),L&&(h=await L(h,te),!qe(h)))throw Error('"transformSchema" returned an invalid GraphQL Schema!');b??(b=q.includes("react"));const P=q.includes("solid-js"),ce=we({schema:Ie(Me(h)),config:{},documents:[],filename:"gqty.generated.ts",pluginMap:{typescript:Ae},plugins:[{typescript:{constEnums:g==="const",onlyOperationTypes:!0,declarationKind:"interface",addUnderscoreToArgsType:!0,scalars:ae,namingConvention:"keep",enumsAsTypes:g==="string",enumsAsConst:g==="assertion"}}]}),_=h.toConfig(),D=new Set,$=new Set,v=new Set,m={query:{},mutation:{},subscription:{}},F=_.query,V=_.mutation,x=_.subscription,z=new Map,E=new Map,S=new Map;function Q(e){if(Array.isArray(e)){const t=e[2]?S.get(e[0])?.[e[1]]?.[e[2]]:E.get(e[0])?.[e[1]];let r="";return t?.description&&(r+=` `+t.description.trim().split(` `).map(n=>"* "+n).join(` `)),t?.deprecated&&(r+=` * @deprecated `+t.deprecated.trim().replace(/\n/g,". ").trim()),t?.defaultValue&&(r+="\n* @defaultValue `"+t.defaultValue.trim()+"`"),r?`/** ${r} */ `:""}else{const t=z.get(e);return t?`/** ${t.trim().split(` `).map(r=>"* "+r).join(` `)} */ `:""}}const pe=e=>{D.add(e.name);const t=e.getValues(),r={};for(const n of t)(n.deprecationReason||n.description)&&(r[n.name]={description:n.description,deprecated:n.deprecationReason});E.set(e.name,r)},ue=e=>{$.add(e.name)},le=new Map,T=(e,t=e.name)=>{const r=e.getFields(),n=e.getInterfaces();if(n.length){le.set(e.name,n.map(o=>o.name));for(const o of n){let c=f.get(o.name);c==null&&f.set(o.name,c=[]),c.push(e.name)}}const s={__typename:{__type:"String!"}},i={},a={};Object.entries(r).forEach(([o,c])=>{if((c.description||c.deprecationReason)&&(i[o]={description:c.description,deprecated:c.deprecationReason}),s[o]={__type:c.type.toString()},c.args.length){if(C&&c.args.every(({type:u})=>ne(u))&&C(c))return;a[o]||(a[o]={}),s[o].__args=c.args.reduce((p,u)=>(p[u.name]=u.type.toString(),(u.description||u.deprecationReason||u.defaultValue!=null)&&(a[o][u.name]={defaultValue:u.defaultValue!=null?JSON.stringify(u.defaultValue):null,deprecated:u.deprecationReason,description:u.description}),p),{})}}),E.set(e.name,i),S.set(e.name,a),m[t]=s},f=new Map,de=e=>{const t=e.getTypes(),r=[];f.set(e.name,r);for(const n of t)r.push(n.name);m[e.name]={__typename:{__type:"String!"}}},fe=e=>{v.add(e.name);const t=e.getFields(),r={};Object.entries(t).forEach(([n,s])=>{r[n]={__type:s.type.toString()},(s.description||s.deprecationReason||s.defaultValue)&&(s.description,s.deprecationReason,s.defaultValue!=null&&JSON.stringify(s.defaultValue))}),m[e.name]=r},me=e=>{const t={__typename:{__type:"String!"}},r=e.getFields(),n={},s={};Object.entries(r).forEach(([i,a])=>{a.type.toString(),t[i]={__type:a.type.toString()};let o=!0;a.args.length?C&&a.args.every(({type:p})=>ne(p))&&C(a)&&(o=!1):o=!1,o&&(s[i]||(s[i]={}),t[i].__args=a.args.reduce((c,p)=>(c[p.name]=p.type.toString(),(p.description||p.deprecationReason||p.defaultValue!=null)&&(s[i][p.name]={defaultValue:p.defaultValue!=null?JSON.stringify(p.defaultValue):null,deprecated:p.deprecationReason,description:p.description}),c),{})),(a.description||a.deprecationReason)&&(n[i]={description:a.description,deprecated:a.deprecationReason})}),E.set(e.name,n),S.set(e.name,s),m[e.name]=t};_.types.forEach(e=>{e.description&&z.set(e.name,e.description),!(e.name.startsWith("__")||e===F||e===V||e===x)&&(He(e)?ue(e):Qe(e)?T(e):xe(e)?me(e):Ue(e)?de(e):Fe(e)?pe(e):Ve(e)&&fe(e))}),F&&T(F,"query"),V&&T(V,"mutation"),x&&T(x,"subscription");const Y=Array.from(f.entries()).reduce((e,[t,r])=>(m[t].$on={__type:`$${t}!`},e[t]=r,e),{});f.size&&(m[Re]=Y);function he({pureType:e,isArray:t,nullableItems:r,isNullable:n,hasDefaultValue:s}){let i=$.has(e)?`Scalars["${e}"]["input"]`:e;return t&&(r&&(i=`Maybe<${i}>`),i=`Array<${i}>`),(n||s)&&(i=`Maybe<${i}>`),i}function ye({pureType:e,isArray:t,nullableItems:r,isNullable:n}){let s=$.has(e)?`Scalars["${e}"]["output"]`:e;return t&&(r&&(s=`Maybe<${s}>`),s=`Array<${s}>`),n&&(s=`Maybe<${s}>`),s}const ge=new Map;let H=I(Object.entries(m),e=>e[0]).reduce((e,[t,r])=>{const n=(()=>{switch(t){case"query":return"Query";case"mutation":return"Mutation";case"subscription":return"Subscription";default:return t}})();if(v.has(n))return e;const s=new Map;f.has(n)||ge.set(n,s);const i=f.get(n);return e+=` ${Q(n)}export interface ${n} { __typename?: ${i?i.map(a=>`"${a}"`).join(" | "):`"${n}"`}; ${Object.entries(r).reduce((a,[o,c])=>{if(o==="__typename")return s.set(o,`?: "${n}"`),a;const p=S.has(n)?S.get(n):void 0,u=p&&p[o]?p[o]:{},O=ee(c.__type),X=ye(O);let R;if(c.__args){const Z=Object.entries(c.__args);let J=!0;const Ee=Z.reduce((K,[G,Te])=>{const w=ee(Te,u[G]),je=w.isNullable||w.hasDefaultValue?"?:":":";w.isNullable||(J=!1);const Oe=he(w);return K+=`${Q([n,o,G])}${G}${je} ${Oe}; `,K},"");R=`: (args${J?"?:":":"} {${Ee}}) => ${X}`}else R=`${O.isNullable||D.has(O.pureType)||$.has(O.pureType)?"?:":":"} ${X}`;return s.set(o,R),a+=` `+Q([n,o])+o+R,a},"")} } `,e},"");f.size&&(H+=I(Array.from(f.entries()),([e])=>e).map(([e,t])=>` export interface $${e} { ${t.map(r=>`${r}?: ${r}`).join(` `)} }`).join("")),H+=` export interface GeneratedSchema { query: Query mutation: Mutation subscription: Subscription } `;function j(e){return`/** * @type {${e}} */ `}const $e=` ${l?j('import("gqty").QueryFetcher')+"const queryFetcher":"const queryFetcher: QueryFetcher"} = async function ({ query, variables, operationName }, fetchOptions) { // Modify "${A}" if needed const response = await fetch("${A}", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ query, variables, operationName, }), mode: "cors", ...fetchOptions }); return await defaultResponseHandler(response); }; `,U=!!f.size,N=Object.fromEntries([...$,...D].sort().map(e=>[e,!0])),B=JSON.stringify(N),W=I(Object.entries(m),e=>e[0]).reduceRight((e,[t,r])=>`${JSON.stringify(t)}:${JSON.stringify(r)}, ${e}`,U?`[SchemaUnionsKey]: ${JSON.stringify(Y)}`:""),Se=await M(` /** * GQty AUTO-GENERATED CODE: PLEASE DO NOT MODIFY MANUALLY */ ${U?'import { SchemaUnionsKey } from "gqty";':""} ${j('import("gqty").ScalarsEnumsHash')}export const scalarsEnumsHash = ${B}; export const generatedSchema = {${W}}; `),k=[U&&"SchemaUnionsKey",!l&&"type ScalarsEnumsHash"].filter(e=>!!e),be=await M(` /** * GQty AUTO-GENERATED CODE: PLEASE DO NOT MODIFY MANUALLY */ ${ie} ${k.length?`import { ${k.join(", ")} } from "gqty";`:""} ${await ce} export${l?" declare":""} const scalarsEnumsHash: ScalarsEnumsHash${l?";":` = ${B};`} export${l?" declare":""} const generatedSchema ${l?":":"="} {${W}}${l?"":" as const"}; ${H} `),Ce=b?` export const { graphql, useQuery, usePaginatedQuery, useTransactionQuery, useLazyQuery, useRefetch, useMutation, useMetaState, prepareReactRender, useHydrateCache, prepareQuery, ${y?"useSubscription,":""} } = ${l?`${j('import("@gqty/react").ReactClient<import("./schema.generated").GeneratedSchema>')}createReactClient(client, {`:"createReactClient<GeneratedSchema>(client, {"} defaults: { // Enable Suspense, you can override this option for each hook. suspense: true, } }); `.trim():"",_e=P?` export const { createQuery } = createSolidClient(client); `:"";return{clientCode:await M(` /** * GQty: You can safely modify this file based on your needs. */ ${[b?'import { createReactClient } from "@gqty/react";':"",P?'import { createSolidClient } from "@gqty/solid";':"",y?`import { createClient as createSubscriptionsClient } from "${y===!0?"graphql-ws":y}";`:"",l?'import { Cache, createClient, defaultResponseHandler } from "gqty";':'import { Cache, createClient, defaultResponseHandler, type QueryFetcher } from "gqty";',l?'import { generatedSchema, scalarsEnumsHash } from "./schema.generated";':'import { generatedSchema, scalarsEnumsHash, type GeneratedSchema } from "./schema.generated";'].filter(Boolean).join(` `)} ${$e} ${y?`const subscriptionsClient = typeof window !== "undefined" ? createSubscriptionsClient({ lazy: true, url: () => { // Modify if needed const url = new URL("${A}", window.location.href); url.protocol = url.protocol.replace('http', 'ws'); return url.href; } }) : undefined;`:""} const cache = new Cache( undefined, /** * Cache is valid for 30 minutes, but starts revalidating after 5 seconds, * allowing soft refetches in background. */ { maxAge: 5000, staleWhileRevalidate: 30 * 60 * 1000, normalization: true, } ); ${l?`${j('import("gqty").GQtyClient<import("./schema.generated").GeneratedSchema>')}export const client = createClient({ schema: generatedSchema, scalars: scalarsEnumsHash, cache, fetchOptions: { fetcher: queryFetcher, ${y?"subscriber: subscriptionsClient":""} }, }); `:` export const client = createClient<GeneratedSchema>({ schema: generatedSchema, scalars: scalarsEnumsHash, cache, fetchOptions:{ fetcher: queryFetcher, ${y?"subscriber: subscriptionsClient":""} }, }); `} // Core functions export const { resolve, subscribe, schema } = client; // Legacy functions export const { query, mutation, mutate, subscription, resolved, refetch, track } = client; ${Ce} ${_e} export * from "./schema.generated"; `),generatedSchema:m,isJavascriptOutput:l,javascriptSchemaCode:Se,scalarsEnumsHash:N,schemaCode:be}}export{Pe as generate};