Skip to content

Commit

Permalink
Inline graphql-codegen deps
Browse files Browse the repository at this point in the history
  • Loading branch information
emmatown committed Mar 11, 2024
1 parent 26d6bc8 commit 6ae0c14
Show file tree
Hide file tree
Showing 30 changed files with 5,226 additions and 563 deletions.
2 changes: 0 additions & 2 deletions packages/compiler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@
"@babel/parser": "^7.9.6",
"@babel/runtime": "^7.9.2",
"@babel/types": "^7.9.6",
"@graphql-codegen/plugin-helpers": "^5.0.3",
"@graphql-codegen/typescript-operations": "^4.2.0",
"@nodelib/fs.walk": "^1.2.4",
"@ts-gql/config": "^0.9.2",
"chokidar": "^3.4.0",
Expand Down
13 changes: 1 addition & 12 deletions packages/compiler/src/get-generated-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
DocumentValidationCache,
} from "./validate-documents";
import { DocumentNode } from "graphql";
import { weakMemoize } from "./weakMemoize";

function memoize<V>(fn: (arg: string) => V): (arg: string) => V {
const cache: { [key: string]: V } = {};
Expand All @@ -38,18 +39,6 @@ function memoize<V>(fn: (arg: string) => V): (arg: string) => V {

const walk = promisify(_walk);

function weakMemoize<Arg extends object, Return>(
fn: (arg: Arg) => Return
): (arg: Arg) => Return {
const cache = new WeakMap<Arg, Return>();
return (arg: Arg) => {
if (cache.has(arg)) return cache.get(arg)!;
const result = fn(arg);
cache.set(arg, result);
return result;
};
}

function getPrintCompilerError() {
let readFile = memoize((filename: string) => fs.readFile(filename, "utf8"));

Expand Down
8 changes: 4 additions & 4 deletions packages/compiler/src/operation-types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as fs from "./fs";
import { DocumentNode, ExecutableDefinitionNode } from "graphql";
import { codegen } from "./codegen-core";
import { codegen } from "./vendor/codegen-core";
import { hashString, parseTsGqlMeta } from "./utils";
import { FsOperation } from "./fs-operations";
import {
Expand All @@ -11,6 +11,7 @@ import stripAnsi from "strip-ansi";
import { Config } from "@ts-gql/config";
import { lazyRequire } from "lazy-require.macro";
import { inlineIntoFirstOperationOrFragment } from "./inline-fragments";
import { typescriptOperationsPlugin } from "./vendor/typescript-operations";

function getUsedFragments(node: ExecutableDefinitionNode) {
const visit = lazyRequire<typeof import("graphql/language/visitor")>().visit;
Expand Down Expand Up @@ -62,10 +63,9 @@ async function generateOperationTypes(
},
],
pluginMap: {
"typescript-operations":
lazyRequire<typeof import("@graphql-codegen/typescript-operations")>(),
"typescript-operations": { plugin: typescriptOperationsPlugin },
},
}).replace(/(SchemaTypes\.Scalars\['[^']+'\])\['(?:input|output)'\]/g, "$1");
});

const operationNode = operation.definitions[0];
if (
Expand Down
1 change: 1 addition & 0 deletions packages/compiler/src/vendor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
These packages are inlined from https://github.com/dotansimha/graphql-code-generator, mainly to remove the dependency on relay-compiler which adds quite a large dependency tree
32 changes: 32 additions & 0 deletions packages/compiler/src/vendor/auto-bind.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// https://github.com/sindresorhus/auto-bind/blob/5f9859a2c163a6567f0595b6268ef667c8248c6a/index.js
const getAllProperties = (object: object) => {
const properties = new Set<[Record<string, any>, string | symbol]>();

do {
for (const key of Reflect.ownKeys(object)) {
properties.add([object, key]);
}
} while (
(object = Reflect.getPrototypeOf(object)!) &&
object !== Object.prototype
);

return properties;
};

export function autoBind<SelfType extends Record<string, any>>(
self: SelfType
): SelfType {
for (const [object, key] of getAllProperties(self.constructor.prototype)) {
if (key === "constructor") {
continue;
}

const descriptor = Reflect.getOwnPropertyDescriptor(object, key);
if (descriptor && typeof descriptor.value === "function") {
(self as any)[key] = self[key as string].bind(self);
}
}

return self;
}
File renamed without changes.
File renamed without changes.
206 changes: 206 additions & 0 deletions packages/compiler/src/vendor/typescript-operations/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
import {
AvoidOptionalsConfig,
RawDocumentsConfig,
} from "../visitor-plugin-common";

/**
* @description This plugin generates TypeScript types based on your GraphQLSchema _and_ your GraphQL operations and fragments.
* It generates types for your GraphQL documents: Query, Mutation, Subscription and Fragment.
*
* Note: In most configurations, this plugin requires you to use `typescript as well, because it depends on its base types.
*/
export interface TypeScriptDocumentsPluginConfig extends RawDocumentsConfig {
/**
* @description The [GraphQL spec](https://spec.graphql.org/draft/#sel-FAHjBJFCAACE_Gh7d)
* allows arrays and a single primitive value for list input. This allows to
* deactivate that behavior to only accept arrays instead of single values. If
* set to `false`, the definition: `query foo(bar: [Int!]!): Foo` will output
* `bar: Array<Int>` instead of `bar: Array<Int> | Int` for the variable part.
* @default true
*
* @exampleMarkdown
* ```ts filename="codegen.ts"
* import type { CodegenConfig } from '@graphql-codegen/cli';
*
* const config: CodegenConfig = {
* // ...
* generates: {
* 'path/to/file.ts': {
* plugins: ['typescript'],
* config: {
* arrayInputCoercion: false
* },
* },
* },
* };
* export default config;
* ```
*/
arrayInputCoercion?: boolean;
/**
* @description This will cause the generator to avoid using TypeScript optionals (`?`) on types,
* so the following definition: `type A { myField: String }` will output `myField: Maybe<string>`
* instead of `myField?: Maybe<string>`.
* @default false
*
* @exampleMarkdown
* ## Override all definition types
*
* ```ts filename="codegen.ts"
* import type { CodegenConfig } from '@graphql-codegen/cli';
*
* const config: CodegenConfig = {
* // ...
* generates: {
* 'path/to/file.ts': {
* plugins: ['typescript'],
* config: {
* avoidOptionals: true
* },
* },
* },
* };
* export default config;
* ```
*
* ## Override only specific definition types
*
* ```ts filename="codegen.ts"
* import type { CodegenConfig } from '@graphql-codegen/cli';
*
* const config: CodegenConfig = {
* // ...
* generates: {
* 'path/to/file.ts': {
* plugins: ['typescript'],
* config: {
* avoidOptionals: {
* field: true
* inputValue: true
* object: true
* defaultValue: true
* }
* },
* },
* },
* };
* export default config;
* ```
*/
avoidOptionals?: boolean | AvoidOptionalsConfig;
/**
* @description Generates immutable types by adding `readonly` to properties and uses `ReadonlyArray`.
* @default false
*
* @exampleMarkdown
* ```ts filename="codegen.ts"
* import type { CodegenConfig } from '@graphql-codegen/cli';
*
* const config: CodegenConfig = {
* // ...
* generates: {
* 'path/to/file.ts': {
* plugins: ['typescript'],
* config: {
* immutableTypes: true
* },
* },
* },
* };
* export default config;
* ```
*/
immutableTypes?: boolean;

/**
* @description Set to `true` in order to generate output without `export` modifier.
* This is useful if you are generating `.d.ts` file and want it to be globally available.
* @default false
*
* @exampleMarkdown
* ```ts filename="codegen.ts"
* import type { CodegenConfig } from '@graphql-codegen/cli';
*
* const config: CodegenConfig = {
* // ...
* generates: {
* 'path/to/file.ts': {
* plugins: ['typescript'],
* config: {
* noExport: true
* },
* },
* },
* };
* export default config;
* ```
*/
noExport?: boolean;
/**
* @description Allow to override the type value of `Maybe`.
* @default T | null
*
* @exampleMarkdown
* ## Allow undefined
* ```ts filename="codegen.ts"
* import type { CodegenConfig } from '@graphql-codegen/cli';
*
* const config: CodegenConfig = {
* // ...
* generates: {
* 'path/to/file.ts': {
* plugins: ['typescript'],
* config: {
* maybeValue: 'T | null | undefined'
* },
* },
* },
* };
* export default config;
* ```
*
* ## Allow `null` in resolvers:
* ```ts filename="codegen.ts"
* import type { CodegenConfig } from '@graphql-codegen/cli';
*
* const config: CodegenConfig = {
* // ...
* generates: {
* 'path/to/file.ts': {
* plugins: ['typescript'],
* config: {
* maybeValue: 'T extends PromiseLike<infer U> ? Promise<U | null> : T | null'
* },
* },
* },
* };
* export default config;
* ```
*/
maybeValue?: string;

/**
* @description Adds undefined as a possible type for query variables
* @default false
*
* @exampleMarkdown
* ```ts filename="codegen.ts"
* import type { CodegenConfig } from '@graphql-codegen/cli';
*
* const config: CodegenConfig = {
* // ...
* generates: {
* 'path/to/file.ts': {
* plugins: ['typescript'],
* config: {
* allowUndefinedQueryVariables: true
* },
* },
* },
* };
* export default config;
* ```
*/

allowUndefinedQueryVariables?: boolean;
}
87 changes: 87 additions & 0 deletions packages/compiler/src/vendor/typescript-operations/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { PluginFunction, Types } from "@graphql-codegen/plugin-helpers";

Check failure on line 1 in packages/compiler/src/vendor/typescript-operations/index.ts

View workflow job for this annotation

GitHub Actions / TypeScript

Cannot find module '@graphql-codegen/plugin-helpers' or its corresponding type declarations.
import { LoadedFragment } from "../visitor-plugin-common";
import {
concatAST,
FragmentDefinitionNode,
GraphQLSchema,
Kind,
} from "graphql";
import { TypeScriptDocumentsPluginConfig } from "./config";
import { TypeScriptDocumentsVisitor } from "./visitor";

export type { TypeScriptDocumentsPluginConfig } from "./config";

import { ASTNode, visit } from "graphql";

type VisitFn = typeof visit;
type NewVisitor = Partial<Parameters<VisitFn>[1]>;
type OldVisitor = {
enter?: Partial<
Record<keyof NewVisitor, NonNullable<NewVisitor[keyof NewVisitor]>["enter"]>
>;
leave?: Partial<
Record<keyof NewVisitor, NonNullable<NewVisitor[keyof NewVisitor]>["leave"]>
>;
} & NewVisitor;

function oldVisit(
root: ASTNode,
{ enter: enterVisitors, leave: leaveVisitors, ..._newVisitor }: OldVisitor
): any {
const newVisitor: any = _newVisitor;
if (typeof enterVisitors === "object") {
for (const key in enterVisitors) {
newVisitor[key] ||= {};
newVisitor[key].enter = (enterVisitors as any)[key];
}
}
if (typeof leaveVisitors === "object") {
for (const key in leaveVisitors) {
newVisitor[key] ||= {};
newVisitor[key].leave = (leaveVisitors as any)[key];
}
}
return visit(root, newVisitor);
}

export const typescriptOperationsPlugin: PluginFunction<
TypeScriptDocumentsPluginConfig,
Types.ComplexPluginOutput
> = (
schema: GraphQLSchema,
documents: Types.DocumentFile[],
config: TypeScriptDocumentsPluginConfig
) => {
const allAst = concatAST(documents.map((v) => v.document!));

const allFragments: LoadedFragment[] = [
...(
allAst.definitions.filter(
(d) => d.kind === Kind.FRAGMENT_DEFINITION
) as FragmentDefinitionNode[]
).map((fragmentDef) => ({
node: fragmentDef,
name: fragmentDef.name.value,
onType: fragmentDef.typeCondition.name.value,
isExternal: false,
})),
];

const visitor = new TypeScriptDocumentsVisitor(schema, config, allFragments);

const visitorResult = oldVisit(allAst, {
leave: visitor as any,
});

let content = visitorResult.definitions.join("\n");

return {
prepend: [
...visitor.getImports(),
...visitor.getGlobalDeclarations(visitor.config.noExport),
],
content,
};
};

export { TypeScriptDocumentsVisitor };
Loading

0 comments on commit 6ae0c14

Please sign in to comment.