Skip to content

Commit

Permalink
fix(generator): use dprint if available (#1221)
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonkuhrt authored Oct 25, 2024
1 parent 718f7c3 commit 5b91cf0
Show file tree
Hide file tree
Showing 12 changed files with 300 additions and 284 deletions.
2 changes: 1 addition & 1 deletion dprint.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"**/*-lock.json"
],
"plugins": [
"https://plugins.dprint.dev/typescript-0.89.1.wasm",
"https://plugins.dprint.dev/typescript-0.93.0.wasm",
"https://plugins.dprint.dev/json-0.19.1.wasm",
"https://plugins.dprint.dev/markdown-0.16.3.wasm"
]
Expand Down
17 changes: 9 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@
"clean": "tsc --build --clean && rm -rf build",
"test:unit": "vitest --exclude tests/examples --exclude tests/e2e",
"test:examples": "vitest --config vitest.examples.config.ts --dir tests/examples",
"test:e2e": "vitest --dir tests/e2e",
"test:e2e": "vitest --dir tests/e2e --testTimeout 10000",
"test": "vitest",
"test:web": "vitest --environment jsdom",
"test:types": "vitest --typecheck --dir src --testNamePattern .*.test-d.ts",
Expand All @@ -129,10 +129,9 @@
"is-plain-obj": "^4.1.0"
},
"peerDependencies": {
"@dprint/formatter": "^0.3.0 || ^0.4.0",
"@dprint/typescript": "^0.91.1 || ^0.92.0 || ^0.93.0",
"@dprint/formatter": "^0.4.0",
"@dprint/typescript": "^0.93.0",
"@opentelemetry/api": "^1.9.0",
"dprint": "^0.46.2 || ^0.47.0",
"graphql": "14 - 16"
},
"peerDependenciesMeta": {
Expand All @@ -151,7 +150,9 @@
},
"devDependencies": {
"@arethetypeswrong/cli": "^0.16.4",
"@ark/attest": "^0.23.0",
"@ark/attest": "^0.24.0",
"@dprint/formatter": "^0.4.1",
"@dprint/typescript": "^0.93.0",
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/sdk-trace-base": "^1.27.0",
"@opentelemetry/sdk-trace-node": "^1.27.0",
Expand All @@ -162,13 +163,13 @@
"@tsconfig/strictest": "^2.0.5",
"@types/body-parser": "^1.19.5",
"@types/express": "^5.0.0",
"@types/node": "^22.7.9",
"@types/node": "^22.8.0",
"@typescript-eslint/eslint-plugin": "^8.11.0",
"@typescript-eslint/parser": "^8.11.0",
"async-cleanup": "^1.0.0",
"doctoc": "^2.2.1",
"dripip": "^0.10.0",
"es-toolkit": "^1.25.2",
"es-toolkit": "^1.26.1",
"eslint": "^9.13.0",
"eslint-config-prisma": "^0.6.0",
"eslint-plugin-deprecation": "^3.0.0",
Expand All @@ -187,7 +188,7 @@
"graphql-upload-minimal": "^1.6.1",
"graphql-yoga": "^5.7.0",
"jsdom": "^25.0.1",
"publint": "^0.2.11",
"publint": "^0.2.12",
"strip-ansi": "^7.1.0",
"tsx": "^4.19.1",
"type-fest": "^4.26.1",
Expand Down
351 changes: 139 additions & 212 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/generator/cli/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { Command } from '@molt/command'
import * as Path from 'node:path'
import { z } from 'zod'
import { toAbsolutePath } from '../../lib/fs.js'
import { toAbsolutePath } from '../../lib/fsp.js'
import { isError, urlParseSafe } from '../../lib/prelude.js'
import { Generator } from '../__.js'

Expand Down
30 changes: 23 additions & 7 deletions src/generator/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,10 @@ import * as Path from 'node:path'
import { Graffle } from '../../entrypoints/__Graffle.js'
import { Introspection } from '../../extensions/Introspection/Introspection.js'
import { ConfigManager } from '../../lib/config-manager/__.js'
import { fileExists, isPathToADirectory, toAbsolutePath, toFilePath } from '../../lib/fs.js'
import { fileExists, isPathToADirectory, toAbsolutePath, toFilePath } from '../../lib/fsp.js'
import { Grafaid } from '../../lib/grafaid/__.js'
import { isString } from '../../lib/prelude.js'
import {
type Formatter,
getTypescriptFormatterOrPassthrough,
passthroughFormatter,
} from '../../lib/typescript-formatter.js'
import { type Formatter, getTypeScriptFormatter, passthroughFormatter } from '../../lib/typescript-formatter.js'
import type { Extension } from '../extension/types.js'
import { defaultLibraryPaths } from './defaults.js'
import { defaultName } from './defaults.js'
Expand Down Expand Up @@ -115,7 +111,27 @@ export const createConfig = async (input: Input): Promise<Config> => {
// --- Formatting ---

const formattingEnabled = input.format ?? true
const formatter = formattingEnabled ? await getTypescriptFormatterOrPassthrough() : passthroughFormatter
let formatter = passthroughFormatter
if (formattingEnabled) {
const formatterReal = await getTypeScriptFormatter()
if (!formatterReal) {
// todo use floggy
console.log(`
WARNING: No TypeScript formatter found. Generated code will remain ugly. To have code automatically formatted do one of the following things:
- pnpm add --save-dev @dprint/formatter @dprint/typescript
- pnpm add --save-dev prettier
To suppress this warning disable formatting in one of the following ways:
- CLI: graffle --no-format
- Configuration file: Generator.configuration({ format: false })
- API: Generator.generate({ format: false })
`.trim())
} else {
formatter = formatterReal
}
}

// --- Library Paths ---

Expand Down
2 changes: 1 addition & 1 deletion src/generator/configFile/loader.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as Path from 'node:path'
import { Errors } from '../../lib/errors/__.js'
import { isPathToADirectory, toAbsolutePath } from '../../lib/fs.js'
import { isPathToADirectory, toAbsolutePath } from '../../lib/fsp.js'
import { importFirst } from '../../lib/import-first.js'
import { isError } from '../../lib/prelude.js'
import { type Builder, isBuilder } from './builder.js'
Expand Down
13 changes: 13 additions & 0 deletions src/lib/fs.ts → src/lib/fsp.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import fs from 'node:fs/promises'
import { extname, isAbsolute, join } from 'node:path'
import type { JsonValue } from 'type-fest'
import { errorFromMaybeError } from './prelude.js'

export const statMaybeExists = async (path: string) => {
Expand Down Expand Up @@ -35,6 +36,18 @@ export const toFilePath = (fileName: string, path: string) => {
}
}

export const readJsonFile = async <$Json extends JsonValue>(path: string): Promise<$Json | null> => {
let content: string

try {
content = await fs.readFile(path, `utf8`)
} catch (error) {
return null
}

return JSON.parse(content) as $Json
}

// export const toFileChecked = async (fileName: string, path: string) => {
// if (isFileLikePath(path)) {
// return path
Expand Down
29 changes: 15 additions & 14 deletions src/lib/typescript-formatter.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import fs from 'node:fs/promises'
import type { JsonObject } from 'type-fest'
import { readJsonFile } from './fsp.js'

export interface Formatter {
formatText(content: string, customFormatterConfig?: object): Promise<string>
Expand All @@ -8,11 +10,6 @@ export const passthroughFormatter: Formatter = {
formatText: (content) => Promise.resolve(content),
}

export const getTypescriptFormatterOrPassthrough = async (): Promise<Formatter> => {
const formatter = await getTypeScriptFormatter()
return formatter ?? passthroughFormatter
}

/**
* Attempt to get a TypeScript formatter using dynamic imports. If none succeed then returns null.
*
Expand All @@ -23,22 +20,26 @@ export const getTypeScriptFormatter = async (): Promise<Formatter | null> => {
const { createFromBuffer } = await import(`@dprint/formatter`)
const { getPath } = await import(`@dprint/typescript`)
const formatter = createFromBuffer(await fs.readFile(getPath()))
const defaultDprintConfig = {
quoteStyle: `preferSingle`,
semiColons: `asi`,
}
return {
formatText: async (content, customFormatterConfig) => {
const config = {
...defaultDprintConfig,
formatText: async (fileText, customFormatterConfig) => {
// todo handle failing to read configuration file gracefully.
// TODO don't read config file manually? https://github.com/dprint/js-formatter/issues/13
const localConfig = await readJsonFile<{ typescript?: JsonObject }>(`dprint.json`) ?? {}
const overrideConfig = {
...localConfig.typescript,
...customFormatterConfig,
}
try {
return formatter.formatText(`memory.ts`, content, config)
const contentFormatted = formatter.formatText({
filePath: `memory.ts`,
fileText,
overrideConfig,
})
return contentFormatted
} catch (error) {
if (process.env[`DEBUG`]) {
const path = `./syntax-error.ts`
await fs.writeFile(path, content)
await fs.writeFile(path, fileText)
console.log(`Wrote contents to ${path} for debugging.`)
}
throw error
Expand Down
30 changes: 28 additions & 2 deletions tests/_/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Graffle } from '../../src/entrypoints/main.js'
import type { ClientContext } from '../../src/entrypoints/utilities-for-generated.js'
import type { Client } from '../../src/layers/6_client/client.js'
import type { ConfigManager } from '../../src/lib/config-manager/__.js'
import { Grafaid } from '../../src/lib/grafaid/__.js'
import { CONTENT_TYPE_REC } from '../../src/lib/grafaid/http/http.js'
import { type SchemaService, serveSchema } from './lib/serveSchema.js'
import { db } from './schemas/db.js'
Expand All @@ -18,6 +19,11 @@ import { schema } from './schemas/pokemon/schema.js'
interface Project {
fs: FSJetpack
run: ExecaMethod
addDprintConfig: () => Promise<void>
addPokemonSchemaSDL: (relativePath?: string) => Promise<{
relative: string
absolute: string
}>
}

export const kitchenSink = KitchenSink.create({ schema: kitchenSinkSchema })
Expand All @@ -42,8 +48,24 @@ export const test = testBase.extend<Fixtures>({
const project: Project = {
fs,
run,
addDprintConfig: async () => {
await fs.writeAsync(`dprint.json`, {
typescript: {},
plugins: [`https://plugins.dprint.dev/typescript-0.93.0.wasm`],
})
},
addPokemonSchemaSDL: async (relativePath) => {
const pathRelative = relativePath
? Path.join(relativePath, `schema.graphql`)
: Path.join(`./`, `schema.graphql`)
const contents = Grafaid.Schema.print(schema)
await fs.writeAsync(pathRelative, contents)
return {
relative: pathRelative,
absolute: Path.join(fs.cwd(), pathRelative),
}
},
}
const relativePathToGraffle = Path.join(`..`, Path.relative(fs.cwd(), Path.join(import.meta.dirname, `../../`)))
await fs.writeAsync(`package.json`, {
name: `test`,
type: `module`,
Expand Down Expand Up @@ -72,7 +94,11 @@ export const test = testBase.extend<Fixtures>({
target: `ES2023`,
},
})
await run`pnpm add ${relativePathToGraffle} tsx @tsconfig/strictest/tsconfig.json`

const isLink = Boolean(process.env[`e2e_link`])
const graffleInstallPath = (isLink ? `` : `file:`)
+ Path.join(`..`, Path.relative(fs.cwd(), Path.join(import.meta.dirname, `../../`)))
await run`pnpm add ${graffleInstallPath} tsx @tsconfig/strictest/tsconfig.json`
console.log(`Scaffolded project at: ${project.fs.cwd()}\n`)
await use(project)
},
Expand Down
51 changes: 51 additions & 0 deletions tests/e2e/__snapshots__/e2e.test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`client works with generation 1`] = `
[
undefined,
"WARNING: No TypeScript formatter found. Generated code will remain ugly. To have code automatically formatted do one of the following things:
- pnpm add --save-dev @dprint/formatter @dprint/typescript
- pnpm add --save-dev prettier
To suppress this warning disable formatting in one of the following ways:
- CLI: graffle --no-format
- Configuration file: Generator.configuration({ format: false })
- API: Generator.generate({ format: false })
WARNING: Custom scalars detected in the schema, but you have not created a custom scalars module to import implementations from.",
"",
]
`;

exports[`client works with generation 2`] = `
[
undefined,
"[
{
name: 'Pikachu',
hp: 35,
attack: 55,
defense: 40,
trainer: { name: 'Ash' }
}
]",
"",
]
`;

exports[`client works without generation 1`] = `
[
undefined,
"[
{
name: 'Pikachu',
hp: 35,
attack: 55,
defense: 40,
trainer: { name: 'Ash' }
}
]",
"",
]
`;
53 changes: 16 additions & 37 deletions tests/e2e/e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,7 @@ test(`client works without generation`, async ({ project, pokemonService }) => {
`,
)
const result = await project.run`pnpm tsx main`
expect(result.stdio).toMatchInlineSnapshot(`
[
undefined,
"[
{
name: 'Pikachu',
hp: 35,
attack: 55,
defense: 40,
trainer: { name: 'Ash' }
}
]",
"",
]
`)
expect(result.stdio).toMatchSnapshot()
})

test(`client works with generation`, async ({ project, pokemonService }) => {
Expand All @@ -78,33 +64,26 @@ test(`client works with generation`, async ({ project, pokemonService }) => {
)
{
const result = await project.run`pnpm graffle --schema http://localhost:3001/graphql`
expect(result.stdio).toMatchInlineSnapshot(`
[
undefined,
"WARNING: Custom scalars detected in the schema, but you have not created a custom scalars module to import implementations from.",
"",
]
`)
expect(result.stdio).toMatchSnapshot()
}
{
await project.run`pnpm check:types`
}
{
const result = await project.run`pnpm tsx main`
expect(result.stdio).toMatchInlineSnapshot(`
[
undefined,
"[
{
name: 'Pikachu',
hp: 35,
attack: 55,
defense: 40,
trainer: { name: 'Ash' }
}
]",
"",
]
`)
expect(result.stdio).toMatchSnapshot()
}
})

test(`client uses dprint formatter if installed`, async ({ project }) => {
await project.addDprintConfig()
const path = await project.addPokemonSchemaSDL()

await project.run`pnpm add --save-dev dprint @dprint/formatter @dprint/typescript`

const genResult = await project.run`pnpm graffle --schema ${path.relative} --format`
const genResultStdout = genResult.stdout as string
expect(genResultStdout.includes(`No TypeScript formatter found`)).toEqual(false)

await project.run`pnpm dprint check graffle/**/*`
})
Loading

0 comments on commit 5b91cf0

Please sign in to comment.