@getcronit/pylon-dev
Version:
CLI for creating a Pylon
241 lines (204 loc) • 37.8 kB
JavaScript
import{program as V}from"commander";import{spawn as ze}from"child_process";import O from"consola";import We from"dotenv";var se="2.0.0-canary-20260313082843.34aeeac66642f7cc26d40ebdc0f36eb226a68aca";import{PostHog as Pe}from"posthog-node";import Ne from"conf";import{readFileSync as xe}from"fs";import{randomUUID as re}from"crypto";var De={distinctId:{type:"string",default:re()}},ke=new Ne({projectName:"pylon",schema:De}),j=ke.get("distinctId"),E=re(),I=new Pe("phc_KN4qCOcCdkXp6sHLIuMWGRfzZWuNht69oqv5Kw5rGxj",{host:"https://eu.i.posthog.com",disabled:process.env.PYLON_DISABLE_TELEMETRY==="true"}),Ce=()=>{let c;try{c=JSON.parse(xe("./package.json","utf8"))}catch{c={}}let n=c.dependencies||{},t=c.devDependencies||{},e=c.peerDependencies||{};return{dependencies:n,devDependencies:t,peerDependencies:e}},R=Ce(),Y=async()=>{try{let n=(await import(`${process.cwd()}/.pylon/config.js`)).config,t=JSON.parse(JSON.stringify(n));return Object.keys(t).length===0?!1:t}catch{return!1}};import Le from"path";import{context as $e}from"esbuild";import Be from"esbuild-plugin-tsc";import ue from"fs/promises";import B from"path";import ae from"fs/promises";async function k(c,n){try{if(await ae.readFile(c,"utf8")===n)return!1}catch(t){if(t.code!=="ENOENT")throw t}return await ae.writeFile(c,n,"utf8"),!0}import Ie from"esbuild";import{readFileSync as Ae}from"fs";import{dirname as Oe,resolve as je}from"path";import S from"typescript";async function oe(c,n=".pylon/config.js"){let t=je(c),e=Ae(t,"utf8"),a=S.createSourceFile(t,e,S.ScriptTarget.ESNext,!0),r=new Map,s=new Map;function i(p,y){if(S.isIdentifier(p))r.set(p.text,y);else if(S.isObjectBindingPattern(p)||S.isArrayBindingPattern(p))for(let g of p.elements)S.isBindingElement(g)&&i(g.name,y)}S.forEachChild(a,p=>{if(S.isVariableStatement(p))for(let y of p.declarationList.declarations)i(y.name,p);else if(S.isFunctionDeclaration(p)&&p.name)r.set(p.name.text,p);else if(S.isClassDeclaration(p)&&p.name)r.set(p.name.text,p);else if(S.isEnumDeclaration(p)&&p.name)r.set(p.name.text,p);else if(S.isInterfaceDeclaration(p)&&p.name)r.set(p.name.text,p);else if(S.isTypeAliasDeclaration(p)&&p.name)r.set(p.name.text,p);else if(S.isImportDeclaration(p)){let y=p.importClause;if(y&&(y.name&&s.set(y.name.text,p),y.namedBindings))if(S.isNamedImports(y.namedBindings))for(let g of y.namedBindings.elements)s.set(g.name.text,p);else S.isNamespaceImport(y.namedBindings)&&s.set(y.namedBindings.name.text,p)}});let l=new Set,d=new Set,f=new Set;function o(p){if(f.has(p))return;f.add(p);let y=r.get(p);y&&(l.add(y),u(y));let g=s.get(p);g&&d.add(g)}function u(p){S.forEachChild(p,y=>{if(S.isIdentifier(y)){let g=y.parent;if(S.isPropertyAccessExpression(g)&&g.name===y||S.isPropertyAssignment(g)&&g.name===y||S.isMethodDeclaration(g)&&g.name===y||S.isClassDeclaration(g)&&g.name===y||S.isFunctionDeclaration(g)&&g.name===y)return;o(y.text)}else u(y)})}let m=r.get("config");m&&(l.add(m),u(m));let T=[];for(let p of a.statements)S.isImportDeclaration(p)?d.has(p)&&T.push(p.getFullText(a).trim()):l.has(p)&&T.push(p.getFullText(a).trim());let h=T.join(`
`);!r.has("config")&&!h.includes("export const config")&&(h+=`
export const config = {}`),await Ie.build({stdin:{contents:h,resolveDir:Oe(t),sourcefile:t,loader:"ts"},bundle:!0,format:"esm",outfile:n,packages:"external"})}import Ee from"fs/promises";import q from"path";var ce=({getBuildDefs:c,outputDir:n})=>({name:"inject-code",setup(t){t.onLoad({filter:/src[\/\\]index\.ts$/,namespace:"file"},async e=>{if(q.relative(process.cwd(),e.path)!==q.join("src","index.ts"))return;let{typeDefs:r,resolvers:s}=c(),i=le(s),l=await Ee.readFile(e.path,"utf-8"),d=q.join(process.cwd(),n,"schema.graphql");await k(d,r);let f=q.join(process.cwd(),n,"resolvers.js");return await k(f,`export const resolvers = ${i}`),{loader:"ts",contents:`import {executeConfig} from "@getcronit/pylon"
var __internalPylonConfig = {config: {}}
try {
__internalPylonConfig = await import('./config.js')
} catch (e) {
}
await executeConfig(__internalPylonConfig.config)
`+l+`
import {handler as __internalPylonHandler} from "@getcronit/pylon"
app.use(__internalPylonHandler({
typeDefs: ${JSON.stringify(r)},
graphql,
resolvers: ${i},
}))
await executeConfig(__internalPylonConfig.config, {
pluginsStrategy: "last"
})
`}})}});function le(c){return`{${Object.entries(c).map(([t,e])=>{if(e!==void 0)return typeof e=="string"?`${t}:${e}`:typeof e=="function"?`${t}:${e.toString()}`:typeof e=="object"&&!Array.isArray(e)?`${t}:${le(e)}`:`${t}:${JSON.stringify(e)}`}).join(",")}}`}import Re from"path";import pe from"fs/promises";import $ from"consola";var fe=({dir:c,onBuild:n})=>({name:"notify",async setup(t){let e=async()=>{let s=Re.join(c,"schema.graphql");try{await pe.access(s)}catch{return null}return await pe.readFile(s,"utf-8")},a=await e(),r=Date.now();t.onStart(async()=>{r=Date.now(),$.start("[Pylon]: Building...")}),t.onEnd(async s=>{if(s.errors.length>0){for(let u of s.errors)$.error(`[Pylon]: ${u.text}
${u.location?`at ${u.location.file}:${u.location.line}:${u.location.column}`:""}
${u.detail?u.detail:""}`);throw new Error("Failed to build Pylon")}if(s.warnings.length>0)for(let u of s.warnings)$.warn(u);let i=Date.now()-r,l=Object.keys(s.metafile.inputs).length,d=Object.values(s.metafile.outputs).reduce((u,m)=>u+m.bytes,0),f=await e();$.success(`[Pylon]: Built in ${i}ms`);let o=f!==a;o&&($.info("[Pylon]: Schema updated"),a=f),n&&await n({totalFiles:l,totalSize:d,schemaChanged:o,duration:i})})}});var U=class{sfiFilePath;outputDir;constructor(n,t="./.pylon"){this.sfiFilePath=n,this.outputDir=t}async initBuildPlugins(n){let t=B.join(process.cwd(),this.outputDir,"config.js");await oe(this.sfiFilePath,t);let e;try{e=(await import(t)).config}catch(s){console.error("Error loading config",s)}let a=[],r=e?.plugins||[];for(let s of r)if(s.build){let i=s.build({onBuild:n.onBuild});a.push(i)}return a}async build(n){let t=B.join(process.cwd(),this.sfiFilePath),e=B.join(process.cwd(),this.outputDir);await ue.mkdir(e,{recursive:!0});let a={name:"write-on-end",setup(i){i.onEnd(async l=>{await Promise.all(l.outputFiles.map(async d=>{await ue.mkdir(B.dirname(d.path),{recursive:!0}),await k(d.path,d.text)}))})}},r=await $e({write:!1,platform:"node",logLevel:"silent",metafile:!0,entryPoints:[t],outdir:e,bundle:!0,format:"esm",sourcemap:"inline",packages:"external",plugins:[fe({dir:e,onBuild:async i=>{await n.onBuild?.(i)}}),ce({getBuildDefs:n.getBuildDefs,outputDir:this.outputDir}),Be({tsconfigPath:B.join(process.cwd(),"tsconfig.json")}),a]});n.skipInitialBuild||await r.rebuild();let s=await this.initBuildPlugins({onBuild:()=>{n.onBuild?.({totalFiles:0,totalSize:0,schemaChanged:!1,duration:0})}});if(!n.skipInitialBuild)for(let i of s)await(await i).rebuild();return{watch:async()=>{for(let i of s)await(await i).watch();return await r.watch()},rebuild:async()=>{for(let i of s)await(await i).rebuild();await r.rebuild()},dispose:async()=>{for(let i of s)await(await i).dispose();await r.dispose()},cancel:async()=>{for(let i of s)await(await i).cancel();await r.cancel()}}}};import N from"typescript";import X from"consola";import F from"typescript";import v from"typescript";import b from"typescript";var me=c=>(c.flags&b.TypeFlags.Object||c.flags&b.TypeFlags.NonPrimitive)&&c.getProperties().length===0&&c.getCallSignatures().length===0,C=(c,n)=>{let t=c.typeToTypeNode(n,void 0,void 0),e=!!(t&&(t.kind===b.SyntaxKind.ArrayType||t.kind===b.SyntaxKind.TupleType));return!e&&(n.getSymbol()?.getName()==="Array"||n.getBaseTypes()?.some(r=>r.getSymbol()?.getName()==="Array"))?!0:e};var w=c=>c.flags&b.TypeFlags.String||c.flags&b.TypeFlags.Number||c.flags&b.TypeFlags.Boolean||c.flags&b.TypeFlags.StringLiteral||c.flags&b.TypeFlags.NumberLiteral||c.flags&b.TypeFlags.BooleanLiteral,ye=c=>!!(c.flags&b.TypeFlags.StringLiteral||c.flags&b.TypeFlags.NumberLiteral||c.flags&b.TypeFlags.BooleanLiteral),Z=c=>!!(c.flags&b.TypeFlags.Never),J=c=>c.getCallSignatures().length>0,x=c=>{if(w(c)||!c.isUnion())return!1;let n=c.types.filter(e=>!(e.flags&b.TypeFlags.Undefined||e.flags&b.TypeFlags.Null));return n.length===0?!1:n.every(e=>e.flags&b.TypeFlags.StringLiteral||e.flags&b.TypeFlags.NumberLiteral||e.flags&b.TypeFlags.BooleanLiteral)},L=c=>c.getSymbol()?.getName()==="Promise",_=c=>{if(c.objectFlags&b.ObjectFlags.Reference){let e=c.typeArguments;if(e&&e.length>0)return e[0]}},de=c=>{if(!c.isUnion())return{type:c,wasOptional:!1};let t=c.types.filter(e=>!(e.flags&b.TypeFlags.Undefined||e.flags&b.TypeFlags.Null)).length!==c.types.length;return{type:c.getNonNullableType(),wasOptional:t}};function he(c,n){let t=n;if(t.isUnion()){let r=t.types.filter(l=>!(l.flags&b.TypeFlags.Object&&l.objectFlags&b.ObjectFlags.Reference&&l.typeArguments?.length)),s=t.types.filter(l=>l.flags&b.TypeFlags.Object&&l.objectFlags&b.ObjectFlags.Reference&&l.typeArguments?.length).map(l=>l.typeArguments[0]),i=r.filter(l=>!s.some(d=>d===l));t=c.getUnionType(i)}let e=[];if(C(c,t)||w(t)||x(t))return e;let a=[];a=t.resolvedProperties||t.getProperties()||[];for(let r of a)(r.valueDeclaration&&!(b.getCombinedModifierFlags(r.valueDeclaration)&b.ModifierFlags.Private)&&!r.getName().startsWith("#"))!==!1&&e.push(r);return e}var P=c=>{let n=c.replace(/[^0-9a-zA-Z_]/g,"_");for(;n.startsWith("_");)n=n.slice(1);return n||"JSONObject"},H=c=>!!c.getSymbol()?.getDeclarations()?.some(n=>n.getSourceFile().fileName.includes("@repeaterjs"));var Q=class{checker;schema;program;typesNameMap=new Map;inputsNameMap=new Map;unions=[];enums=[];constructor(n,t,e){this.checker=n,this.schema=t,this.program=e}getExistingTypeByName(n,t){for(let[e,a]of t.entries())if(a===n)return e}getUniqueName(n,t,e,a){let r=t,s=1;for(;;){let i=this.getExistingTypeByName(r,e);if(!i)break;if(this.checker.isTypeAssignableTo(n,i)&&this.checker.isTypeAssignableTo(i,n))return r;let l=`_${s}`;r=a?a(l):`${t}${l}`,s++}return r}isTypeSymbol(n){return n?!!(n.flags&(v.SymbolFlags.TypeAlias|v.SymbolFlags.Interface|v.SymbolFlags.Class|v.SymbolFlags.Enum|v.SymbolFlags.Type)):!1}getTypeDefinition=(n,t={isInputType:!1,dryRun:!1})=>{let{type:e,wasOptional:a}=de(n);if(e.flags&v.TypeFlags.Void||e.flags&v.TypeFlags.Undefined||e.flags&v.TypeFlags.Null)return{name:"Void",isList:!1,isRequired:!1};if(e.flags&v.TypeFlags.Any||Z(e))return{name:Z(e)?"JSONObject":"Any",isList:!1,isRequired:t.isRequired!==void 0?t.isRequired:!a};if(H(e)){let f=this.checker.getTypeArguments(e)[0];if(f)return this.getTypeDefinition(f,t)}if(L(e)){let f=_(e);if(f)return this.getTypeDefinition(f,t)}let r=t.isRequired!==void 0?t.isRequired:!a;if(me(e))return{name:"JSONObject",isList:!1,isRequired:r};let s=t.isInputType?this.inputsNameMap:this.typesNameMap;if(s.has(e))return{name:s.get(e),isList:!1,isRequired:r};let i=e.aliasSymbol?.escapedName?.toString()||e.symbol?.escapedName.toString();if(i==="__type"||i==="__object"||!i){let f=e.aliasSymbol||e.symbol;if(f){let o=f.getDeclarations();if(o)for(let u of o){if(u.name){i=u.name.escapedText?.toString();break}let m=u.parent;for(;m;){if((v.isVariableDeclaration(m)||v.isPropertyDeclaration(m)||v.isPropertySignature(m)||v.isParameter(m)||v.isPropertyAssignment(m))&&v.isIdentifier(m.name)){i=m.name.escapedText.toString();break}m=m.parent}if(i)break}}}let l=t.propertyName;(i==="__type"||i==="__object"||!i||t.isInputType&&l&&!e.aliasSymbol)&&!w(e)&&!(i&&this.schema.scalars.includes(i))&&l&&(i=l.charAt(0).toUpperCase()+l.slice(1));let d=f=>{let o=f.aliasSymbol||f.symbol;if(!o)return!1;let u=o.getDeclarations();return u?u.some(m=>{let T=m.getSourceFile();return this.program.isSourceFileDefaultLibrary(T)||T.fileName.includes("node_modules/typescript/lib")}):!1};if(i){let f=e,o=this.checker.getTypeArguments(f);o.length===0&&e.aliasTypeArguments&&(o=e.aliasTypeArguments);let u=d(e),m=!!e.aliasSymbol,T=m&&!u;if(o.length>0&&!T&&(!e.aliasSymbol||e.aliasSymbol.escapedName.toString()!==i||e.aliasTypeArguments)){let h=o;u&&m&&(h=o.filter((g,D)=>D===0?!0:!(ye(g)||x(g))));let y=h.map(g=>this.getTypeDefinition(g,{...t,dryRun:t.dryRun}).name).join("");u&&m?i=y:i.startsWith(y)||(i=`${y}${i}`)}i=P(i),i=i.charAt(0).toUpperCase()+i.slice(1)}if(i==="JsonValue"||i==="JsonObject")return{name:"JSON",isList:!1,isRequired:r};if(i==="JsonArray")return{name:"JSON",isList:!0,isRequired:!0,isListRequired:r};if(i&&!this.schema.scalars.includes(i)){t.isInputType&&!i.endsWith("Input")&&!x(e)&&(i=`${i}Input`);let f;if(e.aliasTypeArguments||e.typeArguments){let o=e,u=this.checker.getTypeArguments(o);if(u.length===0&&e.aliasTypeArguments&&(u=e.aliasTypeArguments),u.length>0){let m=u[0],h=this.getTypeDefinition(m,{...t,dryRun:t.dryRun}).name;if(i.startsWith(h)){let p=i.slice(h.length);f=y=>`${h}${y}${p}`}}}i=this.getUniqueName(e,i,s,f)}if(i&&this.schema.scalars.includes(i))return{name:i,isList:!1,isRequired:r};if(s.has(e))return{name:s.get(e),isList:!1,isRequired:r};if(C(this.checker,e)){let f=this.checker.getIndexTypeOfType(e,v.IndexKind.Number);if(f){let o=this.getTypeDefinition(f,t);return{name:o.name,isList:!0,isRequired:o.isRequired,isListRequired:r}}}else if(x(e)){let f=this.checker.typeToTypeNode(e,void 0,void 0),u=e.types.map(m=>{if(m.isLiteral()){let T=m.value?.toString();if(!T)throw new Error("Enum member name is undefined");return P(T)}throw new Error("Invalid type for enum member")});u.length>0&&(i=i||f.typeName?.symbol?.escapedName,i||(i=u.join("_").toUpperCase(),i=t.isInputType?`${i}Input`:i),t.dryRun||this.enums.find(m=>m.name===i)||(this.enums.push({name:i,values:u,rawType:e}),this.typesNameMap.set(e,i),this.inputsNameMap.set(e,i)))}else if(w(e)){let f=this.checker.typeToString(e);return e.flags&v.TypeFlags.StringLiteral?f="String":e.flags&v.TypeFlags.NumberLiteral?f="Number":e.flags&v.TypeFlags.BooleanLiteral?f="Boolean":e.flags&v.TypeFlags.String?f="String":e.flags&v.TypeFlags.Number?f="Number":e.flags&v.TypeFlags.Boolean&&(f="Boolean"),{name:P(f),isList:!1,isRequired:r}}else if(e.isIntersection()){let o=e.types.map(u=>this.getTypeDefinition(u,t).name);i=P(i||o.join("And"))}else if(e.isUnion()){let f=e.types,o=e.types.length===f.length,u=f.some(p=>{let y=C(this.checker,p)?this.checker.getIndexTypeOfType(p,v.IndexKind.Number):p;return y?w(y)||x(y):!0}),m=[...new Set(f.map(p=>this.getTypeDefinition(p,{...t,isRequired:o})))],T=m.filter(p=>p.isList);for(let p of T){let y=m.findIndex(g=>g.name===p.name&&!g.isList);y>-1&&m.splice(y,1)}let h=m.map(p=>p.name);if(i=P(i||h.join("Or")),i&&(i=this.getUniqueName(e,i,s)),m.length>1&&!t.isInputType&&!u)t.dryRun||this.unions.find(p=>p.name===i)||this.unions.push({name:i,types:h,rawType:e});else{if(m.some(g=>g.name==="JSON"||g.name==="JSONObject"||g.name==="Any"))return{name:"JSON",isList:!1,isRequired:r};let p=m[0];if(!p)throw new Error("Cannot get type definition");let y=m.some(g=>g.isList&&g.name===p.name);return{name:p.name,isList:y,isRequired:r}}}else if(J(e)){let o=e.getCallSignatures()[0]?.getReturnType();if(o&&L(o)){let u=_(o);u&&(o=u)}if(o)return this.getTypeDefinition(o,t)}return i||(i="JSONObject"),t.dryRun||s.set(e,i),{name:i,isList:!1,isRequired:r}};getUnions(){return this.unions}getEnums(){return this.enums}typeDefinitionToGraphQLType=n=>{let t=n.name,{isList:e,isRequired:a,isListRequired:r}=n;return a&&(t=`${t}!`),e&&(t=`[${t}]`,r&&(t=`${t}!`)),t}};var G=class{schema;checker;program;sfiFile;typeDefinitionBuilder;constructor(n,t,e){this.schema={types:[],inputs:[],interfaces:[],unions:[],enums:[],scalars:["ID","Int","Float","Number","Any","Void","JSONObject","File","Date","JSON","String","Boolean"]},this.checker=n,this.sfiFile=t,this.program=e,this.typeDefinitionBuilder=new Q(n,this.schema,e)}parse(n){let t=this.makeReferenceSchema(n);for(let[e,a]of t.types){let r;n.Query===e?r="Query":n.Mutation===e?r="Mutation":n.Subscription===e&&(r="Subscription"),this.processSchemaReference(e,a,r,"types")}for(let[e,a]of t.inputs)this.processSchemaReference(e,a,void 0,"inputs");this.extractForbiddenFieldNamesFromSchema(),this.schema.unions=this.typeDefinitionBuilder.getUnions().map(e=>({...e,description:this.getTypeDocumentation(e.rawType)})),this.schema.enums=this.typeDefinitionBuilder.getEnums().map(e=>({...e,description:this.getTypeDocumentation(e.rawType)})),this.schema.types=this.schema.types.filter(e=>!this.schema.enums.find(a=>a.name===e.name)),this.schema.inputs=this.schema.inputs.filter(e=>!this.schema.enums.find(a=>a.name===e.name)),this.schema.unions.forEach(e=>{let a=this.checkIfInterfaceIsPossibleForUnion(e,this.schema.types);a&&(this.schema.interfaces.push(a),this.schema.unions=this.schema.unions.filter(r=>r.name!==e.name),this.schema.types.map(r=>{if(e.types.includes(r.name))return r.implements||(r.implements=[]),r.implements.push(a.name),r}))});for(let[e,a]of t.inheritanceMap){let r=P(this.checker.typeToString(e)),s=`I${r}`,i=this.schema.types.find(l=>l.name===r);if(i){let l=this.schema.interfaces.find(f=>f.name===s);if(!l){l={name:s,description:i.description,fields:[...i.fields],implements:[],__resolveType:void 0};let f=e.getBaseTypes();f&&f.forEach(o=>{let m=`I${P(this.checker.typeToString(o))}`;if(t.inheritanceMap.has(o))l.implements.push(m);else{let T=o.getSymbol();if(T){for(let[h]of t.inheritanceMap)if(h.getSymbol()===T){l.implements.push(m);break}}}}),this.schema.interfaces.push(l)}i.implements||(i.implements=[]),i.implements.includes(s)||i.implements.push(s);let d=f=>{for(let o of f){let u=P(this.checker.typeToString(o)),m=this.schema.types.find(h=>h.name===u);m&&(m.implements||(m.implements=[]),m.implements.includes(s)||m.implements.push(s));let T=t.inheritanceMap.get(o);if(!T){let h=o.getSymbol();if(h){for(let[p,y]of t.inheritanceMap)if(p.getSymbol()===h){T=y;break}}}T&&d(T)}};d(a),this.schema.types.forEach(f=>{f.fields.forEach(o=>{o.type.name===r&&(o.type.name=s)})})}}for(let[e,a]of t.classImplementsMap){this.schema.types.map(r=>{let s=this.schema.types.find(i=>i.rawType===e);return s&&(s.implements=Array.from(new Set([...s.implements||[],...a.map(i=>this.checker.typeToString(i))]))),r});for(let r of a){let s=this.schema.types.find(i=>i.rawType===r);s&&(this.schema.interfaces.push({name:this.checker.typeToString(r),description:this.getTypeDocumentation(r),fields:s.fields}),this.schema.types=this.schema.types.filter(i=>i.rawType!==r))}}this.schema.types=this.schema.types.map(e=>((e.implements||this.schema.unions.find(a=>a.types.includes(e.name)))&&(e.fields=e.fields.filter(a=>a.type.name!=="Void")),e)),this.schema.unions=this.schema.unions.map(e=>({...e,__resolveType:this.getResolveTypeForUnionOrInterface(e,this.schema.types)})),this.schema.interfaces=this.schema.interfaces.map(e=>({...e,__resolveType:this.getResolveTypeForUnionOrInterface(e,this.schema.types)}))}checkIfInterfaceIsPossibleForUnion(n,t){let e=n.types.map(s=>{let i=t.find(l=>l.name===s);if(!i)throw new Error(`Type ${s} not found`);return i}),r=e[0].fields.filter(s=>e.every(i=>i.fields.some(l=>JSON.stringify(l)===JSON.stringify(s))));return r.length>0?{name:n.name,description:n.description,fields:r}:null}getResolveTypeForUnionOrInterface(n,t){let e="types"in n?t.filter(i=>n.types.includes(i.name)):t.filter(i=>i.implements?.includes(n.name));e.sort((i,l)=>l.fields.length-i.fields.length);let a=new Map;e.forEach(i=>{let l=i.fields.map(d=>d.name).sort().join(", ");if(a.has(l)){let d=a.get(l);X.warn(`Warning: Union types "${i.name}" and "${d?.name}" have the same fields: [${l}].
Consider differentiating these types by adding unique fields or using different type names.
This may cause ambiguity in type resolution.`)}else a.set(l,i)});let s=`function resolveType(node) { if (!node || typeof node !== 'object') return null; ${e.map(i=>{let l=e.filter(o=>o.name!==i.name),d=new Set(l.flatMap(o=>o.fields.map(u=>u.name))),f=i.fields.find(o=>o.type.isRequired&&!d.has(o.name));if(f)return`if ("${f.name}" in node && node["${f.name}"] !== undefined) { return '${i.name}'; }`;{let o=i.fields.map(u=>`"${u.name}" in node && node["${u.name}"] !== undefined`).join(" && ");return o.length>0?`if (${o}) { return '${i.name}'; }`:""}}).filter(i=>i.length>0).join(" ")} return null; }`;return new Function("return "+s)()}toString(){let{typeDefinitionToGraphQLType:n}=this.typeDefinitionBuilder,t=a=>a?`"""
${a}
"""
`:"",e="";for(let a of this.schema.inputs){e+=t(a.description),e+=`input ${a.name} {
`,a.fields.length===0&&(e+=` _ : String
`);for(let r of a.fields)e+=`${t(r.type.description)}`,e+=` ${r.name}: ${n(r.type)}
`;e+=`}
`}for(let a of this.schema.types)if(a.fields.length!==0){e+=t(a.description),e+=`type ${a.name}`,a.implements&&(e+=` implements ${[...a.implements].sort((r,s)=>r.localeCompare(s)).join(" & ")}`),e+=` {
`;for(let r of a.fields){let s="";r.args.length>0&&(s=`(${r.args.map(i=>`${t(i.type.description)}${i.name}: ${n(i.type)}`).join(", ")})`),e+=`${t(r.type.description)}`,e+=`${r.name}${s}: ${n(r.type)}
`}e+=`}
`}for(let a of this.schema.unions)e+=t(a.description),e+=`union ${a.name} = ${a.types.join(" | ")}
`;for(let a of this.schema.interfaces){e+=t(a.description),e+=`interface ${a.name}`,a.implements&&a.implements.length>0&&(e+=` implements ${[...a.implements].sort((r,s)=>r.localeCompare(s)).join(" & ")}`),e+=` {
`;for(let r of a.fields)e+=`${t(r.type.description)}`,e+=`${r.name}: ${n(r.type)}
`;e+=`}
`}for(let a of this.schema.scalars)e+=`scalar ${a}
`;for(let a of this.schema.enums){e+=t(a.description),e+=`enum ${a.name} {
`;for(let r of a.values)e+=` ${r}
`;e+=`}
`}return e}getSchema(){return this.schema}getResolvers(){let n={};for(let t of this.schema.unions)n[t.name]={__resolveType:t.__resolveType};for(let t of this.schema.interfaces)n[t.name]={__resolveType:t.__resolveType};return n}processSchemaReference(n,t,e,a="types"){let{getTypeDefinition:r}=this.typeDefinitionBuilder,s=a==="inputs",i=r(n,{isInputType:s}),l=e||i.name,d=this.schema[a].find(f=>f.name===l);if(d){if(d.fields.length>0)return}else{if(this.schema.scalars.includes(l))return;this.schema[a].push({name:l,description:this.getTypeDocumentation(n),fields:[],rawType:C(this.checker,n)&&(n.getNumberIndexType()||n.getStringIndexType())||n}),d=this.schema[a][this.schema[a].length-1]}for(let[f,o]of Object.entries(t)){let u=o.returnType,m=r(u,{isInputType:s,propertyName:f});if(a==="types"){let T={name:f,type:{...m,description:this.getSymbolDocumentation(o.symbol)},args:[]};if(o.args)for(let[h,p]of Object.entries(o.args)){let y=p,g=r(y.type,{isInputType:!0,propertyName:f+h.charAt(0).toUpperCase()+h.slice(1),isRequired:p.isRequired});this.schema.scalars.includes(this.checker.typeToString(y.type))&&(g.name=this.checker.typeToString(y.type)),T.args.push({name:h,type:{...g,description:y.documentation}})}d.fields.push(T)}else if(a==="inputs"){let T={name:f,type:{...m,description:this.getTypeDocumentation(u)}};d.fields.find(h=>h.name===T.name)||d.fields.push(T)}}}getSymbolDocumentation(n){let t="";t+=F.displayPartsToString(n.getDocumentationComment(this.checker));let e=n.getJsDocTags(this.checker).map(a=>`@${a.name} ${F.displayPartsToString(a.text)}`).join(`
`);return e&&(t+=`
`+e),t}getTypeDocumentation=n=>{let t=n.getSymbol();return t?this.getSymbolDocumentation(t):""};extractForbiddenFieldNamesFromSchema(){let n=/^[_A-Za-z][_0-9A-Za-z]*$/,t=e=>n.test(e)?e.startsWith("__"):!0;for(let e of this.schema.types)e.fields=e.fields.filter(a=>!t(a.name));for(let e of this.schema.inputs)e.fields=e.fields.filter(a=>!t(a.name))}makeReferenceSchema(n){let t={types:new Map,inputs:new Map,classImplementsMap:new Map,inheritanceMap:new Map},e=(s,i={},l="types",d=[])=>{if(t[l].has(s))return;if(H(s)){let o=this.checker.getTypeArguments(s)[0];e(o,i,l,[...d,"REPEATER_ITEM"]);return}if(this.checker.typeToString(s)!=="[]"&&!this.schema.scalars.includes(this.checker.typeToString(s))&&!w(s)){if(L(s)){if(l==="inputs")return;let o=_(s);o&&e(o,i,l,[...d,"PROMISE"]);return}if(s.getSymbol()?.flags&F.SymbolFlags.Class){let o=s.getBaseTypes();o&&o.forEach(u=>{u.getSymbol()?.flags&F.SymbolFlags.Class&&(t.inheritanceMap.has(u)||t.inheritanceMap.set(u,[]),t.inheritanceMap.get(u).push(s),e(u))})}if(s.isUnion())if(x(s))t[l].has(s)||t[l].set(s,{}),e(s,i,l,[...d,"ENUM"]);else if(l==="types")s.types.forEach(o=>{o.flags&F.TypeFlags.Null||o.flags&F.TypeFlags.Undefined||w(o)||e(o,i,l,[...d,o.symbol?.getName()||`N/A ${this.checker.typeToString(o)}`])});else{let o=s.getNonNullableType();o.isUnion()&&!w(o)&&(X.warn(`Warning: Union types in input fields are not supported yet. Defaulting to the first type (${this.checker.typeToString(o)}) at path: ${d.join(" > ")}`),o=o.types[0]),e(o,i,l,[...d,"NON_NULLABLE"])}else if(J(s)){if(l==="inputs")return;if(!i.parentType)throw new Error("Cannot have a function without a parent type");let o=s.getCallSignatures()[0],u=o?.getParameters()||[],m=o?.getReturnType(),T=t[l].get(i.parentType)[i.propetyName];u.forEach(h=>{let p=this.checker.getTypeOfSymbolAtLocation(h,this.sfiFile);if(this.checker.isTupleType(p))p.target.labeledElementDeclarations.forEach((D,Se)=>{let ie=this.checker.getTypeAtLocation(D),ne=D.name.text,ve=this.checker.getSymbolAtLocation(D),we=this.getSymbolDocumentation(ve||h);T.args[ne]={type:ie,isRequired:D.initializer===void 0?void 0:!1,documentation:we},e(ie,{parentType:s},"inputs",[...d,ne])});else if(h.valueDeclaration&&F.isParameter(h.valueDeclaration)&&h.valueDeclaration.dotDotDotToken)X.warn(`Warning: Rest parameters without explicit names are not supported. Skipping rest parameter at path: ${d.join(" > ")}.
Unsupported: \`function example(...args: any[]) { }\`.
Supported: \`function example(...namedArgs: [first: string, second: number]) { }\`.
Please provide named rest parameters to ensure proper type resolution.`);else{let y=h.valueDeclaration;T.args&&(T.args[h.escapedName]={type:p,isRequired:y.initializer===void 0?void 0:!1,documentation:this.getSymbolDocumentation(h)},e(p,{parentType:s},"inputs",[...d,h.escapedName]))}}),m&&e(m,i,l,[...d,"RETURN_TYPE"])}else if(C(this.checker,s)){let o=this.checker.getIndexTypeOfType(s,F.IndexKind.Number);o&&!w(o)&&(t[l].has(s)||t[l].set(s,{}),e(o,i,l,[...d,"ITEM_TYPE"]))}else if(!w(s)){let o=he(this.checker,s);t[l].has(s)||t[l].set(s,{}),o.forEach(u=>{let m=this.checker.getTypeOfSymbolAtLocation(u,this.sfiFile);t[l].get(s)[u.escapedName]||(t[l].get(s)[u.escapedName]={symbol:u,returnType:m,args:{}}),e(m,{propetyName:u.escapedName,parentType:s},l,[...d,u.escapedName])})}}};n.Query&&e(n.Query),n.Mutation&&e(n.Mutation),n.Subscription&&e(n.Subscription);let a=this.program.getSourceFiles();for(let s of a)s.isDeclarationFile||F.forEachChild(s,i=>{if(F.isClassDeclaration(i)||F.isInterfaceDeclaration(i)){let l=this.checker.getTypeAtLocation(i),d=i.heritageClauses;d&&d.forEach(f=>{f.types.forEach(o=>{let u=this.checker.getTypeAtLocation(o),m=u,T=u.getSymbol();if(T){for(let y of t.inheritanceMap.keys())if(y.getSymbol()===T){m=y;break}}t.inheritanceMap.has(m)||t.inheritanceMap.set(m,[]);let h=t.inheritanceMap.get(m),p=l.getSymbol();p&&!h.some(y=>y.getSymbol()===p)&&h.push(l)})})}});let r=!0;for(;r;){r=!1;for(let[s,i]of t.inheritanceMap){let l=t.types.has(s);if(!l){let f=s.getSymbol();if(f){for(let o of t.types.keys())if(o.getSymbol()===f){l=!0;break}}}let d=!1;for(let f of i){if(t.types.has(f)){d=!0;break}let o=f.getSymbol();if(o){for(let u of t.types.keys())if(u.getSymbol()===o){d=!0;break}}if(d)break}if(l)for(let f of i){let o=t.types.has(f);if(!o){let u=f.getSymbol();if(u){for(let m of t.types.keys())if(m.getSymbol()===u){o=!0;break}}}o||(e(f),r=!0)}else d&&(e(s),r=!0)}}return t}};import A from"path";var z=class{program;checker;sfiFile;sfi;sfiFilePath;constructor(n){this.sfiFilePath=n;let t=this.loadTsConfigOptions(),e=N.sys.readDirectory(A.dirname(this.sfiFilePath),[".ts"],[".d.ts"]).concat([A.join(A.dirname(this.sfiFilePath),"..","pylon.d.ts")]);this.program=N.createProgram(e,t),this.checker=this.program.getTypeChecker(),this.loadSfi()}loadSfi(){let t=this.program.getSourceFiles().find(s=>A.resolve(s.fileName)===this.sfiFilePath);if(!t)throw new Error("Could not find index.ts (pylon entrypoint)");this.sfiFile=t;let e=this.checker.getSymbolAtLocation(t),r=this.checker.getExportsOfModule(e).find(s=>s.escapedName==="graphql");if(!r)throw new Error("Could not find graphql export");this.sfi=r}loadTsConfigOptions(){let n={target:N.ScriptTarget.ESNext,module:N.ModuleKind.CommonJS,strict:!0,esModuleInterop:!0,skipLibCheck:!1,forceConsistentCasingInFileNames:!0,noImplicitAny:!0,experimentalDecorators:!0},t=N.findConfigFile(A.dirname(this.sfiFilePath),N.sys.fileExists,"tsconfig.json");if(!t)return console.log("Could not find tsconfig.json"),n;let e=N.readConfigFile(t,N.sys.readFile);return e.error?(console.log("Could not read tsconfig.json",e.error),n):N.parseJsonConfigFileContent(e.config,N.sys,A.dirname(t)).options}build(){let n=this.checker.getTypeOfSymbolAtLocation(this.sfi,this.sfiFile),t=n.getProperty("Query"),e=n.getProperty("Mutation"),a=n.getProperty("Subscription"),r=t?this.checker.getTypeOfSymbolAtLocation(t,this.sfiFile):void 0,s=e?this.checker.getTypeOfSymbolAtLocation(e,this.sfiFile):void 0,i=a?this.checker.getTypeOfSymbolAtLocation(a,this.sfiFile):void 0,l=new G(this.checker,this.sfiFile,this.program);return l.parse({Query:r,Mutation:s,Subscription:i}),{typeDefs:l.toString(),schema:l.getSchema(),resolvers:l.getResolvers()}}};var ee=async c=>await new U(c.sfiFilePath,c.outputFilePath).build({getBuildDefs:()=>{let e=new z(Le.join(process.cwd(),c.sfiFilePath)).build();return{typeDefs:e.typeDefs,resolvers:e.resolvers}},onBuild:c.onBuild,skipInitialBuild:c.skipInitialBuild});import{generateClient as _e}from"@gqty/cli";import Me from"esbuild";import W from"fs/promises";import{buildSchema as qe}from"graphql";import K from"path";var ge=K.join(process.cwd(),".pylon/schema.graphql"),M=K.join(process.cwd(),".pylon/client/index.ts"),te=async({schemaChanged:c})=>{try{await W.access(ge)}catch{throw new Error("Schema not found. Please run `pylon build` or `pylon dev` first.")}if(!c)try{await W.access(M);return}catch{}let n=await W.readFile(ge,"utf-8"),t=qe(n);await W.mkdir(K.dirname(M),{recursive:!0}),await k(M,Ue),await _e(t,{endpoint:"will-be-overwritten",frameworks:["react"],destination:M,react:!0,scalarTypes:{Number:"number",JSONObject:"Record<string, unknown>"}}),await Me.build({entryPoints:[M],bundle:!0,outfile:K.join(process.cwd(),".pylon/client/index.js"),packages:"external",format:"esm",platform:"node"})},Ue=`/**
* GQty: You can safely modify this file based on your needs.
*/
import {createReactClient} from '@gqty/react'
import {
Cache,
createClient,
defaultResponseHandler,
type QueryFetcher
} from 'gqty'
import {
generatedSchema,
scalarsEnumsHash,
type GeneratedSchema
} from './schema.generated'
const queryFetcher: QueryFetcher = async function (
{query, variables, operationName},
fetchOptions
) {
const headers = new Headers({});
let fetchToUse: typeof fetch | typeof app.request = fetch
try {
// 1. Try importing Pylon \u2014 if this works, we're on the server
const moduleNameToPreventBundling = '@getcronit/pylon'
const { app, getContext } = await import(moduleNameToPreventBundling)
fetchToUse = app.request
// 2. Get headers from the original server request and forward them
const context = getContext()
for (const [key, value] of context.req.raw.headers.entries()) {
headers.append(key, value)
// Set Accept-Encoding header to identity so the internal fetch returns JSON
headers.set('Accept-Encoding', 'identity')
headers.set('X-Pylon-Internal', 'true')
}
} catch {
// 3. Pylon not available \u2014 fallback to default fetch (runs in browser)
// No additional headers are needed; browser sends cookies automatically
}
const formData = buildGraphQLMultipartForm(query, variables);
const response = await fetchToUse('/graphql', {
method: 'POST',
headers,
body: formData,
mode: 'cors',
...fetchOptions
})
return await defaultResponseHandler(response)
}
function buildGraphQLMultipartForm(query, variables) {
const form = new FormData();
const operations = { query, variables: structuredClone(variables) };
const map = {};
const files = [];
let fileIndex = 0;
// Helper to find all files in variables
function recurse(value, path = []) {
if (value instanceof File || value instanceof Blob) {
map[fileIndex] = [\`variables.\${path.join(".")}\`];
set(operations.variables, path, null);
files.push({ index: fileIndex, file: value });
fileIndex++;
} else if (Array.isArray(value)) {
value.forEach((item, i) => recurse(item, [...path, i]));
} else if (value && typeof value === "object") {
Object.entries(value).forEach(([key, val]) =>
recurse(val, [...path, key])
);
}
}
recurse(variables);
form.append("operations", JSON.stringify(operations));
form.append("map", JSON.stringify(map));
files.forEach(({ index, file }) => {
form.append(index, file);
});
return form;
}
// Utility to set a value at a path inside an object
function set(obj, path, value) {
let curr = obj;
for (let i = 0; i < path.length - 1; i++) {
curr = curr[path[i]];
}
curr[path[path.length - 1]] = value;
}
export const cache = new Cache(
undefined,
/**
* Default option is immediate cache expiry but keep it for 5 minutes,
* allowing soft refetches in background.
*/
{
maxAge: Infinity,
staleWhileRevalidate: 5 * 60 * 1000,
normalization: true
}
)
export const client = createClient<GeneratedSchema>({
schema: generatedSchema,
scalars: scalarsEnumsHash,
cache,
fetchOptions: {
fetcher: queryFetcher
}
})
export const pageClient = () => {
const client = createClient<GeneratedSchema>({
schema: generatedSchema,
scalars: scalarsEnumsHash,
cache: new Cache(
undefined,
{
maxAge: Infinity,
staleWhileRevalidate: 5 * 60 * 1000,
normalization: true
}
),
fetchOptions: {
fetcher: queryFetcher
}
})
const react = createReactClient(client, {
defaults: {
suspense: false
}
})
return {client, ...react, pageClient}
}
// Core functions
export const {resolve, subscribe, schema} = client
// Legacy functions
export const {query, mutation, mutate, subscription, resolved, refetch, track} =
client
export const {
graphql,
useQuery,
usePaginatedQuery,
useTransactionQuery,
useLazyQuery,
useRefetch,
useMutation,
useMetaState,
prepareReactRender,
useHydrateCache,
prepareQuery
} = createReactClient<GeneratedSchema>(client, {
defaults: {
// Enable Suspense, you can override this option for each hook.
suspense: false
}
})
export * from './schema.generated'`;import{execSync as Je,spawnSync as He}from"child_process";function be(c,n){if(process.platform==="win32"){Je("taskkill /pid "+c+" /T /F");return}Ge(c).forEach(function(e){Te(e,n)}),Te(c,n)}function Qe(){let c=He("ps",["-A","-o","pid,ppid"],{encoding:"utf-8",stdio:"pipe"});return c.error||!c.stdout?[]:c.stdout.trim().split(`
`).slice(1).map(function(t){let e=t.match(/\s*(\d+)\s*(\d+)/);return e===null?null:{pid:Number(e[1]),ppid:Number(e[2])}}).filter(t=>t!=null)}function Ge(c){let n=Qe(),t={},e=[];n.forEach(function(r){t[r.ppid]=t[r.ppid]||[],t[r.ppid].push(r.pid)});let a=function(r){t[r]=t[r]||[],t[r].forEach(function(s){e.push(s),a(s)})};return a(c),e}function Te(c,n){try{process.kill(c,n)}catch(t){if(t.code!=="ESRCH")throw t}}We.config();V.name("pylon-dev").description("Pylon Development CLI").version(se);V.command("build").description("Build the Pylon Schema").action(async()=>{let c=await ee({sfiFilePath:"./src/index.ts",outputFilePath:"./.pylon",onBuild:async({totalFiles:t,totalSize:e,duration:a,schemaChanged:r})=>{try{I.capture({distinctId:j,event:"build completed",properties:{duration:a,totalFiles:t,totalSize:e,schemaChanged:r,dependencies:R,isDevelopment:!1,$session_id:E}}),await te({schemaChanged:r})}catch(s){O.error("Error during build callback",s)}}}),n=async()=>{await c.dispose(),process.exit(0)};process.on("SIGINT",n),process.on("SIGTERM",n),process.on("SIGHUP",n),await c.rebuild(),await c.dispose()});V.command("dev").description("Start the Pylon Development Server").option("-c, --command <command>","Command to run the server","bun run .pylon/index.js").action(async c=>{let n=null,t=async()=>{if(n&&n.pid){try{be(n.pid)}catch(a){O.error("Failed to kill server process",a)}n=null}},e=null;await new Promise(async(a,r)=>{try{e=await ee({sfiFilePath:"./src/index.ts",outputFilePath:"./.pylon",onBuild:async({schemaChanged:i,totalFiles:l,totalSize:d,duration:f})=>{try{await te({schemaChanged:i}),await t(),n=await Ke(c.command),I.capture({distinctId:j,event:"build completed",properties:{duration:f,totalFiles:l,totalSize:d,schemaChanged:i,dependencies:R,pylonConfig:await Y(),isDevelopment:!0,$session_id:E}})}catch(o){O.error("Error during dev build callback",o)}},skipInitialBuild:!0}),await e.watch(),O.box(`Pylon is up and running!
Press \`Ctrl + C\` to stop the server.
Encounter any issues? Report them here:
https://github.com/getcronit/pylon/issues
We value your feedback\u2014help us make Pylon even better!`);let s=async()=>{e&&await e.dispose(),await t(),process.exit(0)};process.on("SIGINT",s),process.on("SIGTERM",s),process.on("SIGHUP",s),process.on("exit",()=>t()),I.capture({distinctId:j,event:"dev server started",properties:{command:c.command,dependencies:R,pylonConfig:await Y(),$session_id:E}})}catch(s){e&&await e.dispose(),await t(),r(s)}})});var Ke=async c=>{let[n,...t]=c.split(" "),e=ze(n,t,{stdio:"inherit",env:{...process.env,NODE_ENV:"development",FORCE_COLOR:"1"}});return e.on("error",a=>{O.error(a)}),e};try{await V.parseAsync(process.argv)}catch(c){O.error(c),I.captureException(c,j,{$session_id:E,dependencies:R})}finally{await I.shutdown()}
//# sourceMappingURL=index.js.map