Skip to content

Commit cdb9eea

Browse files
committed
test: add failing test for TypeScript reserved keyword scalar names
Add tests that demonstrate the issue where scalar names that are TypeScript reserved keywords (like 'bigint', 'boolean') generate invalid TypeScript code. The fix is commented out with TODO markers. Issue #1354
1 parent 4c487bc commit cdb9eea

File tree

2 files changed

+84
-6
lines changed

2 files changed

+84
-6
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import * as MemFS from 'memfs'
2+
import { describe, expect, test } from 'vitest'
3+
import { generate } from '../generator/generate.js'
4+
5+
const fs = MemFS.fs.promises as any
6+
7+
describe('Scalar module generation', () => {
8+
describe('Issue #1354 - TypeScript reserved keywords', () => {
9+
test('should escape reserved TypeScript keywords in scalar names', async () => {
10+
await generate({
11+
fs,
12+
schema: {
13+
type: 'sdl',
14+
sdl: `
15+
scalar bigint
16+
scalar boolean
17+
18+
type Query {
19+
getBigint: bigint
20+
getBoolean: boolean
21+
}
22+
`
23+
}
24+
})
25+
26+
const scalarModule = MemFS.fs.readFileSync('./graffle/modules/scalar.ts', 'utf8')
27+
28+
// The generated code should use escaped names (e.g., $bigint instead of bigint)
29+
// to avoid TypeScript compilation errors
30+
expect(scalarModule).toContain('export type $bigint =')
31+
expect(scalarModule).toContain('export type $boolean =')
32+
33+
// But the scalar references should still use the original names
34+
expect(scalarModule).toContain('ScalarCodecless<"bigint">')
35+
expect(scalarModule).toContain('ScalarCodecless<"boolean">')
36+
})
37+
38+
test('should escape reserved keywords for custom scalars with codecs', async () => {
39+
// First create the custom scalars file
40+
await fs.mkdir('./custom-scalars', { recursive: true })
41+
await fs.writeFile('./custom-scalars/scalars.js', `
42+
export const bigint = {
43+
encode: (value) => value.toString(),
44+
decode: (value) => BigInt(value),
45+
}
46+
`)
47+
48+
await generate({
49+
fs,
50+
schema: {
51+
type: 'sdl',
52+
sdl: `
53+
scalar bigint
54+
type Query {
55+
getBigint: bigint
56+
}
57+
`
58+
},
59+
customScalars: './custom-scalars/scalars.js'
60+
})
61+
62+
const scalarModule = MemFS.fs.readFileSync('./graffle/modules/scalar.ts', 'utf8')
63+
64+
// Type definitions should be escaped
65+
expect(scalarModule).toContain('export type $bigint = typeof')
66+
expect(scalarModule).toContain('type $bigint_ = typeof')
67+
expect(scalarModule).toContain('export type $bigintDecoded =')
68+
expect(scalarModule).toContain('export type $bigintEncoded =')
69+
70+
// But runtime references should use original names
71+
expect(scalarModule).toContain('typeof CustomScalars.bigint')
72+
})
73+
})
74+
})

src/generator/generators/Scalar.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import { Grafaid } from '../../lib/grafaid/_namespace.js'
33
import { Tex } from '../../lib/tex/_namespace.js'
44
import { $ } from '../helpers/identifiers.js'
55
import { createModuleGenerator } from '../helpers/moduleGenerator.js'
6-
import { renderName, typeTitle2 } from '../helpers/render.js'
6+
import { typeTitle2 } from '../helpers/render.js'
7+
// TODO: Uncomment to fix issue #1354
8+
// import { renderName, typeTitle2 } from '../helpers/render.js'
79

810
export const ModuleGeneratorScalar = createModuleGenerator(
911
`scalar`,
@@ -32,12 +34,13 @@ export const ModuleGeneratorScalar = createModuleGenerator(
3234
code(typeTitle2(`custom scalar type`)(scalar))
3335
code``
3436
code`
35-
export type ${renderName(scalar.name)} = typeof ${$.CustomScalars}.${scalar.name}
37+
// TODO: Fix issue #1354 - use renderName() here
38+
export type ${scalar.name} = typeof ${$.CustomScalars}.${scalar.name}
3639
// Without this we get error:
3740
// "Exported type alias 'DateDecoded' has or is using private name 'Date'."
38-
type ${renderName(scalar.name)}_ = typeof ${$.CustomScalars}.${scalar.name}
39-
export type ${renderName(scalar.name)}Decoded = ${$.$$Utilities}.Schema.Scalar.GetDecoded<${renderName(scalar.name)}_>
40-
export type ${renderName(scalar.name)}Encoded = ${$.$$Utilities}.Schema.Scalar.GetEncoded<${renderName(scalar.name)}_>
41+
type ${scalar.name}_ = typeof ${$.CustomScalars}.${scalar.name}
42+
export type ${scalar.name}Decoded = ${$.$$Utilities}.Schema.Scalar.GetDecoded<${scalar.name}_>
43+
export type ${scalar.name}Encoded = ${$.$$Utilities}.Schema.Scalar.GetEncoded<${scalar.name}_>
4144
`
4245
code``
4346
}
@@ -56,7 +59,8 @@ export const ModuleGeneratorScalar = createModuleGenerator(
5659
for (const scalar of config.schema.kindMap.list.ScalarCustom) {
5760
code(typeTitle2(`custom scalar type`)(scalar))
5861
code``
59-
code`export type ${renderName(scalar.name)} = ${$.$$Utilities}.Schema.Scalar.ScalarCodecless<'${scalar.name}'>`
62+
// TODO: Fix issue #1354 - use renderName() here
63+
code`export type ${scalar.name} = ${$.$$Utilities}.Schema.Scalar.ScalarCodecless<'${scalar.name}'>`
6064
// code(`import type { String as ${scalar.name} } from '${config.paths.imports.grafflePackage.scalars}'`)
6165
// code()
6266
// code(`export { String as ${scalar.name} } from '${config.paths.imports.grafflePackage.scalars}'`)

0 commit comments

Comments
 (0)