fix: keep enum values in types generation
This commit is contained in:
6 files changed
+128
-9
No files matched your search
@@ -234,6 +234,7 @@ function cleanAndMergeSchema(loadedSchema) {
|
|||||||
const defaultMedusaSchema = `
|
const defaultMedusaSchema = `
|
||||||
scalar DateTime
|
scalar DateTime
|
||||||
scalar JSON
|
scalar JSON
|
||||||
|
directive @enumValue(value: String) on ENUM_VALUE
|
||||||
`
|
`
|
||||||
const { schema: cleanedSchema, notFound } = GraphQLUtils.cleanGraphQLSchema(
|
const { schema: cleanedSchema, notFound } = GraphQLUtils.cleanGraphQLSchema(
|
||||||
defaultMedusaSchema + loadedSchema
|
defaultMedusaSchema + loadedSchema
|
||||||
|
|||||||
@@ -13,6 +13,11 @@ describe("GraphQL builder", () => {
|
|||||||
isVerified: model.boolean(),
|
isVerified: model.boolean(),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
enum DepartmentEnum {
|
||||||
|
FinanceDept = "finance",
|
||||||
|
MarketingDept = "marketing",
|
||||||
|
}
|
||||||
|
|
||||||
const user = model.define("user", {
|
const user = model.define("user", {
|
||||||
id: model.id(),
|
id: model.id(),
|
||||||
username: model.text(),
|
username: model.text(),
|
||||||
@@ -21,8 +26,9 @@ describe("GraphQL builder", () => {
|
|||||||
phones: model.array(),
|
phones: model.array(),
|
||||||
group: model.belongsTo(() => group, { mappedBy: "users" }),
|
group: model.belongsTo(() => group, { mappedBy: "users" }),
|
||||||
role: model
|
role: model
|
||||||
.enum(["moderator", "admin", "guest", "new_user"])
|
.enum(["moderator", "admin", "guest", "new-user"])
|
||||||
.default("guest"),
|
.default("guest"),
|
||||||
|
department: model.enum(DepartmentEnum),
|
||||||
tags: model.manyToMany(() => tag, {
|
tags: model.manyToMany(() => tag, {
|
||||||
pivotTable: "custom_user_tags",
|
pivotTable: "custom_user_tags",
|
||||||
}),
|
}),
|
||||||
@@ -59,10 +65,15 @@ describe("GraphQL builder", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum UserRoleEnum {
|
enum UserRoleEnum {
|
||||||
MODERATOR
|
MODERATOR @enumValue(value: "moderator")
|
||||||
ADMIN
|
ADMIN @enumValue(value: "admin")
|
||||||
GUEST
|
GUEST @enumValue(value: "guest")
|
||||||
NEW_USER
|
NEW_USER @enumValue(value: "new-user")
|
||||||
|
}
|
||||||
|
|
||||||
|
enum UserDepartmentEnum {
|
||||||
|
FINANCE @enumValue(value: "finance")
|
||||||
|
MARKETING @enumValue(value: "marketing")
|
||||||
}
|
}
|
||||||
|
|
||||||
type User {
|
type User {
|
||||||
@@ -74,6 +85,7 @@ describe("GraphQL builder", () => {
|
|||||||
group_id:String!
|
group_id:String!
|
||||||
group: Group!
|
group: Group!
|
||||||
role: UserRoleEnum!
|
role: UserRoleEnum!
|
||||||
|
department: UserDepartmentEnum!
|
||||||
tags: [Tag]!
|
tags: [Tag]!
|
||||||
raw_spend_limit: JSON!
|
raw_spend_limit: JSON!
|
||||||
created_at: DateTime!
|
created_at: DateTime!
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export function getGraphQLAttributeFromDMLPropety(
|
|||||||
const enumValues = field.dataType
|
const enumValues = field.dataType
|
||||||
.options!.choices.map((value) => {
|
.options!.choices.map((value) => {
|
||||||
const enumValue = value.replace(/[^a-z0-9_]/gi, "_").toUpperCase()
|
const enumValue = value.replace(/[^a-z0-9_]/gi, "_").toUpperCase()
|
||||||
return ` ${enumValue}`
|
return ` ${enumValue} @enumValue(value: "${value}")`
|
||||||
})
|
})
|
||||||
.join("\n")
|
.join("\n")
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
.test-output
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
import { makeExecutableSchema } from "@graphql-tools/schema"
|
||||||
|
import fs from "fs"
|
||||||
|
import path from "path"
|
||||||
|
import { gqlSchemaToTypes } from "../graphql-to-ts-types"
|
||||||
|
|
||||||
|
describe("gqlSchemaToTypes", () => {
|
||||||
|
it("should use enumValue directive for enum values", async () => {
|
||||||
|
const schema = `
|
||||||
|
directive @enumValue(value: String) on ENUM_VALUE
|
||||||
|
|
||||||
|
enum Test {
|
||||||
|
Test_A @enumValue(value: "test-a")
|
||||||
|
Test_B
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const executableSchema = makeExecutableSchema({
|
||||||
|
typeDefs: schema,
|
||||||
|
})
|
||||||
|
|
||||||
|
await gqlSchemaToTypes({
|
||||||
|
schema: executableSchema,
|
||||||
|
outputDir: path.resolve(__dirname, ".test-output/enum-values"),
|
||||||
|
filename: "query-entry-points",
|
||||||
|
joinerConfigs: [],
|
||||||
|
interfaceName: "RemoteQueryEntryPoints",
|
||||||
|
})
|
||||||
|
|
||||||
|
const expectedTypes = `
|
||||||
|
import "@medusajs/framework/types"
|
||||||
|
export type Maybe<T> = T | null;
|
||||||
|
export type InputMaybe<T> = Maybe<T>;
|
||||||
|
export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
|
||||||
|
export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> };
|
||||||
|
export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> };
|
||||||
|
export type MakeEmpty<T extends { [key: string]: unknown }, K extends keyof T> = { [_ in K]?: never };
|
||||||
|
export type Incremental<T> = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never };
|
||||||
|
/** All built-in and custom scalars, mapped to their actual values */
|
||||||
|
export type Scalars = {
|
||||||
|
ID: { input: string; output: string; }
|
||||||
|
String: { input: string; output: string; }
|
||||||
|
Boolean: { input: boolean; output: boolean; }
|
||||||
|
Int: { input: number; output: number; }
|
||||||
|
Float: { input: number; output: number; }
|
||||||
|
};
|
||||||
|
|
||||||
|
export enum Test {
|
||||||
|
TestA = 'test-a',
|
||||||
|
TestB = 'Test_B'
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module '@medusajs/framework/types' {
|
||||||
|
interface RemoteQueryEntryPoints {
|
||||||
|
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
|
||||||
|
const fileName = ".test-output/enum-values/query-entry-points.d.ts"
|
||||||
|
const generatedTypes = fs
|
||||||
|
.readFileSync(path.resolve(__dirname, fileName))
|
||||||
|
.toString()
|
||||||
|
expect(normalizeFile(generatedTypes)).toEqual(normalizeFile(expectedTypes))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const normalizeFile = (file: string) => {
|
||||||
|
return file.replace(/^\s+/g, "").replace(/\s+/g, " ").trim()
|
||||||
|
}
|
||||||
@@ -1,7 +1,14 @@
|
|||||||
import { codegen } from "@graphql-codegen/core"
|
import { codegen } from "@graphql-codegen/core"
|
||||||
import * as typescriptPlugin from "@graphql-codegen/typescript"
|
import * as typescriptPlugin from "@graphql-codegen/typescript"
|
||||||
import { ModuleJoinerConfig } from "@medusajs/types"
|
import { ModuleJoinerConfig } from "@medusajs/types"
|
||||||
import { type GraphQLSchema, parse, printSchema } from "graphql"
|
import {
|
||||||
|
EnumTypeDefinitionNode,
|
||||||
|
EnumValueDefinitionNode,
|
||||||
|
type GraphQLSchema,
|
||||||
|
Kind,
|
||||||
|
parse,
|
||||||
|
printSchema,
|
||||||
|
} from "graphql"
|
||||||
import { FileSystem } from "../common"
|
import { FileSystem } from "../common"
|
||||||
|
|
||||||
function buildEntryPointsTypeMap({
|
function buildEntryPointsTypeMap({
|
||||||
@@ -87,6 +94,35 @@ ${entryPoints
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getEnumValues = (schema: GraphQLSchema) => {
|
||||||
|
const enumTypes = Object.values(schema.getTypeMap()).filter(
|
||||||
|
(type) => type.astNode?.kind === Kind.ENUM_TYPE_DEFINITION
|
||||||
|
)
|
||||||
|
|
||||||
|
const enumValues = {}
|
||||||
|
enumTypes.forEach((type) => {
|
||||||
|
const enumName = type.name
|
||||||
|
enumValues[enumName] = {}
|
||||||
|
|
||||||
|
const nodes = (type.astNode as EnumTypeDefinitionNode).values || []
|
||||||
|
nodes.forEach((node: EnumValueDefinitionNode) => {
|
||||||
|
const directive = node.directives?.find(
|
||||||
|
(d) => d.name.value === "enumValue"
|
||||||
|
)
|
||||||
|
if (directive) {
|
||||||
|
const valueArg = directive.arguments?.find(
|
||||||
|
(a) => a.name.value === "value"
|
||||||
|
)
|
||||||
|
if (valueArg && valueArg.value.kind === Kind.STRING) {
|
||||||
|
enumValues[enumName][node.name.value] = valueArg.value.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return enumValues
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: rename from gqlSchemaToTypes to grapthqlToTsTypes
|
// TODO: rename from gqlSchemaToTypes to grapthqlToTsTypes
|
||||||
export async function gqlSchemaToTypes({
|
export async function gqlSchemaToTypes({
|
||||||
schema,
|
schema,
|
||||||
@@ -118,9 +154,10 @@ export async function gqlSchemaToTypes({
|
|||||||
filename: "",
|
filename: "",
|
||||||
schema: parse(printSchema(schema as any)),
|
schema: parse(printSchema(schema as any)),
|
||||||
plugins: [
|
plugins: [
|
||||||
// Each plugin should be an object
|
|
||||||
{
|
{
|
||||||
typescript: {}, // Here you can pass configuration to the plugin
|
typescript: {
|
||||||
|
enumValues: getEnumValues(schema),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
pluginMap: {
|
pluginMap: {
|
||||||
|
|||||||
Reference in new issue
Block a user