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,68 +1,36 @@
1
- import ts from "typescript";
2
- import { createBuilderCallExpr, createDeprecationPropertyAssignment, createDescriptionPropertyAssignment, createDslExportConstStmt, onlyNonNull, } from "./util";
1
+ import { compact, protobufGraphQLExtensions } from "@proto-graphql/codegen-core";
2
+ import { code, joinCode, literalOf } from "ts-poet";
3
+ import { pothosBuilder, pothosRef } from "./util";
3
4
  /**
4
5
  * @example
5
6
  * ```ts
6
- * export cosnt Hello = builder.enumType("Hello", {
7
+ * export cosnt Hello$Ref = builder.enumType("Hello", {
8
+ * values: [
9
+ * // ...
10
+ * ],
7
11
  * // ...
8
12
  * })
9
13
  * ```
10
14
  */
11
- export function createEnumTypeDslStmt(type) {
12
- return createDslExportConstStmt(type.pothosRefObjectName, createBuilderCallExpr("enumType", [
13
- ts.factory.createStringLiteral(type.typeName),
14
- ts.factory.createObjectLiteralExpression([
15
- createDescriptionPropertyAssignment(type),
16
- ts.factory.createPropertyAssignment("values", ts.factory.createAsExpression(ts.factory.createObjectLiteralExpression(type.values
17
- .filter((v) => !v.isIgnored() && !v.isUnespecified())
18
- .map((ev) => ts.factory.createPropertyAssignment(ev.name, createEnumValueExpr(ev))), true // multiline
19
- ), ts.factory.createTypeReferenceNode("const"))),
20
- ts.factory.createPropertyAssignment("extensions", createExtensionsObjectLiteralExpr(type)),
21
- ].filter(onlyNonNull()), true),
22
- ]));
23
- }
24
- function createEnumValueExpr(ev) {
25
- return ts.factory.createObjectLiteralExpression([
26
- createDescriptionPropertyAssignment(ev),
27
- createDeprecationPropertyAssignment(ev),
28
- ts.factory.createPropertyAssignment("value", ts.factory.createNumericLiteral(ev.number)),
29
- ts.factory.createPropertyAssignment("extensions", createExtensionsObjectLiteralExprForEnumValue(ev)),
30
- ].filter(onlyNonNull()), true // multiline
31
- );
32
- }
33
- /**
34
- * @example
35
- * ```ts
36
- * {{
37
- * protobufEnum: {
38
- * name: "...",
39
- * fullName: "...",
40
- * package: "...",
41
- * },
42
- * } as ProtobufEnumExtensions)
43
- * ```
44
- */
45
- function createExtensionsObjectLiteralExpr(type) {
46
- return ts.factory.createObjectLiteralExpression([
47
- ts.factory.createPropertyAssignment("protobufEnum", ts.factory.createObjectLiteralExpression([
48
- ts.factory.createPropertyAssignment("name", ts.factory.createStringLiteral(type.proto.name)),
49
- ts.factory.createPropertyAssignment("fullName", ts.factory.createStringLiteral(type.proto.fullName.toString())),
50
- ts.factory.createPropertyAssignment("package", ts.factory.createStringLiteral(type.proto.file.package)),
51
- ], true)),
52
- ], true);
53
- }
54
- /**
55
- * @example
56
- * ```ts
57
- * ({
58
- * protobufEnumValue: {
59
- * name: "...",
60
- * },
61
- * } as ProtobufEnumValueExtensions)
62
- * ```
63
- */
64
- function createExtensionsObjectLiteralExprForEnumValue(ev) {
65
- return ts.factory.createObjectLiteralExpression([
66
- ts.factory.createPropertyAssignment("protobufEnumValue", ts.factory.createObjectLiteralExpression([ts.factory.createPropertyAssignment("name", ts.factory.createStringLiteral(ev.proto.name))], true)),
67
- ], true);
15
+ export function createEnumTypeCode(type, opts) {
16
+ const typeOpts = {
17
+ description: type.description,
18
+ values: code `{${joinCode(type.values
19
+ .filter((v) => !v.isIgnored() && !v.isUnespecified())
20
+ .map((ev) => code `${ev.name}: ${literalOf(compact({
21
+ description: ev.description,
22
+ deprecationReason: ev.deprecationReason,
23
+ value: ev.number,
24
+ extensions: {
25
+ protobufEnumValue: {
26
+ name: ev.proto.name,
27
+ },
28
+ },
29
+ }))},`))}} as const`,
30
+ extensions: protobufGraphQLExtensions(type),
31
+ };
32
+ return code `
33
+ export const ${pothosRef(type)} =
34
+ ${pothosBuilder(type, opts)}.enumType(${literalOf(type.typeName)}, ${literalOf(compact(typeOpts))});
35
+ `;
68
36
  }
@@ -1,9 +1,9 @@
1
- import { EnumType, InputObjectField, ObjectField, ObjectOneofField, ObjectType, ScalarType, SquashedOneofUnionType, } from "@proto-graphql/codegen-core";
2
- import ts from "typescript";
3
- import { createEnumResolverStmts } from "./fieldResolver/enumFieldResolver";
4
- import { createNonNullResolverStmts } from "./fieldResolver/nonNullResolver";
5
- import { createOneofUnionResolverStmts } from "./fieldResolver/oneofUnionResolver";
6
- import { createDeprecationPropertyAssignment, createDescriptionPropertyAssignment, onlyNonNull } from "./util";
1
+ import { compact, createGetFieldValueCode, EnumType, InputObjectField, ObjectField, ObjectOneofField, ObjectType, protobufGraphQLExtensions, ScalarType, SquashedOneofUnionType, } from "@proto-graphql/codegen-core";
2
+ import { code, literalOf } from "ts-poet";
3
+ import { createEnumResolverCode } from "./fieldResolver/enumFieldResolver";
4
+ import { createNonNullResolverCode } from "./fieldResolver/nonNullResolver";
5
+ import { createOneofUnionResolverCode } from "./fieldResolver/oneofUnionResolver";
6
+ import { fieldTypeRef } from "./util";
7
7
  /**
8
8
  * @example
9
9
  * ```ts
@@ -24,53 +24,45 @@ import { createDeprecationPropertyAssignment, createDescriptionPropertyAssignmen
24
24
  * })
25
25
  * ```
26
26
  */
27
- export function createFieldDefinitionExpr(field) {
28
- let typeExpr = field.type instanceof ScalarType
29
- ? ts.factory.createStringLiteral(field.type.typeName)
30
- : ts.factory.createIdentifier(field.type.pothosRefObjectName);
27
+ export function createFieldRefCode(field, opts) {
31
28
  const isInput = field instanceof InputObjectField;
32
- const nullableToken = ts.factory.createToken(isInput ? ts.SyntaxKind.FalseKeyword : ts.SyntaxKind.TrueKeyword);
33
- const nonNullableToken = ts.factory.createToken(isInput ? ts.SyntaxKind.TrueKeyword : ts.SyntaxKind.FalseKeyword);
34
- let nullableExpr = field.isNullable() ? nullableToken : nonNullableToken;
35
- // let defaultValueExpr: ts.Expression | undefined;
36
- if (field.isList()) {
37
- typeExpr = ts.factory.createArrayLiteralExpression([typeExpr], false);
38
- // if (isInput) {
39
- // defaultValueExpr = ts.factory.createArrayLiteralExpression([], false);
40
- // }
41
- nullableExpr = ts.factory.createObjectLiteralExpression([
42
- ts.factory.createPropertyAssignment("list", nullableExpr),
43
- ts.factory.createPropertyAssignment("items", nonNullableToken),
44
- ], false);
45
- }
46
- let createResolveStmts;
29
+ const baseType = field.type instanceof ScalarType ? literalOf(field.type.typeName) : fieldTypeRef(field, opts);
30
+ const sourceExpr = code `source`;
31
+ let resolverCode;
47
32
  if (!isInput) {
48
- const nullableInProto = field.type instanceof ObjectType ||
49
- (field.type instanceof ScalarType && !field.type.isPrimitive() && !field.type.isWrapperType());
50
- if (nullableInProto && !field.isNullable()) {
51
- createResolveStmts = (sourceExpr) => createNonNullResolverStmts(ts.factory.createPropertyAccessExpression(sourceExpr, field.protoJsName));
52
- }
53
- if (field.type instanceof EnumType && field instanceof ObjectField) {
54
- createResolveStmts = (sourceExpr) => createEnumResolverStmts(ts.factory.createPropertyAccessExpression(sourceExpr, field.protoJsName), field);
55
- }
56
33
  if (field instanceof ObjectOneofField) {
57
- createResolveStmts = (sourceExpr) => createOneofUnionResolverStmts(sourceExpr, field);
34
+ resolverCode = createOneofUnionResolverCode(sourceExpr, field);
58
35
  }
59
- if (field.type instanceof SquashedOneofUnionType && field instanceof ObjectField) {
60
- createResolveStmts = (sourceExpr) => createOneofUnionResolverStmts(ts.factory.createPropertyAccessExpression(sourceExpr, field.protoJsName), field);
36
+ else {
37
+ const valueExpr = createGetFieldValueCode(sourceExpr, field.proto, opts);
38
+ const nullableInProto = field.type instanceof ObjectType ||
39
+ (field.type instanceof ScalarType && !field.type.isPrimitive() && !field.type.isWrapperType());
40
+ if (nullableInProto && !field.isNullable()) {
41
+ resolverCode = createNonNullResolverCode(valueExpr);
42
+ }
43
+ if (field.type instanceof EnumType && field instanceof ObjectField) {
44
+ resolverCode = createEnumResolverCode(valueExpr, field, opts);
45
+ }
46
+ if (field.type instanceof SquashedOneofUnionType && field instanceof ObjectField) {
47
+ resolverCode = createOneofUnionResolverCode(valueExpr, field);
48
+ }
61
49
  }
62
50
  }
63
- const fieldOptionsExpr = ts.factory.createObjectLiteralExpression([
64
- ts.factory.createPropertyAssignment("type", typeExpr),
65
- ts.factory.createPropertyAssignment(isInput ? "required" : "nullable", nullableExpr),
66
- createDescriptionPropertyAssignment(field),
67
- createDeprecationPropertyAssignment(field),
68
- // defaultValueExpr && ts.factory.createPropertyAssignment("defaultValue", defaultValueExpr),
69
- createResolveStmts && ts.factory.createPropertyAssignment("resolve", createResolverExpr(createResolveStmts)),
70
- ts.factory.createPropertyAssignment("extensions", createExtensionsObjectLiteralExpr(field)),
71
- ].filter(onlyNonNull()), true);
72
- const shouldUseFieldFunc = field instanceof InputObjectField || createResolveStmts != null;
73
- return ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier("t"), ts.factory.createIdentifier(shouldUseFieldFunc ? "field" : "expose")), undefined, shouldUseFieldFunc ? [fieldOptionsExpr] : [ts.factory.createStringLiteral(field.protoJsName), fieldOptionsExpr]);
51
+ const nullableValue = isInput !== field.isNullable(); /* Logical XOR */
52
+ const fieldOpts = {
53
+ type: field.isList() ? code `[${baseType}]` : baseType,
54
+ [isInput ? "required" : "nullable"]: field.isList()
55
+ ? { list: nullableValue, items: isInput /* always non-null */ }
56
+ : nullableValue,
57
+ description: field.description,
58
+ deprecationReason: field.deprecationReason,
59
+ resolve: resolverCode ? code `${sourceExpr} => {${resolverCode}}` : null,
60
+ extensions: protobufGraphQLExtensions(field),
61
+ };
62
+ const shouldUseFieldFunc = isInput || resolverCode != null;
63
+ return shouldUseFieldFunc
64
+ ? code `t.field(${literalOf(compact(fieldOpts))})`
65
+ : code `t.expose(${literalOf(field.proto.jsonName)}, ${literalOf(compact(fieldOpts))})`;
74
66
  }
75
67
  /**
76
68
  * @example
@@ -85,51 +77,13 @@ export function createFieldDefinitionExpr(field) {
85
77
  * })
86
78
  * ```
87
79
  */
88
- export function createNoopFieldDefinitionExpr(opts) {
89
- return ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier("t"), ts.factory.createIdentifier("field")), undefined, [
90
- ts.factory.createObjectLiteralExpression([
91
- ts.factory.createPropertyAssignment("type", ts.factory.createStringLiteral("Boolean")),
92
- opts.input
93
- ? ts.factory.createPropertyAssignment("required", ts.factory.createToken(ts.SyntaxKind.FalseKeyword))
94
- : ts.factory.createPropertyAssignment("nullable", ts.factory.createToken(ts.SyntaxKind.TrueKeyword)),
95
- ts.factory.createPropertyAssignment("description", ts.factory.createStringLiteral("noop field")),
96
- opts.input
97
- ? null
98
- : ts.factory.createMethodDeclaration(undefined, undefined, undefined, "resolve", undefined, undefined, [], undefined, ts.factory.createBlock([
99
- ts.factory.createReturnStatement(ts.factory.createToken(ts.SyntaxKind.TrueKeyword)),
100
- ])),
101
- ].filter(onlyNonNull()), true),
102
- ]);
103
- }
104
- function createResolverExpr(createStmts) {
105
- return ts.factory.createArrowFunction(undefined, undefined, [ts.factory.createParameterDeclaration(undefined, undefined, undefined, ts.factory.createIdentifier("source"))], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBlock(createStmts(ts.factory.createIdentifier("source")), true));
106
- }
107
- /**
108
- * @example
109
- * ```ts
110
- * ({
111
- * protobufField: {
112
- * name: "...",
113
- * },
114
- * } as ProtobufFieldExtensions)
115
- * ```
116
- */
117
- function createExtensionsObjectLiteralExpr(field) {
118
- let typeName;
119
- if ((field instanceof ObjectField || field instanceof InputObjectField) && field.proto.type !== null) {
120
- if (field.proto.type.kind === "Scalar") {
121
- typeName = field.proto.type.type;
122
- }
123
- else {
124
- typeName = field.proto.type.fullName.toString();
125
- }
126
- }
127
- return ts.factory.createObjectLiteralExpression([
128
- ts.factory.createPropertyAssignment("protobufField", ts.factory.createObjectLiteralExpression([
129
- ts.factory.createPropertyAssignment("name", ts.factory.createStringLiteral(field.proto.name)),
130
- typeName
131
- ? ts.factory.createPropertyAssignment("typeFullName", ts.factory.createStringLiteral(typeName))
132
- : undefined,
133
- ].filter(onlyNonNull()), true)),
134
- ], true);
80
+ export function createNoopFieldRefCode(opts) {
81
+ return code `
82
+ t.field({
83
+ type: "Boolean",
84
+ ${opts.input ? "required: false" : "nullable: true"},
85
+ description: "noop field",
86
+ ${opts.input ? "" : "resolve: () => true,"}
87
+ })
88
+ `;
135
89
  }
@@ -1,5 +1,5 @@
1
- import ts from "typescript";
2
- import { createFullNameExpr, onlyNonNull } from "../util";
1
+ import { protoType } from "@proto-graphql/codegen-core";
2
+ import { code } from "ts-poet";
3
3
  /**
4
4
  * @example nullable
5
5
  * ```ts
@@ -16,46 +16,42 @@ import { createFullNameExpr, onlyNonNull } from "../util";
16
16
  * return root.myEnum
17
17
  * ```
18
18
  */
19
- export function createEnumResolverStmts(valueExpr, field) {
20
- let whenNullStmt = field.isNullable() && !field.isList()
21
- ? ts.factory.createReturnStatement(ts.factory.createToken(ts.SyntaxKind.NullKeyword))
22
- : ts.factory.createThrowStatement(ts.factory.createNewExpression(ts.factory.createIdentifier("Error"), undefined, [
23
- ts.factory.createStringLiteral(`${field.name} is required field. But got unspecified.`),
24
- ]));
25
- whenNullStmt = ts.factory.createBlock([whenNullStmt], true // multiline
26
- );
19
+ export function createEnumResolverCode(valueExpr, field, opts) {
20
+ const createBlockStmtCodes = (valueExpr) => {
21
+ const chunks = [];
22
+ if (field.type.unspecifiedValue != null) {
23
+ const escapeCode = field.isNullable() && !field.isList()
24
+ ? code `return null;`
25
+ : code `throw new Error("${field.name} is required field. But got unspecified.");`;
26
+ chunks.push(code `
27
+ if (${valueExpr} === ${protoType(field.type.proto, opts)}.${field.type.unspecifiedValue.proto.name}) {
28
+ ${escapeCode}
29
+ }
30
+ `);
31
+ }
32
+ for (const ev of field.type.valuesWithIgnored) {
33
+ if (!ev.isIgnored())
34
+ continue;
35
+ chunks.push(code `
36
+ if (${valueExpr} === ${protoType(field.type.proto, opts)}.${ev.proto.name}) {
37
+ throw new Error("${ev.name} is ignored in GraphQL schema");
38
+ }
39
+ `);
40
+ }
41
+ return chunks;
42
+ };
27
43
  if (field.isList()) {
28
- const guardStmts = createGuardStmts(ts.factory.createIdentifier("item"), whenNullStmt, field.type.unspecifiedValue, field.type.valuesWithIgnored);
29
- if (guardStmts.length === 0) {
30
- return [ts.factory.createReturnStatement(valueExpr)];
44
+ const stmts = createBlockStmtCodes(code `item`);
45
+ if (stmts.length === 0) {
46
+ return code `return ${valueExpr}`;
31
47
  }
32
- return [
33
- ts.factory.createReturnStatement(createMapExpr(valueExpr, (itemExpr) => [...guardStmts, ts.factory.createReturnStatement(itemExpr)])),
34
- ];
48
+ return code `return ${valueExpr}.map(item => {
49
+ ${stmts}
50
+ return item;
51
+ })`;
35
52
  }
36
- return [
37
- ...createGuardStmts(valueExpr, whenNullStmt, field.type.unspecifiedValue, field.type.valuesWithIgnored),
38
- ts.factory.createReturnStatement(valueExpr),
39
- ];
40
- }
41
- function createGuardStmts(valueExpr, thenStmt, unspecifiedValue, ignoredValues) {
42
- return [
43
- unspecifiedValue
44
- ? ts.factory.createIfStatement(ts.factory.createBinaryExpression(valueExpr, ts.SyntaxKind.EqualsEqualsEqualsToken, createFullNameExpr(unspecifiedValue.fullName)), thenStmt)
45
- : null,
46
- ...ignoredValues.map((ev) => ev.isIgnored()
47
- ? ts.factory.createIfStatement(ts.factory.createBinaryExpression(valueExpr, ts.SyntaxKind.EqualsEqualsEqualsToken, createFullNameExpr(ev.fullName)), ts.factory.createBlock([
48
- ts.factory.createThrowStatement(ts.factory.createNewExpression(ts.factory.createIdentifier("Error"), undefined, [
49
- ts.factory.createStringLiteral(`${ev.name} is ignored in GraphQL schema`),
50
- ])),
51
- ], true // multiline
52
- ))
53
- : null),
54
- ].filter(onlyNonNull());
55
- }
56
- function createMapExpr(listExpr, blockFn) {
57
- return ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(listExpr, "map"), undefined, [
58
- ts.factory.createArrowFunction(undefined, undefined, [ts.factory.createParameterDeclaration(undefined, undefined, undefined, "item", undefined, undefined, undefined)], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBlock(blockFn(ts.factory.createIdentifier("item")), true // multiline
59
- )),
60
- ]);
53
+ return code `
54
+ ${createBlockStmtCodes(valueExpr)}
55
+ return ${valueExpr};
56
+ `;
61
57
  }
@@ -1,4 +1,6 @@
1
- import ts from "typescript";
2
- export function createNonNullResolverStmts(valueExpr) {
3
- return [ts.factory.createReturnStatement(ts.factory.createNonNullExpression(valueExpr))];
1
+ import { code } from "ts-poet";
2
+ export function createNonNullResolverCode(valueExpr) {
3
+ return code `
4
+ return ${valueExpr}!;
5
+ `;
4
6
  }
@@ -1,6 +1,5 @@
1
1
  import { ObjectField, ObjectOneofField } from "@proto-graphql/codegen-core";
2
- import ts from "typescript";
3
- import { onlyNonNull } from "../util";
2
+ import { code, joinCode } from "ts-poet";
4
3
  /**
5
4
  * @example nullable
6
5
  * ```ts
@@ -11,44 +10,28 @@ import { onlyNonNull } from "../util";
11
10
  * return value
12
11
  * ```
13
12
  */
14
- export function createOneofUnionResolverStmts(sourceExpr, field) {
15
- const createResolverStmts = (sourceExpr, field, { nullable }) => {
13
+ export function createOneofUnionResolverCode(sourceExpr, field) {
14
+ const createBlockStmtCode = (sourceExpr, { nullable }) => {
16
15
  const createFieldExpr = (memberField) => {
17
16
  if (field instanceof ObjectOneofField) {
18
- return ts.factory.createPropertyAccessExpression(sourceExpr, memberField.protoJsName);
17
+ return code `${sourceExpr}.${memberField.proto.jsonName}`;
19
18
  }
20
- return ts.factory.createPropertyAccessChain(sourceExpr, ts.factory.createToken(ts.SyntaxKind.QuestionDotToken), memberField.protoJsName);
19
+ return code `${sourceExpr}?.${memberField.proto.jsonName}`;
21
20
  };
22
- const valueExpr = ts.factory.createIdentifier("value");
23
- return [
24
- ts.factory.createVariableStatement(undefined, ts.factory.createVariableDeclarationList([
25
- ts.factory.createVariableDeclaration("value", undefined, undefined,
26
- // obj.field1 ?? obj.field2 ?? obj.field3 ?? ...
27
- field.type.fields.reduceRight((expr, field) => {
28
- if (expr == null) {
29
- return createFieldExpr(field);
30
- }
31
- return ts.factory.createBinaryExpression(createFieldExpr(field), ts.factory.createToken(ts.SyntaxKind.QuestionQuestionToken), expr);
32
- }, null)),
33
- ], ts.NodeFlags.Const)),
34
- nullable
35
- ? undefined
36
- : ts.factory.createIfStatement(ts.factory.createBinaryExpression(valueExpr, ts.SyntaxKind.EqualsEqualsToken, ts.factory.createToken(ts.SyntaxKind.NullKeyword)), ts.factory.createBlock([
37
- ts.factory.createThrowStatement(ts.factory.createNewExpression(ts.factory.createIdentifier("Error"), undefined, [
38
- ts.factory.createStringLiteral(`${field.name} should not be null`),
39
- ])),
40
- ], true)),
41
- ts.factory.createReturnStatement(valueExpr),
42
- ].filter(onlyNonNull());
21
+ return code `
22
+ const value = ${joinCode(field.type.fields.map(createFieldExpr), { on: "??" })};
23
+ if (value == null) {
24
+ ${nullable ? "return null" : `throw new Error("${field.name} should not be null")`};
25
+ }
26
+ return value;
27
+ `;
43
28
  };
44
- if (!(field instanceof ObjectField && field.isList())) {
45
- return createResolverStmts(sourceExpr, field, { nullable: field.isNullable() });
29
+ if (field instanceof ObjectField && field.isList()) {
30
+ return code `
31
+ return ${sourceExpr}.map(item => {
32
+ ${createBlockStmtCode(code `item`, { nullable: false })}
33
+ })
34
+ `;
46
35
  }
47
- return [
48
- ts.factory.createReturnStatement(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(sourceExpr, "map"), undefined, [
49
- ts.factory.createArrowFunction(undefined, undefined, [
50
- ts.factory.createParameterDeclaration(undefined, undefined, undefined, "item", undefined, undefined, undefined),
51
- ], undefined, ts.factory.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.factory.createBlock(createResolverStmts(ts.factory.createIdentifier("item"), field, { nullable: false }), true)),
52
- ])),
53
- ];
36
+ return createBlockStmtCode(sourceExpr, { nullable: field.isNullable() });
54
37
  }
@@ -1,53 +1,23 @@
1
1
  import { EnumType, InputObjectType, ObjectType, OneofUnionType, SquashedOneofUnionType, } from "@proto-graphql/codegen-core";
2
- import ts from "typescript";
3
- import { createEnumTypeDslStmt } from "./enumType";
4
- import { createInputObjectTypeDslStmts } from "./inputObjectType";
5
- import { createObjectTypeDslStmts } from "./objectType";
6
- import { createOneofUnionTypeDslStmt } from "./oneofUnionType";
7
- import { createImportDecl, createQualifiedName, fullNameString, onlyNonNull, onlyUnique } from "./util";
8
- export function createImportDecls(types) {
9
- return types
10
- .flatMap((t) => t.importModules)
11
- .filter(onlyUnique((m) => JSON.stringify([m.alias, m.module])))
12
- .sort(({ module: a }, { module: b }) => {
13
- const pat = /^\.+\//;
14
- const [aIsRel, bIsRel] = [a.match(pat), b.match(pat)];
15
- if (aIsRel && !bIsRel)
16
- return 1;
17
- if (!aIsRel && bIsRel)
18
- return -1;
19
- if (a < b)
20
- return -1;
21
- if (a > b)
22
- return 1;
23
- return 0;
24
- })
25
- .map((m) => createImportDecl(m));
26
- }
27
- export function createReExportStmts(types) {
28
- return types
29
- .flatMap((t) => t.exportTypes)
30
- .sort()
31
- .filter(onlyUnique(({ type }) => fullNameString(type)))
32
- .map(({ name, type }) => ts.factory.createTypeAliasDeclaration(undefined, [ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], name, undefined, ts.factory.createTypeReferenceNode(createQualifiedName(type))));
33
- }
34
- export function createTypeDslStmts(types) {
35
- return types
36
- .flatMap((type) => {
2
+ import { createEnumTypeCode } from "./enumType";
3
+ import { createInputObjectTypeCode } from "./inputObjectType";
4
+ import { createObjectTypeCode } from "./objectType";
5
+ import { createOneofUnionTypeCode } from "./oneofUnionType";
6
+ export function createTypeDslCodes(types, opts) {
7
+ return types.flatMap((type) => {
37
8
  if (type instanceof ObjectType) {
38
- return createObjectTypeDslStmts(type);
9
+ return createObjectTypeCode(type, opts);
39
10
  }
40
11
  if (type instanceof InputObjectType) {
41
- return createInputObjectTypeDslStmts(type);
12
+ return createInputObjectTypeCode(type, opts);
42
13
  }
43
14
  if (type instanceof EnumType) {
44
- return [createEnumTypeDslStmt(type)];
15
+ return [createEnumTypeCode(type, opts)];
45
16
  }
46
17
  if (type instanceof OneofUnionType || type instanceof SquashedOneofUnionType) {
47
- return [createOneofUnionTypeDslStmt(type)];
18
+ return [createOneofUnionTypeCode(type, opts)];
48
19
  }
49
20
  const _exhaustiveCheck = type;
50
21
  throw "unreachable";
51
- })
52
- .filter(onlyNonNull());
22
+ });
53
23
  }
@@ -1,12 +1,14 @@
1
- import { InputObjectType } from "@proto-graphql/codegen-core";
2
- import ts from "typescript";
3
- import { createFieldDefinitionExpr, createNoopFieldDefinitionExpr } from "./field";
4
- import { createBuilderPropExpr, createDescriptionPropertyAssignment, createDslExportConstStmt, createQualifiedName, onlyNonNull, } from "./util";
1
+ import { compact, InputObjectType, protobufGraphQLExtensions, protoType } from "@proto-graphql/codegen-core";
2
+ import { code, imp, joinCode, literalOf } from "ts-poet";
3
+ import { createFieldRefCode, createNoopFieldRefCode } from "./field";
4
+ import { fieldTypeShape, pothosBuilder, pothosRef, shapeType } from "./util";
5
5
  /**
6
6
  * @example
7
7
  * ```ts
8
- * export const HelloInput = builder.inputRef<Omit<_$hello$hello_pb.Hello, "$type">>("HelloInput");
9
- * HelloInput.implement({
8
+ * export type HelloInput$Shape = {
9
+ * // ...
10
+ * }
11
+ * export const HelloInput$Ref: pothos.InputObjectRef<Hello$SHape> = builder.inputRef("HelloInput").implement({
10
12
  * description: "...",
11
13
  * fields: (t) => ({
12
14
  * // ...
@@ -14,80 +16,38 @@ import { createBuilderPropExpr, createDescriptionPropertyAssignment, createDslEx
14
16
  * })
15
17
  * ```
16
18
  */
17
- export function createInputObjectTypeDslStmts(type) {
18
- return [
19
- createInputObjectTypeShapeDecl(type),
20
- createDslExportConstStmt(type.pothosRefObjectName, ts.factory.createCallExpression(createBuilderPropExpr("inputRef"), [ts.factory.createTypeReferenceNode(createInputObjectTypeShapeIdent(type))], [ts.factory.createStringLiteral(type.typeName)])),
21
- ts.factory.createExpressionStatement(ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(type.pothosRefObjectName), "implement"), undefined, [
22
- ts.factory.createObjectLiteralExpression([
23
- createDescriptionPropertyAssignment(type),
24
- ts.factory.createPropertyAssignment("fields", createInputObjectTypeFieldsMethodExpr(type)),
25
- ts.factory.createPropertyAssignment("extensions", createExtensionsObjectLiteralExpr(type)),
26
- ].filter(onlyNonNull()), true),
27
- ])),
28
- ];
29
- }
30
- /**
31
- * @example
32
- * ```ts
33
- * definition(t) {
34
- * // ...
35
- * }
36
- * ```
37
- */
38
- function createInputObjectTypeFieldsMethodExpr(type) {
39
- 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(type.fields.length > 0
40
- ? type.fields.map((f) => ts.factory.createPropertyAssignment(f.name, createFieldDefinitionExpr(f)))
41
- : [ts.factory.createPropertyAssignment("_", createNoopFieldDefinitionExpr({ input: true }))], true)));
42
- }
43
- /**
44
- * @example
45
- * ```ts
46
- * {
47
- * message?: _$hello$hello_pb$Hello["message"] | null,
48
- * // ...
49
- * }
50
- * ```
51
- */
52
- function createInputObjectTypeShapeDecl(type) {
53
- return ts.factory.createTypeAliasDeclaration(undefined, [ts.factory.createToken(ts.SyntaxKind.ExportKeyword)], createInputObjectTypeShapeIdent(type), undefined, ts.factory.createTypeLiteralNode(type.fields.map((field) => {
54
- let typeNode = ts.factory.createIndexedAccessTypeNode(ts.factory.createTypeReferenceNode(createQualifiedName(type.protoTypeFullName)), ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral(field.protoJsName)));
55
- if (field.type instanceof InputObjectType) {
56
- typeNode = ts.factory.createTypeReferenceNode(createInputObjectTypeShapeIdent(field.type));
57
- if (field.isList()) {
58
- typeNode = ts.factory.createTypeReferenceNode("Array", [typeNode]);
59
- }
19
+ export function createInputObjectTypeCode(type, opts) {
20
+ const shapeTypeCode = code `
21
+ export type ${shapeType(type)} = {
22
+ ${joinCode(type.fields.map((f) => {
23
+ let typeNode;
24
+ if (f.type instanceof InputObjectType) {
25
+ // @ts-expect-error f should be inferred as InputObjectField<InputObjectType>
26
+ typeNode = code `${fieldTypeShape(f, opts)}`;
27
+ if (f.isList())
28
+ typeNode = code `Array<${typeNode}>`;
60
29
  }
61
- if (field.isNullable()) {
62
- typeNode = ts.factory.createUnionTypeNode([
63
- typeNode,
64
- ts.factory.createLiteralTypeNode(ts.factory.createToken(ts.SyntaxKind.NullKeyword)),
65
- ]);
30
+ else {
31
+ typeNode = code `${protoType(type.proto, opts)}[${literalOf(f.proto.jsonName)}]`;
66
32
  }
67
- return ts.factory.createPropertySignature(undefined, field.name, field.isNullable() ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) : undefined, typeNode);
68
- })));
69
- }
70
- function createInputObjectTypeShapeIdent(type) {
71
- return ts.factory.createIdentifier(`${type.typeName}$Shape`);
72
- }
73
- /**
74
- * @example
75
- * ```ts
76
- * {
77
- * protobufMessage: {
78
- * fullName: "...",
79
- * name: "...",
80
- * package: "...",
81
- * },
82
- * }
83
- * ```
84
- */
85
- function createExtensionsObjectLiteralExpr(type) {
86
- return ts.factory.createObjectLiteralExpression([
87
- ts.factory.createPropertyAssignment("protobufMessage", ts.factory.createObjectLiteralExpression([
88
- ts.factory.createPropertyAssignment("fullName", ts.factory.createStringLiteral(type.proto.fullName.toString())),
89
- ts.factory.createPropertyAssignment("name", ts.factory.createStringLiteral(type.proto.name)),
90
- ts.factory.createPropertyAssignment("package", ts.factory.createStringLiteral(type.proto.file.package)),
91
- ], true)),
92
- ], true);
33
+ return f.isNullable() ? code `${f.name}?: ${typeNode} | null,` : code `${f.name}: ${typeNode},`;
34
+ }))}
35
+ };
36
+ `;
37
+ const refCode = code `
38
+ export const ${pothosRef(type)}: ${imp("InputObjectRef@@pothos/core")}<${shapeType(type)}> =
39
+ ${pothosBuilder(type, opts)}.inputRef<${shapeType(type)}>(${literalOf(type.typeName)}).implement(
40
+ ${literalOf(compact({
41
+ description: type.description,
42
+ fields: code `t => ({${type.fields.length > 0
43
+ ? type.fields.map((f) => code `${f.name}: ${createFieldRefCode(f, opts)},`)
44
+ : code `_: ${createNoopFieldRefCode({ input: true })}`}})`,
45
+ extensions: protobufGraphQLExtensions(type),
46
+ }))}
47
+ );
48
+ `;
49
+ return code `
50
+ ${shapeTypeCode}
51
+ ${refCode}
52
+ `;
93
53
  }