From 9a10a1155266f50890655f8bb8ad76fbd799cbf7 Mon Sep 17 00:00:00 2001 From: orta Date: Thu, 5 Sep 2024 11:23:38 +0100 Subject: [PATCH 1/5] Moves the lib to be async to match prettier --- CHANGELOG.md | 6 ++++- package.json | 3 +-- src/formatDTS.ts | 26 ++++++------------- src/index.ts | 26 +++++++++---------- src/serviceFile.ts | 7 +++-- src/sharedSchema.ts | 18 ++++++------- .../bugs/parentCanBeGraphQLObject.test.ts | 4 +-- ...returnObjectCanBeGraphQLInterfaces.test.ts | 4 +-- .../features/generatesTypesForUnions.test.ts | 4 +-- .../features/preferPromiseFnWhenKnown.test.ts | 4 +-- ...turnTypePositionsWhichPreferPrisma.test.ts | 4 +-- .../features/supportGenericExtension.test.ts | 4 +-- .../supportRefferingToEnumsOnlyInSDL.test.ts | 4 +-- .../warnOnSuperfluousResolvers.test.ts | 4 +-- src/tests/serviceFile.test.ts | 10 +++---- src/tests/testRunner.ts | 6 ++--- 16 files changed, 62 insertions(+), 72 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4b251b..d05a0fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,12 @@ # Changelog +### 2.0.0 + +Redwood uses prettier 3, and prettier 3 removes the sync API. This means we now have to operate entirely async. This is a breaking change from the sdl-codegen API, as you need to await the exposed public fns. + ### 1.1.2 -Removed this because its over-reaching: +Pulled back this a lot because its over-reaching: - When a resolver is simply a fn to a literal, narrow to that exact type in the codegen (instead of keeping the optional promise type) diff --git a/package.json b/package.json index 0f1cf88..0a62a84 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@sdl-codegen/node", - "version": "1.1.2", + "version": "2.0.0", "description": "GraphQL .d.ts file generation for SDL-first projects", "repository": { "type": "git", @@ -39,7 +39,6 @@ }, "dependencies": { "@mrleebo/prisma-ast": "^0.12.0", - "@prettier/sync": "0.5.2", "ts-morph": "^22.0.0" }, "devDependencies": { diff --git a/src/formatDTS.ts b/src/formatDTS.ts index 6e5b54a..3adf0ca 100644 --- a/src/formatDTS.ts +++ b/src/formatDTS.ts @@ -5,24 +5,14 @@ try { hasPrettierInstalled = !!require.resolve("prettier") } catch (error) {} -import * as prettier from "@prettier/sync" - -export const getPrettierConfig = (path: string): unknown => { - if (!hasPrettierInstalled) return {} - - if (!prettier?.default?.resolveConfig) return {} - if (typeof prettier.default.resolveConfig !== "function") return {} - - // I confirmed that this lookup hits caches in RedwoodJS - return prettier.default.resolveConfig(path) ?? {} -} - -export const formatDTS = (path: string, content: string, config: unknown): string => { +export const formatDTS = async (path: string, content: string): Promise => { if (!hasPrettierInstalled) return content - if (!prettier?.default?.format) return content - if (typeof prettier.default.format !== "function") return content - - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call - return prettier.default.format(content, { ...(config as object), filepath: path }) as string + try { + const prettier = await import("prettier") + if (!prettier) return content + return prettier.format(content, { filepath: path }) + } catch (error) { + return content + } } diff --git a/src/index.ts b/src/index.ts index dd5ea21..4afd20f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,11 +23,11 @@ interface SDLCodeGenReturn { } /** The API specifically for the Redwood preset */ -export function runFullCodegen(preset: "redwood", config: { paths: RedwoodPaths; verbose?: true }): SDLCodeGenReturn +export async function runFullCodegen(preset: "redwood", config: { paths: RedwoodPaths; verbose?: true }): Promise -export function runFullCodegen(preset: string, config: unknown): SDLCodeGenReturn +export async function runFullCodegen(preset: string, config: unknown): Promise -export function runFullCodegen(preset: string, config: unknown): SDLCodeGenReturn { +export async function runFullCodegen(preset: string, config: unknown): Promise { if (preset !== "redwood") throw new Error("Only Redwood codegen is supported at this time") const verbose = (config as { verbose?: true }).verbose const startTime = Date.now() @@ -83,22 +83,22 @@ export function runFullCodegen(preset: string, config: unknown): SDLCodeGenRetur const filepaths = [] as string[] // Create the two shared schema files - const sharedDTSes = createSharedSchemaFiles(appContext) + const sharedDTSes = await createSharedSchemaFiles(appContext) filepaths.push(...sharedDTSes) let knownServiceFiles: string[] = [] - const createDTSFilesForAllServices = () => { + const createDTSFilesForAllServices = async () => { // TODO: Maybe Redwood has an API for this? Its grabbing all the services const serviceFiles = appContext.sys.readDirectory(appContext.pathSettings.apiServicesPath) knownServiceFiles = serviceFiles.filter(isRedwoodServiceFile) for (const path of knownServiceFiles) { - const dts = lookAtServiceFile(path, appContext) + const dts = await lookAtServiceFile(path, appContext) if (dts) filepaths.push(dts) } } // Initial run - createDTSFilesForAllServices() + await createDTSFilesForAllServices() const endTime = Date.now() const timeTaken = endTime - startTime @@ -106,23 +106,23 @@ export function runFullCodegen(preset: string, config: unknown): SDLCodeGenRetur const createWatcher = () => { return { - fileChanged: (path: string) => { + fileChanged: async (path: string) => { if (path === appContext.pathSettings.graphQLSchemaPath) { if (verbose) console.log("[sdl-codegen] SDL Schema changed") getGraphQLSDLFromFile(appContext.pathSettings) - createSharedSchemaFiles(appContext) - createDTSFilesForAllServices() + await createSharedSchemaFiles(appContext) + await createDTSFilesForAllServices() } else if (path === appContext.pathSettings.prismaDSLPath) { if (verbose) console.log("[sdl-codegen] Prisma schema changed") getPrismaSchemaFromFile(appContext.pathSettings) - createDTSFilesForAllServices() + await createDTSFilesForAllServices() } else if (isRedwoodServiceFile(path)) { if (knownServiceFiles.includes(path)) { if (verbose) console.log("[sdl-codegen] New service file") - createDTSFilesForAllServices() + await createDTSFilesForAllServices() } else { if (verbose) console.log("[sdl-codegen] Service file changed") - lookAtServiceFile(path, appContext) + await lookAtServiceFile(path, appContext) } } }, diff --git a/src/serviceFile.ts b/src/serviceFile.ts index a104666..f3718ae 100644 --- a/src/serviceFile.ts +++ b/src/serviceFile.ts @@ -3,13 +3,13 @@ import * as graphql from "graphql" import { AppContext } from "./context.js" -import { formatDTS, getPrettierConfig } from "./formatDTS.js" +import { formatDTS } from "./formatDTS.js" import { getCodeFactsForJSTSFileAtPath } from "./serviceFile.codefacts.js" import { CodeFacts, ModelResolverFacts, ResolverFuncFact } from "./typeFacts.js" import { TypeMapper, typeMapper } from "./typeMap.js" import { capitalizeFirstLetter, createAndReferOrInlineArgsForField, inlineArgsForField } from "./utils.js" -export const lookAtServiceFile = (file: string, context: AppContext) => { +export const lookAtServiceFile = async (file: string, context: AppContext) => { const { gql, prisma, pathSettings: settings, codeFacts: serviceFacts, fieldFacts } = context if (!gql) throw new Error(`No schema when wanting to look at service file: ${file}`) @@ -153,8 +153,7 @@ export const lookAtServiceFile = (file: string, context: AppContext) => { const shouldWriteDTS = !!dts.trim().length if (!shouldWriteDTS) return - const config = getPrettierConfig(dtsFilepath) - const formatted = formatDTS(dtsFilepath, dts, config) + const formatted = await formatDTS(dtsFilepath, dts) // Don't make a file write if the content is the same const priorContent = context.sys.readFile(dtsFilename) diff --git a/src/sharedSchema.ts b/src/sharedSchema.ts index 355ac65..1821a5a 100644 --- a/src/sharedSchema.ts +++ b/src/sharedSchema.ts @@ -4,12 +4,12 @@ import * as graphql from "graphql" import * as tsMorph from "ts-morph" import { AppContext } from "./context.js" -import { formatDTS, getPrettierConfig } from "./formatDTS.js" +import { formatDTS } from "./formatDTS.js" import { typeMapper } from "./typeMap.js" -export const createSharedSchemaFiles = (context: AppContext) => { - createSharedExternalSchemaFile(context) - createSharedReturnPositionSchemaFile(context) +export const createSharedSchemaFiles = async (context: AppContext) => { + await createSharedExternalSchemaFile(context) + await createSharedReturnPositionSchemaFile(context) return [ context.join(context.pathSettings.typesFolderRoot, context.pathSettings.sharedFilename), @@ -17,7 +17,7 @@ export const createSharedSchemaFiles = (context: AppContext) => { ] } -function createSharedExternalSchemaFile(context: AppContext) { +async function createSharedExternalSchemaFile(context: AppContext) { const gql = context.gql const types = gql.getTypeMap() const knownPrimitives = ["String", "Boolean", "Int"] @@ -123,14 +123,13 @@ function createSharedExternalSchemaFile(context: AppContext) { } const fullPath = context.join(context.pathSettings.typesFolderRoot, context.pathSettings.sharedFilename) - const config = getPrettierConfig(fullPath) - const formatted = formatDTS(fullPath, externalTSFile.getText(), config) + const formatted = await formatDTS(fullPath, externalTSFile.getText()) const prior = context.sys.readFile(fullPath) if (prior !== formatted) context.sys.writeFile(fullPath, formatted) } -function createSharedReturnPositionSchemaFile(context: AppContext) { +async function createSharedReturnPositionSchemaFile(context: AppContext) { const { gql, prisma, fieldFacts } = context const types = gql.getTypeMap() const mapper = typeMapper(context, { preferPrismaModels: true }) @@ -254,8 +253,7 @@ function createSharedReturnPositionSchemaFile(context: AppContext) { } const fullPath = context.join(context.pathSettings.typesFolderRoot, context.pathSettings.sharedInternalFilename) - const config = getPrettierConfig(fullPath) - const formatted = formatDTS(fullPath, externalTSFile.getText(), config) + const formatted = await formatDTS(fullPath, externalTSFile.getText()) const prior = context.sys.readFile(fullPath) if (prior !== formatted) context.sys.writeFile(fullPath, formatted) diff --git a/src/tests/bugs/parentCanBeGraphQLObject.test.ts b/src/tests/bugs/parentCanBeGraphQLObject.test.ts index fa057e0..111d3fd 100644 --- a/src/tests/bugs/parentCanBeGraphQLObject.test.ts +++ b/src/tests/bugs/parentCanBeGraphQLObject.test.ts @@ -2,7 +2,7 @@ import { expect, it } from "vitest" import { getDTSFilesForRun, graphql, prisma } from "../testRunner.js" -it("Uses GraphQL objects when prisma objects are not available for resolver parents", () => { +it("Uses GraphQL objects when prisma objects are not available for resolver parents", async () => { const prismaSchema = prisma` model Game { id Int @id @default(autoincrement()) @@ -27,7 +27,7 @@ export const Puzzle = { }; ` - const { vfsMap } = getDTSFilesForRun({ sdl, gamesService, prismaSchema }) + const { vfsMap } = await getDTSFilesForRun({ sdl, gamesService, prismaSchema }) const dts = vfsMap.get("/types/games.d.ts")! expect(dts.trim()).toMatchInlineSnapshot(` "import type { Puzzle as SPuzzle } from \\"./shared-return-types\\"; diff --git a/src/tests/bugs/returnObjectCanBeGraphQLInterfaces.test.ts b/src/tests/bugs/returnObjectCanBeGraphQLInterfaces.test.ts index 26cedb5..f706905 100644 --- a/src/tests/bugs/returnObjectCanBeGraphQLInterfaces.test.ts +++ b/src/tests/bugs/returnObjectCanBeGraphQLInterfaces.test.ts @@ -2,7 +2,7 @@ import { expect, it } from "vitest" import { getDTSFilesForRun, graphql, prisma } from "../testRunner.js" -it("The retunr type can be a graphql interface", () => { +it("The retunr type can be a graphql interface", async () => { const prismaSchema = prisma` model Game { id Int @id @default(autoincrement()) @@ -28,7 +28,7 @@ export const Game = { }; ` - const { vfsMap } = getDTSFilesForRun({ sdl, gamesService, prismaSchema }) + const { vfsMap } = await getDTSFilesForRun({ sdl, gamesService, prismaSchema }) const dts = vfsMap.get("/types/games.d.ts")! expect(dts.trim()).toMatchInlineSnapshot(` "import type { Game as PGame } from \\"@prisma/client\\"; diff --git a/src/tests/features/generatesTypesForUnions.test.ts b/src/tests/features/generatesTypesForUnions.test.ts index 04fd95a..6125ea5 100644 --- a/src/tests/features/generatesTypesForUnions.test.ts +++ b/src/tests/features/generatesTypesForUnions.test.ts @@ -2,7 +2,7 @@ import { expect, it } from "vitest" import { getDTSFilesForRun, graphql, prisma } from "../testRunner.js" -it("generates a union type for a gql union", () => { +it("generates a union type for a gql union", async () => { const prismaSchema = prisma` model Game { id Int @id @default(autoincrement()) @@ -35,7 +35,7 @@ export const Game = { }; ` - const { vfsMap } = getDTSFilesForRun({ sdl, gamesService, prismaSchema, generateShared: true }) + const { vfsMap } = await getDTSFilesForRun({ sdl, gamesService, prismaSchema, generateShared: true }) const dts = vfsMap.get("/types/shared-schema-types.d.ts")! expect(dts.trim()).toMatchInlineSnapshot(` "export interface Game { diff --git a/src/tests/features/preferPromiseFnWhenKnown.test.ts b/src/tests/features/preferPromiseFnWhenKnown.test.ts index 69790af..3484f6f 100644 --- a/src/tests/features/preferPromiseFnWhenKnown.test.ts +++ b/src/tests/features/preferPromiseFnWhenKnown.test.ts @@ -2,7 +2,7 @@ import { expect, it } from "vitest" import { getDTSFilesForRun, graphql, prisma } from "../testRunner.js" -it("uses a rn to promise when we see an async tag", () => { +it("uses a rn to promise when we see an async tag", async () => { const prismaSchema = prisma` model Game { id Int @id @default(autoincrement()) @@ -51,7 +51,7 @@ export const Game = { }; ` - const { vfsMap } = getDTSFilesForRun({ sdl, gamesService, prismaSchema }) + const { vfsMap } = await getDTSFilesForRun({ sdl, gamesService, prismaSchema }) const dts = vfsMap.get("/types/games.d.ts")! expect(dts.trim()).toMatchInlineSnapshot(` "import type { Game as PGame } from \\"@prisma/client\\"; diff --git a/src/tests/features/returnTypePositionsWhichPreferPrisma.test.ts b/src/tests/features/returnTypePositionsWhichPreferPrisma.test.ts index 6e7d4f6..08039ab 100644 --- a/src/tests/features/returnTypePositionsWhichPreferPrisma.test.ts +++ b/src/tests/features/returnTypePositionsWhichPreferPrisma.test.ts @@ -2,7 +2,7 @@ import { expect, it } from "vitest" import { getDTSFilesForRun, graphql, prisma } from "../testRunner.js" -it("supports a return position where a prisma object can be given, if the extra fn are defined as resolvers", () => { +it("supports a return position where a prisma object can be given, if the extra fn are defined as resolvers", async () => { const prismaSchema = prisma` model Game { id Int @id @default(autoincrement()) @@ -36,7 +36,7 @@ export const Game = { }; ` - const { vfsMap } = getDTSFilesForRun({ sdl, gamesService: services, prismaSchema }) + const { vfsMap } = await getDTSFilesForRun({ sdl, gamesService: services, prismaSchema }) const dts = vfsMap.get("/types/games.d.ts")! expect(dts.trimStart()).toMatchInlineSnapshot( diff --git a/src/tests/features/supportGenericExtension.test.ts b/src/tests/features/supportGenericExtension.test.ts index 0c113d0..c8018a0 100644 --- a/src/tests/features/supportGenericExtension.test.ts +++ b/src/tests/features/supportGenericExtension.test.ts @@ -2,7 +2,7 @@ import { expect, it } from "vitest" import { getDTSFilesForRun, graphql, prisma } from "../testRunner.js" -it("It allows you to add a generic parameter", () => { +it("It allows you to add a generic parameter", async () => { const prismaSchema = prisma` model Game { id Int @id @default(autoincrement()) @@ -25,7 +25,7 @@ import { db } from "src/lib/db"; export const Game: GameResolvers<{ type: string }> = {}; ` - const { vfsMap } = getDTSFilesForRun({ sdl, gamesService: services, prismaSchema }) + const { vfsMap } = await getDTSFilesForRun({ sdl, gamesService: services, prismaSchema }) expect(vfsMap.get("/types/games.d.ts")!).toContain("interface GameTypeResolvers") diff --git a/src/tests/features/supportRefferingToEnumsOnlyInSDL.test.ts b/src/tests/features/supportRefferingToEnumsOnlyInSDL.test.ts index de5324b..54dcdb9 100644 --- a/src/tests/features/supportRefferingToEnumsOnlyInSDL.test.ts +++ b/src/tests/features/supportRefferingToEnumsOnlyInSDL.test.ts @@ -2,7 +2,7 @@ import { expect, it } from "vitest" import { getDTSFilesForRun, graphql, prisma } from "../testRunner.js" -it("It adds a reference to the graphql enums you use", () => { +it("It adds a reference to the graphql enums you use", async () => { const prismaSchema = prisma` model Game { id Int @id @default(autoincrement()) @@ -33,7 +33,7 @@ export const allGames = () => {} export const Game: GameResolvers = {}; ` - const { vfsMap } = getDTSFilesForRun({ sdl, gamesService: services, prismaSchema, generateShared: true }) + const { vfsMap } = await getDTSFilesForRun({ sdl, gamesService: services, prismaSchema, generateShared: true }) // We are expecting to see import type GameType from "./shared-schema-types" diff --git a/src/tests/features/warnOnSuperfluousResolvers.test.ts b/src/tests/features/warnOnSuperfluousResolvers.test.ts index 4e2f155..6b7610e 100644 --- a/src/tests/features/warnOnSuperfluousResolvers.test.ts +++ b/src/tests/features/warnOnSuperfluousResolvers.test.ts @@ -2,7 +2,7 @@ import { expect, it } from "vitest" import { getDTSFilesForRun, graphql, prisma } from "../testRunner.js" -it("It prints a warning, and doesn't crash when you have resolvers which exist but are not on the parent", () => { +it("It prints a warning, and doesn't crash when you have resolvers which exist but are not on the parent", async () => { const prismaSchema = prisma` model Game { id Int @id @default(autoincrement()) @@ -28,7 +28,7 @@ export const Game: GameResolvers = { ` - const { vfsMap } = getDTSFilesForRun({ sdl, gamesService: services, prismaSchema }) + const { vfsMap } = await getDTSFilesForRun({ sdl, gamesService: services, prismaSchema }) expect(vfsMap.get("/types/games.d.ts")!).toContain("// This field does not exist in the generated schema.graphql\n") }) diff --git a/src/tests/serviceFile.test.ts b/src/tests/serviceFile.test.ts index 9feaafe..a21ed8f 100644 --- a/src/tests/serviceFile.test.ts +++ b/src/tests/serviceFile.test.ts @@ -5,8 +5,8 @@ import { getCodeFactsForJSTSFileAtPath } from "../serviceFile.codefacts.js" import { lookAtServiceFile } from "../serviceFile.js" import { getDTSFilesForRun } from "./testRunner.js" -it("reads a service file", () => { - const { appContext, vfsMap } = getDTSFilesForRun({}) +it("reads a service file", async () => { + const { appContext, vfsMap } = await getDTSFilesForRun({}) vfsMap.set( "/api/src/services/example.ts", @@ -17,13 +17,13 @@ export function game2() {} ) expect(vfsMap.has("/types/example.d.ts")).toBeFalsy() - lookAtServiceFile("/api/src/services/example.ts", appContext) + await lookAtServiceFile("/api/src/services/example.ts", appContext) // this isn't really very useful as a test, but it proves it doesn't crash? }) -it("generates useful service facts from a (truncated) real file", () => { - const { appContext, vfsMap } = getDTSFilesForRun({}) +it("generates useful service facts from a (truncated) real file", async () => { + const { appContext, vfsMap } = await getDTSFilesForRun({}) vfsMap.set("/api/src/services/userProfile.ts", readFileSync("./src/tests/vendor/puzzmo/one-offs/userProfiles.ts", "utf8")) diff --git a/src/tests/testRunner.ts b/src/tests/testRunner.ts index 050eee0..c969c35 100644 --- a/src/tests/testRunner.ts +++ b/src/tests/testRunner.ts @@ -17,7 +17,7 @@ interface Run { sdl?: string } -export function getDTSFilesForRun(run: Run) { +export async function getDTSFilesForRun(run: Run) { const prisma = getPrismaSchema(run.prismaSchema ?? "") let gqlSDL = run.sdl ?? "" if (!gqlSDL.includes("type Query")) gqlSDL += "type Query { _: String }\n" @@ -52,11 +52,11 @@ export function getDTSFilesForRun(run: Run) { if (run.gamesService) { vfsMap.set("/api/src/services/games.ts", run.gamesService) - lookAtServiceFile("/api/src/services/games.ts", appContext) + await lookAtServiceFile("/api/src/services/games.ts", appContext) } if (run.generateShared) { - createSharedSchemaFiles(appContext) + await createSharedSchemaFiles(appContext) } return { From b1c8c53e6eda023924d758b63913b750939cba1d Mon Sep 17 00:00:00 2001 From: orta Date: Thu, 5 Sep 2024 11:27:00 +0100 Subject: [PATCH 2/5] Issue tempaltes --- .github/ISSUE_TEMPLATE/01-bug.yml | 33 --------------------- .github/ISSUE_TEMPLATE/02-documentation.yml | 25 ---------------- .github/ISSUE_TEMPLATE/03-feature.yml | 27 ----------------- .github/ISSUE_TEMPLATE/04-tooling.yml | 27 ----------------- 4 files changed, 112 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/01-bug.yml delete mode 100644 .github/ISSUE_TEMPLATE/02-documentation.yml delete mode 100644 .github/ISSUE_TEMPLATE/03-feature.yml delete mode 100644 .github/ISSUE_TEMPLATE/04-tooling.yml diff --git a/.github/ISSUE_TEMPLATE/01-bug.yml b/.github/ISSUE_TEMPLATE/01-bug.yml deleted file mode 100644 index b5e5336..0000000 --- a/.github/ISSUE_TEMPLATE/01-bug.yml +++ /dev/null @@ -1,33 +0,0 @@ -body: - - attributes: - description: If any of these required steps are not taken, we may not be able to review your issue. Help us to help you! - label: Bug Report Checklist - options: - - label: I have tried restarting my IDE and the issue persists. - required: true - - label: I have pulled the latest `main` branch of the repository. - required: true - - label: I have [searched for related issues](https://github.com/sdl-codegen/sdl-codegen/issues?q=is%3Aissue) and found none that matched my issue. - required: true - type: checkboxes - - attributes: - description: What did you expect to happen? - label: Expected - type: textarea - validations: - required: true - - attributes: - description: What happened instead? - label: Actual - type: textarea - validations: - required: true - - attributes: - description: Any additional info you'd like to provide. - label: Additional Info - type: textarea -description: Report a bug trying to run the code -labels: - - "type: bug" -name: 🐛 Report a Bug -title: "🐛 Bug: " diff --git a/.github/ISSUE_TEMPLATE/02-documentation.yml b/.github/ISSUE_TEMPLATE/02-documentation.yml deleted file mode 100644 index d792e33..0000000 --- a/.github/ISSUE_TEMPLATE/02-documentation.yml +++ /dev/null @@ -1,25 +0,0 @@ -body: - - attributes: - description: If any of these required steps are not taken, we may not be able to review your issue. Help us to help you! - label: Bug Report Checklist - options: - - label: I have pulled the latest `main` branch of the repository. - required: true - - label: I have [searched for related issues](https://github.com/sdl-codegen/sdl-codegen/issues?q=is%3Aissue) and found none that matched my issue. - required: true - type: checkboxes - - attributes: - description: What would you like to report? - label: Overview - type: textarea - validations: - required: true - - attributes: - description: Any additional info you'd like to provide. - label: Additional Info - type: textarea -description: Report a typo or missing area of documentation -labels: - - "area: documentation" -name: 📝 Documentation -title: "📝 Documentation: " diff --git a/.github/ISSUE_TEMPLATE/03-feature.yml b/.github/ISSUE_TEMPLATE/03-feature.yml deleted file mode 100644 index 7ec4f7a..0000000 --- a/.github/ISSUE_TEMPLATE/03-feature.yml +++ /dev/null @@ -1,27 +0,0 @@ -body: - - attributes: - description: If any of these required steps are not taken, we may not be able to review your issue. Help us to help you! - label: Bug Report Checklist - options: - - label: I have tried restarting my IDE and the issue persists. - required: true - - label: I have pulled the latest `main` branch of the repository. - required: true - - label: I have [searched for related issues](https://github.com/sdl-codegen/sdl-codegen/issues?q=is%3Aissue) and found none that matched my issue. - required: true - type: checkboxes - - attributes: - description: What did you expect to be able to do? - label: Overview - type: textarea - validations: - required: true - - attributes: - description: Any additional info you'd like to provide. - label: Additional Info - type: textarea -description: Request that a new feature be added or an existing feature improved -labels: - - "type: feature" -name: 🚀 Request a Feature -title: "🚀 Feature: " diff --git a/.github/ISSUE_TEMPLATE/04-tooling.yml b/.github/ISSUE_TEMPLATE/04-tooling.yml deleted file mode 100644 index d7dc7a6..0000000 --- a/.github/ISSUE_TEMPLATE/04-tooling.yml +++ /dev/null @@ -1,27 +0,0 @@ -body: - - attributes: - description: If any of these required steps are not taken, we may not be able to review your issue. Help us to help you! - label: Bug Report Checklist - options: - - label: I have tried restarting my IDE and the issue persists. - required: true - - label: I have pulled the latest `main` branch of the repository. - required: true - - label: I have [searched for related issues](https://github.com/sdl-codegen/sdl-codegen/issues?q=is%3Aissue) and found none that matched my issue. - required: true - type: checkboxes - - attributes: - description: What did you expect to be able to do? - label: Overview - type: textarea - validations: - required: true - - attributes: - description: Any additional info you'd like to provide. - label: Additional Info - type: textarea -description: Report a bug or request an enhancement in repository tooling -labels: - - "area: tooling" -name: 🛠 Tooling -title: "🛠 Tooling: " From f79b2d9059906932c1e1930eef6a08bd659b6be6 Mon Sep 17 00:00:00 2001 From: orta Date: Thu, 5 Sep 2024 14:38:42 +0100 Subject: [PATCH 3/5] Drop unused files, pass linter --- src/index.ts | 1 - src/main.ts | 3 -- src/prismaModeller.ts | 2 +- src/run.ts | 116 ------------------------------------------ src/types.ts | 2 +- 5 files changed, 2 insertions(+), 122 deletions(-) delete mode 100644 src/main.ts delete mode 100644 src/run.ts diff --git a/src/index.ts b/src/index.ts index 4afd20f..d74db2d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,7 +10,6 @@ import { createSharedSchemaFiles } from "./sharedSchema.js" import { CodeFacts, FieldFacts } from "./typeFacts.js" import { RedwoodPaths } from "./types.js" -export * from "./main.js" export * from "./types.js" import { basename, join } from "node:path" diff --git a/src/main.ts b/src/main.ts deleted file mode 100644 index 9cb72a4..0000000 --- a/src/main.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const run = () => { - console.log("Hello, world!") -} diff --git a/src/prismaModeller.ts b/src/prismaModeller.ts index 6b896e3..28843ae 100644 --- a/src/prismaModeller.ts +++ b/src/prismaModeller.ts @@ -39,7 +39,7 @@ export const prismaModeller = (schema: PrismaSchemaBlocks) => { leadingFieldComments.push(p.text.replace("/// ", "").replace("// ", "")) } else if (p.type === "break") { leadingFieldComments.push("") - } else if (p.type === "attribute" || p.type === "field") { + } else { properties.set(p.name, { leadingComments: leadingFieldComments.join("\n"), property: p, diff --git a/src/run.ts b/src/run.ts deleted file mode 100644 index 7256cdb..0000000 --- a/src/run.ts +++ /dev/null @@ -1,116 +0,0 @@ -// TODO: Remove? -import { basename, join } from "node:path" - -import { getSchema as getPrismaSchema } from "@mrleebo/prisma-ast" -import * as graphql from "graphql" -import { Project } from "ts-morph" -import typescript from "typescript" - -import { AppContext } from "./context.js" -import { PrismaMap, prismaModeller } from "./prismaModeller.js" -import { lookAtServiceFile } from "./serviceFile.js" -import { createSharedSchemaFiles } from "./sharedSchema.js" -import { CodeFacts, FieldFacts } from "./typeFacts.js" - -export function run( - appRoot: string, - typesRoot: string, - config: { deleteOldGraphQLDTS?: boolean; runESLint?: boolean; sys?: typescript.System } = {} -) { - const sys = config.sys ?? typescript.sys - const project = new Project({ useInMemoryFileSystem: true }) - - let gqlSchema: graphql.GraphQLSchema | undefined - const getGraphQLSDLFromFile = (settings: AppContext["pathSettings"]) => { - const schema = sys.readFile(settings.graphQLSchemaPath) - if (!schema) throw new Error("No schema found at " + settings.graphQLSchemaPath) - gqlSchema = graphql.buildSchema(schema) - } - - let prismaSchema: PrismaMap = new Map() - const getPrismaSchemaFromFile = (settings: AppContext["pathSettings"]) => { - const prismaSchemaText = sys.readFile(settings.prismaDSLPath) - if (!prismaSchemaText) throw new Error("No prisma file found at " + settings.prismaDSLPath) - const prismaSchemaBlocks = getPrismaSchema(prismaSchemaText) - prismaSchema = prismaModeller(prismaSchemaBlocks) - } - - const settings: AppContext["pathSettings"] = { - root: appRoot, - graphQLSchemaPath: join(appRoot, ".redwood", "schema.graphql"), - apiServicesPath: join(appRoot, "api", "src", "services"), - prismaDSLPath: join(appRoot, "api", "db", "schema.prisma"), - sharedFilename: "shared-schema-types.d.ts", - sharedInternalFilename: "shared-return-types.d.ts", - typesFolderRoot: typesRoot, - } - - getGraphQLSDLFromFile(settings) - getPrismaSchemaFromFile(settings) - - if (!gqlSchema) throw new Error("No GraphQL Schema was created during setup") - - const appContext: AppContext = { - gql: gqlSchema, - prisma: prismaSchema, - tsProject: project, - codeFacts: new Map(), - fieldFacts: new Map(), - pathSettings: settings, - sys, - join, - basename, - } - - const serviceFilesToLookAt = [] as string[] - for (const dirEntry of sys.readDirectory(appContext.pathSettings.apiServicesPath)) { - // These are generally the folders - if (sys.directoryExists(dirEntry)) { - const folderPath = join(appContext.pathSettings.apiServicesPath, dirEntry) - // And these are the files in them - for (const subdirEntry of sys.readDirectory(folderPath)) { - const folderPath = join(appContext.pathSettings.apiServicesPath, dirEntry) - if ( - sys.fileExists(folderPath) && - subdirEntry.endsWith(".ts") && - !subdirEntry.includes(".test.ts") && - !subdirEntry.includes("scenarios.ts") - ) { - serviceFilesToLookAt.push(join(folderPath, subdirEntry)) - } - } - } - } - - // empty the types folder - for (const dirEntry of sys.readDirectory(appContext.pathSettings.typesFolderRoot)) { - const fileToDelete = join(appContext.pathSettings.typesFolderRoot, dirEntry) - if (sys.deleteFile && sys.fileExists(fileToDelete)) { - sys.deleteFile(fileToDelete) - } - } - - // This needs to go first, as it sets up fieldFacts - for (const path of serviceFilesToLookAt) { - lookAtServiceFile(path, appContext) - } - - createSharedSchemaFiles(appContext) - // console.log(`Updated`, typesRoot) - - if (config.runESLint) { - // console.log("Running ESLint...") - // const process = Deno.run({ - // cwd: appRoot, - // cmd: ["yarn", "eslint", "--fix", "--ext", ".d.ts", appContext.settings.typesFolderRoot], - // stdin: "inherit", - // stdout: "inherit", - // }) - // await process.status() - } - - if (sys.deleteFile && config.deleteOldGraphQLDTS) { - console.log("Deleting old graphql.d.ts") - sys.deleteFile(join(appRoot, "api", "src", "graphql.d.ts")) - } -} diff --git a/src/types.ts b/src/types.ts index 9e429d7..7a46522 100644 --- a/src/types.ts +++ b/src/types.ts @@ -41,5 +41,5 @@ export interface RedwoodPaths { // } } scripts: string - web: any + web: object } From dc8f925b5f638b547fdaeb6a73b3edc491785c28 Mon Sep 17 00:00:00 2001 From: orta Date: Thu, 5 Sep 2024 14:50:15 +0100 Subject: [PATCH 4/5] Timing info --- CHANGELOG.md | 3 ++- src/index.ts | 26 ++++++++++++++++++-------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d05a0fb..e2cc9e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,8 @@ ### 2.0.0 -Redwood uses prettier 3, and prettier 3 removes the sync API. This means we now have to operate entirely async. This is a breaking change from the sdl-codegen API, as you need to await the exposed public fns. +- Redwood uses prettier 3, and prettier 3 removes the sync API. This means we now have to operate entirely async. This is a breaking change from the sdl-codegen API, as you need to await the exposed public fns. +- There is a verbose option which provides info on the timings of the codegen. ### 1.1.2 diff --git a/src/index.ts b/src/index.ts index d74db2d..028377b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -28,8 +28,9 @@ export async function runFullCodegen(preset: string, config: unknown): Promise { if (preset !== "redwood") throw new Error("Only Redwood codegen is supported at this time") - const verbose = (config as { verbose?: true }).verbose + const verbose = !!(config as { verbose?: true }).verbose const startTime = Date.now() + const step = makeStep(verbose) const paths = (config as { paths: RedwoodPaths }).paths const sys = typescript.sys @@ -61,8 +62,8 @@ export async function runFullCodegen(preset: string, config: unknown): Promise getGraphQLSDLFromFile(pathSettings)) + await step("Read the Prisma schema", () => getPrismaSchemaFromFile(pathSettings)) if (!gqlSchema) throw new Error("No GraphQL Schema was created during setup") @@ -82,8 +83,10 @@ export async function runFullCodegen(preset: string, config: unknown): Promise { + const sharedDTSes = await createSharedSchemaFiles(appContext) + filepaths.push(...sharedDTSes) + }) let knownServiceFiles: string[] = [] const createDTSFilesForAllServices = async () => { @@ -97,10 +100,10 @@ export async function runFullCodegen(preset: string, config: unknown): Promise { @@ -116,7 +119,7 @@ export async function runFullCodegen(preset: string, config: unknown): Promise { if (file.endsWith("scenarios.ts") || file.endsWith("scenarios.js")) return false return file.endsWith(".ts") || file.endsWith(".tsx") || file.endsWith(".js") } + +const makeStep = (verbose: boolean) => async (msg: string, fn: () => Promise | void) => { + if (!verbose) return fn() + console.time(msg) + await fn() + console.timeEnd(msg) +} From 56c6a3cb6ac3b3f71277ced10f579696f95e9a30 Mon Sep 17 00:00:00 2001 From: orta Date: Thu, 5 Sep 2024 17:08:25 +0100 Subject: [PATCH 5/5] Also throw in the watcher improvements --- CHANGELOG.md | 1 + package.json | 1 + src/index.ts | 38 +++++++++++++++++++++++--------------- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e2cc9e5..6f5d087 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Redwood uses prettier 3, and prettier 3 removes the sync API. This means we now have to operate entirely async. This is a breaking change from the sdl-codegen API, as you need to await the exposed public fns. - There is a verbose option which provides info on the timings of the codegen. +- Big watch mode improvements ### 1.1.2 diff --git a/package.json b/package.json index 0a62a84..7570127 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ ], "scripts": { "build": "tsc", + "build:watch": "tsc --watch", "format": "prettier \"**/*\" --ignore-unknown", "format:write": "pnpm format --write", "jest": "vitest", diff --git a/src/index.ts b/src/index.ts index 028377b..4d618f4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -14,9 +14,9 @@ export * from "./types.js" import { basename, join } from "node:path" -interface SDLCodeGenReturn { +export interface SDLCodeGenReturn { // Optional way to start up a watcher mode for the codegen - createWatcher: () => { fileChanged: (path: string) => void } + createWatcher: () => { fileChanged: (path: string) => Promise } // Paths which were added/changed during the run paths: string[] } @@ -107,24 +107,27 @@ export async function runFullCodegen(preset: string, config: unknown): Promise { + const oldSDL = "" + return { fileChanged: async (path: string) => { + if (isTypesFile(path)) return if (path === appContext.pathSettings.graphQLSchemaPath) { + const newSDL = appContext.sys.readFile(path) + if (newSDL === oldSDL) return + if (verbose) console.log("[sdl-codegen] SDL Schema changed") - getGraphQLSDLFromFile(appContext.pathSettings) - await createSharedSchemaFiles(appContext) - await createDTSFilesForAllServices() + await step("GraphQL schema changed", () => getGraphQLSDLFromFile(appContext.pathSettings)) + await step("Create all shared schema files", () => createSharedSchemaFiles(appContext)) + await step("Create all service files", createDTSFilesForAllServices) } else if (path === appContext.pathSettings.prismaDSLPath) { - if (verbose) console.log("[sdl-codegen] Prisma schema changed") - getPrismaSchemaFromFile(appContext.pathSettings) - await createDTSFilesForAllServices() + await step("Prisma schema changed", () => getPrismaSchemaFromFile(appContext.pathSettings)) + await step("Create all shared schema files", createDTSFilesForAllServices) } else if (isRedwoodServiceFile(path)) { if (!knownServiceFiles.includes(path)) { - if (verbose) console.log("[sdl-codegen] New service file") - await createDTSFilesForAllServices() + await step("Create all shared schema files", createDTSFilesForAllServices) } else { - if (verbose) console.log("[sdl-codegen] Service file changed") - await lookAtServiceFile(path, appContext) + await step("Create known service files", () => lookAtServiceFile(path, appContext)) } } }, @@ -137,15 +140,20 @@ export async function runFullCodegen(preset: string, config: unknown): Promise file.endsWith(".d.ts") + const isRedwoodServiceFile = (file: string) => { + if (!file.includes("services")) return false + if (file.endsWith(".d.ts")) return false if (file.endsWith(".test.ts") || file.endsWith(".test.js")) return false if (file.endsWith("scenarios.ts") || file.endsWith("scenarios.js")) return false return file.endsWith(".ts") || file.endsWith(".tsx") || file.endsWith(".js") } -const makeStep = (verbose: boolean) => async (msg: string, fn: () => Promise | void) => { +const makeStep = (verbose: boolean) => async (msg: string, fn: () => Promise | Promise | void) => { if (!verbose) return fn() - console.time(msg) + console.log("[sdl-codegen] " + msg) + console.time("[sdl-codegen] " + msg) await fn() - console.timeEnd(msg) + console.timeEnd("[sdl-codegen] " + msg) }