protoc-gen-pothos 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,96 +1,46 @@
1
- import { InterfaceType } from "@proto-graphql/codegen-core";
2
- import ts from "typescript";
3
- import { createFieldDefinitionExpr, createNoopFieldDefinitionExpr } from "./field";
4
- import { createBuilderCallExpr, createBuilderPropExpr, createDescriptionPropertyAssignment, createDslExportConstStmt, createQualifiedName, onlyNonNull, } from "./util";
1
+ import { compact, InterfaceType, protobufGraphQLExtensions, protoType } from "@proto-graphql/codegen-core";
2
+ import { code, joinCode, literalOf } from "ts-poet";
3
+ import { createFieldRefCode, createNoopFieldRefCode } from "./field";
4
+ import { pothosBuilder, pothosRef } from "./util";
5
5
  /**
6
6
  * @example
7
7
  * ```ts
8
- * export const Hello = builder.objectRef<_$hello$hello_pb.Hello>("Hello")
9
- * builder.objectType(Hello, {
8
+ * export const Hello$Ref = builder.objectRef<_$hello$hello_pb.Hello>("Hello")
9
+ * builder.objectType(Hello$Ref, {
10
10
  * name: "Hello",
11
11
  * // ...
12
12
  * })
13
13
  * ```
14
14
  */
15
- export function createObjectTypeDslStmts(objType) {
16
- const isInterface = objType instanceof InterfaceType;
17
- return [
18
- createDslExportConstStmt(objType.pothosRefObjectName, ts.factory.createCallExpression(createBuilderPropExpr(isInterface ? "interfaceRef" : "objectRef"), [
19
- isInterface
20
- ? ts.factory.createTypeReferenceNode("Pick", [
21
- ts.factory.createTypeReferenceNode(createQualifiedName(objType.protoTypeFullName)),
22
- ts.factory.createUnionTypeNode(objType.fields.map((f) => ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(f.protoJsName)))),
23
- ])
24
- : ts.factory.createTypeReferenceNode(createQualifiedName(objType.protoTypeFullName)),
25
- ], [ts.factory.createStringLiteral(objType.typeName)])),
26
- ts.factory.createExpressionStatement(createBuilderCallExpr(isInterface ? "interfaceType" : "objectType", [
27
- ts.factory.createIdentifier(objType.pothosRefObjectName),
28
- ts.factory.createObjectLiteralExpression([
29
- ts.factory.createPropertyAssignment("name", ts.factory.createStringLiteral(objType.typeName)),
30
- createDescriptionPropertyAssignment(objType),
31
- ts.factory.createPropertyAssignment("fields", createObjectTypeFieldsFuncExpr(objType)),
32
- isInterface ? null : ts.factory.createPropertyAssignment("isTypeOf", createIsTypeOfMethodExpr(objType)),
33
- ts.factory.createPropertyAssignment("extensions", createExtensionsObjectLiteralExpr(objType)),
34
- ].filter(onlyNonNull()), true),
35
- ])),
36
- ];
37
- }
38
- /**
39
- * @example
40
- * ```ts
41
- * fields: (t) => ({
42
- * // ...
43
- * })
44
- * ```
45
- */
46
- function createObjectTypeFieldsFuncExpr(objType) {
47
- return ts.factory.createArrowFunction(undefined, undefined, [ts.factory.createParameterDeclaration(undefined, undefined, undefined, "t", undefined, undefined, undefined)], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createParenthesizedExpression(ts.factory.createObjectLiteralExpression(objType.fields.length > 0
48
- ? objType.fields.map((f) => ts.factory.createPropertyAssignment(f.name, createFieldDefinitionExpr(f)))
49
- : [ts.factory.createPropertyAssignment("_", createNoopFieldDefinitionExpr({ input: false }))], true)));
50
- }
51
- /**
52
- * @example
53
- * ```ts
54
- * isTypeOf(data) {
55
- * return data instanceof _$hello$hello_pb.Hello;
56
- *
57
- * (source) =>
58
- * // eslint-disable-next-line @typescript-eslint/ban-types
59
- * (source as _$hello$hello_pb.Hello | { $type: string & {} }).$type === "hello.Hello",
60
- * }
61
- * ```
62
- */
63
- function createIsTypeOfMethodExpr(objType) {
64
- return ts.factory.createArrowFunction(undefined, undefined, [ts.factory.createParameterDeclaration(undefined, undefined, undefined, "source", undefined, undefined, undefined)], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBlock([
65
- ts.factory.createReturnStatement(ts.factory.createBinaryExpression(ts.factory.createPropertyAccessExpression(ts.factory.createParenthesizedExpression(ts.factory.createAsExpression(ts.factory.createIdentifier("source"), ts.factory.createUnionTypeNode([
66
- ts.factory.createTypeReferenceNode(createQualifiedName(objType.protoTypeFullName)),
67
- ts.factory.createTypeLiteralNode([
68
- ts.factory.createPropertySignature(undefined, "$type", undefined, ts.factory.createIntersectionTypeNode([
69
- ts.factory.createToken(ts.SyntaxKind.StringKeyword),
70
- ts.factory.createTypeLiteralNode([]),
71
- ])),
72
- ]),
73
- ]))), "$type"), ts.SyntaxKind.EqualsEqualsEqualsToken, ts.factory.createStringLiteral(objType.proto.fullName.toString()))),
74
- ], true));
75
- }
76
- /**
77
- * @example
78
- * ```ts
79
- * {
80
- * protobufMessage: {
81
- * fullName: "...",
82
- * name: "...",
83
- * package: "...",
84
- * },
85
- * }
86
- * ```
87
- */
88
- function createExtensionsObjectLiteralExpr(objType) {
89
- return ts.factory.createObjectLiteralExpression([
90
- ts.factory.createPropertyAssignment("protobufMessage", ts.factory.createObjectLiteralExpression([
91
- ts.factory.createPropertyAssignment("fullName", ts.factory.createStringLiteral(objType.proto.fullName.toString())),
92
- ts.factory.createPropertyAssignment("name", ts.factory.createStringLiteral(objType.proto.name)),
93
- ts.factory.createPropertyAssignment("package", ts.factory.createStringLiteral(objType.proto.file.package)),
94
- ], true)),
95
- ], true);
15
+ export function createObjectTypeCode(type, opts) {
16
+ const isInterface = type instanceof InterfaceType;
17
+ const typeOpts = {
18
+ name: type.typeName,
19
+ fields: code `t => ({${type.fields.length > 0
20
+ ? joinCode(type.fields.map((f) => code `${f.name}: ${createFieldRefCode(f, opts)},`))
21
+ : code `_: ${createNoopFieldRefCode({ input: false })}`}})`,
22
+ description: type.description,
23
+ isTypeOf: isInterface
24
+ ? undefined
25
+ : code `
26
+ (source) => {
27
+ return (source as ${protoType(type.proto, opts)} | { $type: string & {} }).$type
28
+ === ${literalOf(type.proto.fullName.toString())};
29
+ }
30
+ `,
31
+ extensions: protobufGraphQLExtensions(type),
32
+ };
33
+ const buildRefFunc = code `${pothosBuilder(type, opts)}.${isInterface ? "interface" : "object"}Ref`;
34
+ const buildTypeFunc = code `${pothosBuilder(type, opts)}.${isInterface ? "interface" : "object"}Type`;
35
+ const refFuncTypeArg = isInterface
36
+ ? code `
37
+ Pick<
38
+ ${protoType(type.proto, opts)},
39
+ ${joinCode(type.fields.map((f) => code `${literalOf(f.proto.jsonName)}`), { on: "|" })}
40
+ >`
41
+ : protoType(type.proto, opts);
42
+ return code `
43
+ export const ${pothosRef(type)} = ${buildRefFunc}<${refFuncTypeArg}>(${literalOf(type.typeName)});
44
+ ${buildTypeFunc}(${pothosRef(type)}, ${literalOf(compact(typeOpts))});
45
+ `;
96
46
  }
@@ -1,6 +1,6 @@
1
- import { SquashedOneofUnionType } from "@proto-graphql/codegen-core";
2
- import ts from "typescript";
3
- import { createBuilderCallExpr, createDescriptionPropertyAssignment, createDslExportConstStmt, onlyNonNull, } from "./util";
1
+ import { compact, protobufGraphQLExtensions, } from "@proto-graphql/codegen-core";
2
+ import { code, literalOf } from "ts-poet";
3
+ import { pothosBuilder, pothosRef } from "./util";
4
4
  /**
5
5
  * @example
6
6
  * ```ts
@@ -10,60 +10,14 @@ import { createBuilderCallExpr, createDescriptionPropertyAssignment, createDslEx
10
10
  * })
11
11
  * ```
12
12
  */
13
- export function createOneofUnionTypeDslStmt(type) {
14
- return createDslExportConstStmt(type.pothosRefObjectName, createBuilderCallExpr("unionType", [
15
- ts.factory.createStringLiteral(type.typeName),
16
- ts.factory.createObjectLiteralExpression([
17
- createDescriptionPropertyAssignment(type),
18
- ts.factory.createPropertyAssignment("types", ts.factory.createArrayLiteralExpression(type.fields.map((f) => ts.factory.createIdentifier(f.type.pothosRefObjectName)), true)),
19
- ts.factory.createPropertyAssignment("extensions", createExtensionsObjectLiteralExpr(type)),
20
- ].filter(onlyNonNull()), true),
21
- ]));
22
- }
23
- /**
24
- * @example
25
- * ```ts
26
- * {
27
- * protobufMessage: {
28
- * fullName: "...",
29
- * name: "...",
30
- * package: "...",
31
- * },
32
- * }
33
- * ```
34
- */
35
- function createExtensionsObjectLiteralExpr(type) {
36
- if (type instanceof SquashedOneofUnionType) {
37
- return ts.factory.createObjectLiteralExpression([
38
- ts.factory.createPropertyAssignment("protobufMessage", ts.factory.createObjectLiteralExpression([
39
- ts.factory.createPropertyAssignment("fullName", ts.factory.createStringLiteral(type.proto.fullName.toString())),
40
- ts.factory.createPropertyAssignment("name", ts.factory.createStringLiteral(type.proto.name)),
41
- ts.factory.createPropertyAssignment("package", ts.factory.createStringLiteral(type.proto.file.package)),
42
- ts.factory.createPropertyAssignment("fields", ts.factory.createArrayLiteralExpression(type.proto.oneofs[0].fields.map((f) => ts.factory.createObjectLiteralExpression([
43
- ts.factory.createPropertyAssignment("name", ts.factory.createStringLiteral(f.name)),
44
- ...(f.type && f.type.kind !== "Scalar"
45
- ? [
46
- ts.factory.createPropertyAssignment("type", ts.factory.createStringLiteral(f.type.fullName.toString())),
47
- ]
48
- : []),
49
- ], true)), true)),
50
- ], true)),
51
- ], true);
52
- }
53
- return ts.factory.createObjectLiteralExpression([
54
- ts.factory.createPropertyAssignment("protobufOneof", ts.factory.createObjectLiteralExpression([
55
- ts.factory.createPropertyAssignment("fullName", ts.factory.createStringLiteral(type.proto.fullName.toString())),
56
- ts.factory.createPropertyAssignment("name", ts.factory.createStringLiteral(type.proto.name)),
57
- ts.factory.createPropertyAssignment("messageName", ts.factory.createStringLiteral(type.proto.parent.name)),
58
- ts.factory.createPropertyAssignment("package", ts.factory.createStringLiteral(type.proto.parent.file.package)),
59
- ts.factory.createPropertyAssignment("fields", ts.factory.createArrayLiteralExpression(type.proto.fields.map((f) => ts.factory.createObjectLiteralExpression([
60
- ts.factory.createPropertyAssignment("name", ts.factory.createStringLiteral(f.name)),
61
- ...(f.type && f.type.kind !== "Scalar"
62
- ? [
63
- ts.factory.createPropertyAssignment("type", ts.factory.createStringLiteral(f.type.fullName.toString())),
64
- ]
65
- : []),
66
- ], true)), true)),
67
- ], true)),
68
- ], true);
13
+ export function createOneofUnionTypeCode(type, opts) {
14
+ const typeOpts = {
15
+ types: type.fields.map((f) => pothosRef(f.type)),
16
+ description: type.description,
17
+ extensions: protobufGraphQLExtensions(type),
18
+ };
19
+ return code `
20
+ export const ${pothosRef(type)} =
21
+ ${pothosBuilder(type, opts)}.unionType(${literalOf(type.typeName)}, ${literalOf(compact(typeOpts))});
22
+ `;
69
23
  }
@@ -1,79 +1,37 @@
1
- import ts from "typescript";
2
- /**
3
- * @example
4
- * ```
5
- * nexus.objectType(...)
6
- * ```
7
- */
8
- export function createBuilderCallExpr(name, args) {
9
- return ts.factory.createCallExpression(createBuilderPropExpr(name), undefined, args);
10
- }
11
- /**
12
- * @example
13
- * ```
14
- * builder.objectRef
15
- * ```
16
- */
17
- export function createBuilderPropExpr(name) {
18
- return ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier("builder"), name);
19
- }
20
- export function createDescriptionPropertyAssignment(gql) {
21
- if (!gql.description)
22
- return null;
23
- return ts.factory.createPropertyAssignment("description", ts.factory.createStringLiteral(gql.description));
24
- }
25
- export function createDeprecationPropertyAssignment(gql) {
26
- const reason = gql.deprecationReason;
27
- if (!reason)
28
- return null;
29
- return ts.factory.createPropertyAssignment("deprecationReason", ts.factory.createStringLiteral(reason));
30
- }
31
- export function fullNameString(fn) {
32
- if (typeof fn === "string") {
33
- return fn;
34
- }
35
- return `${typeof fn[0] === "string" ? fn[0] : fullNameString(fn[0])}.${fn[1]}`;
36
- }
37
- export function createFullNameExpr(fn) {
38
- if (typeof fn === "string") {
39
- return ts.factory.createIdentifier(fn);
40
- }
41
- return ts.factory.createPropertyAccessExpression(typeof fn[0] === "string" ? ts.factory.createIdentifier(fn[0]) : createFullNameExpr(fn[0]), fn[1]);
42
- }
43
- export function createQualifiedName(fn) {
44
- if (typeof fn === "string") {
45
- return ts.factory.createIdentifier(fn);
46
- }
47
- return ts.factory.createQualifiedName(typeof fn[0] === "string" ? ts.factory.createIdentifier(fn[0]) : createQualifiedName(fn[0]), fn[1]);
48
- }
49
- /**
50
- * @example
51
- * ```
52
- * import * as foo$bar$baz from "foo/bar/baz";
53
- * ```
54
- */
55
- export function createImportDecl({ alias, module, type, }) {
56
- return ts.factory.createImportDeclaration(undefined, undefined, ts.factory.createImportClause(false, undefined, type === "namespace"
57
- ? ts.factory.createNamespaceImport(ts.factory.createIdentifier(alias))
58
- : type === "named"
59
- ? ts.factory.createNamedImports([
60
- ts.factory.createImportSpecifier(false, undefined, ts.factory.createIdentifier(alias)),
61
- ])
62
- : undefined), ts.factory.createStringLiteral(module));
63
- }
64
- export function createDslExportConstStmt(name, exp) {
65
- return ts.factory.createVariableStatement([ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(name, undefined, undefined, exp)], ts.NodeFlags.Const));
66
- }
67
- export function onlyNonNull() {
68
- return (t) => t != null;
69
- }
70
- export function onlyUnique(f) {
71
- const set = new Set();
72
- return (t) => {
73
- const key = f ? f(t) : t;
74
- if (set.has(key))
75
- return false;
76
- set.add(key);
77
- return true;
78
- };
1
+ import { filename, generatedGraphQLTypeImportPath, } from "@proto-graphql/codegen-core";
2
+ import * as path from "path";
3
+ import { code, imp } from "ts-poet";
4
+ export function pothosRef(type) {
5
+ return code `${pothosRefName(type)}`;
6
+ }
7
+ function pothosRefName(type) {
8
+ return `${type.typeName}$Ref`;
9
+ }
10
+ export function shapeType(type) {
11
+ return code `${shapeTypeName(type)}`;
12
+ }
13
+ export function shapeTypeName(type) {
14
+ return `${type.typeName}$Shape`;
15
+ }
16
+ export function fieldTypeRef(field, opts) {
17
+ const importPath = generatedGraphQLTypeImportPath(field, opts);
18
+ if (importPath == null)
19
+ return pothosRef(field.type);
20
+ const imported = imp(`IMPORTED_PLACEHOLDER@${importPath}`);
21
+ imported.symbol = pothosRefName(field.type); // NOTE: Workaround for ts-poet not recognizing "$" as an identifier
22
+ return code `${imported}`;
23
+ }
24
+ export function fieldTypeShape(field, opts) {
25
+ const importPath = generatedGraphQLTypeImportPath(field, opts);
26
+ if (importPath == null)
27
+ return shapeType(field.type);
28
+ const imported = imp(`IMPORTED_PLACEHOLDER@${importPath}`);
29
+ imported.symbol = shapeTypeName(field.type); // NOTE: Workaround for ts-poet not recognizing "$" as an identifier
30
+ return code `${imported}`;
31
+ }
32
+ export function pothosBuilder(type, opts) {
33
+ const importPath = opts.pothos.builderPath.startsWith(".")
34
+ ? path.relative(path.dirname(filename(type, opts)), opts.pothos.builderPath)
35
+ : opts.pothos.builderPath;
36
+ return code `${imp(`builder@${importPath}`)}`;
79
37
  }
package/module/printer.js CHANGED
@@ -1,57 +1,30 @@
1
- import ts from "typescript";
2
- import { collectTypesFromFile, DslFile } from "@proto-graphql/codegen-core";
3
- import { createImportDecls, createTypeDslStmts } from "./dslgen";
1
+ import { collectTypesFromFile, filename, filenameFromProtoFile, printCodes, } from "@proto-graphql/codegen-core";
2
+ import { createTypeDslCodes } from "./dslgen";
4
3
  export function generateFiles(registry, file, opts) {
5
- const dslFile = new DslFile(file, { ...opts, dsl: "pothos", useTsProto: true });
6
- const types = collectTypesFromFile(dslFile, registry);
7
- switch (opts.fileLayout) {
4
+ opts.printer.protobuf = "ts-proto"; // default
5
+ const types = collectTypesFromFile(file, opts.type, registry);
6
+ switch (opts.printer.fileLayout) {
8
7
  case "proto_file": {
9
8
  return [
10
9
  {
11
- filename: dslFile.filename,
12
- content: printSource(types, file),
10
+ filename: filenameFromProtoFile(file, opts.printer),
11
+ content: printCodes(createCodes(types, opts.printer), "protoc-gen-pothos", file),
13
12
  },
14
13
  ];
15
14
  }
16
15
  case "graphql_type": {
17
16
  return types.map((t) => ({
18
- filename: t.filename,
19
- content: printSource([t], file),
17
+ filename: filename(t, opts.printer),
18
+ content: printCodes(createCodes([t], opts.printer), "protoc-gen-pothos", file),
20
19
  }));
21
20
  }
22
21
  /* istanbul ignore next */
23
22
  default: {
24
- const _exhaustiveCheck = opts.fileLayout;
23
+ const _exhaustiveCheck = opts.printer.fileLayout;
25
24
  throw "unreachable";
26
25
  }
27
26
  }
28
27
  }
29
- function printSource(types, file) {
30
- const ast = [
31
- // `import builder from "../../builder";`
32
- // `import * as _$hello$hello_pb from "./hello/hello_pb";`
33
- ...createImportDecls(types),
34
- // `export cosnt Hello = objectType({ ... });`
35
- // `export cosnt HelloInput = inputObjectType({ ... });`
36
- // `export cosnt Oneof = unionType({ ... });`
37
- // `export const Role = enumType({ ... });`
38
- ...createTypeDslStmts(types),
39
- ];
40
- if (ast.length === 0) {
41
- ast.push(
42
- // `export {}`
43
- ts.factory.createExportDeclaration(undefined, undefined, false, ts.factory.createNamedExports([]), undefined));
44
- }
45
- const nexusFile = ts.factory.updateSourceFile(ts.createSourceFile("generated.ts", "", ts.ScriptTarget.Latest, false, ts.ScriptKind.TS), ast, false);
46
- const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
47
- const result = printer.printFile(nexusFile);
48
- const content = [
49
- "// Code generated by protoc-gen-pothos. DO NOT EDIT.",
50
- `// source: ${file.descriptor.getName()}`,
51
- "",
52
- "/* eslint-disable */",
53
- "",
54
- result,
55
- ].join("\n");
56
- return content;
28
+ function createCodes(types, opts) {
29
+ return [...createTypeDslCodes(types, opts)];
57
30
  }
package/module/process.js CHANGED
@@ -1,3 +1,3 @@
1
1
  import { createProcessor } from "@proto-graphql/protoc-plugin-helpers";
2
2
  import { generateFiles } from "./printer";
3
- export const processRequest = createProcessor({ generateFiles });
3
+ export const processRequest = createProcessor({ generateFiles, dsl: "pothos" });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "protoc-gen-pothos",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "description": "Generate DSL for Pothos GraphQL from Protocol Buffers IDL",
5
5
  "keywords": [
6
6
  "graphql",
@@ -23,10 +23,11 @@
23
23
  "node": ">= 14.0.0"
24
24
  },
25
25
  "dependencies": {
26
- "@proto-graphql/codegen-core": "^0.2.2",
27
- "@proto-graphql/proto-descriptors": "^0.2.0",
28
- "@proto-graphql/protoc-plugin-helpers": "^0.2.1",
29
- "google-protobuf": "^3.20.1"
26
+ "@proto-graphql/codegen-core": "^0.3.0",
27
+ "@proto-graphql/proto-descriptors": "^0.3.0",
28
+ "@proto-graphql/protoc-plugin-helpers": "^0.2.2",
29
+ "google-protobuf": "^3.20.1",
30
+ "ts-poet": "^6.3.0"
30
31
  },
31
32
  "devDependencies": {
32
33
  "@pothos/core": "^3.22.7",