From f9704e094e22202040c49194e3f9a839484bf7d3 Mon Sep 17 00:00:00 2001 From: Adel Salakh Date: Tue, 26 Sep 2023 23:03:10 +0200 Subject: [PATCH] fix: escape non-identifier keys in generated interfaces --- packages/cli/src/generator.test.ts | 16 ++++++++++++++++ packages/cli/src/generator.ts | 23 ++++++++++++++++++----- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/packages/cli/src/generator.test.ts b/packages/cli/src/generator.test.ts index d094ae52..d4de45e0 100644 --- a/packages/cli/src/generator.test.ts +++ b/packages/cli/src/generator.test.ts @@ -578,6 +578,22 @@ test('comment escaping', () => { ); }); +test('interface generation with escaped keys', () => { + const expected = `export interface ExplainResult { + "QUERY PLAN": string; +} + +`; + const fields = [ + { + fieldName: 'QUERY PLAN', + fieldType: 'string', + }, + ]; + const result = generateInterface('ExplainResult', fields); + expect(result).toEqual(expected); +}); + test('interface generation', () => { const expected = `export interface User { age: number; diff --git a/packages/cli/src/generator.ts b/packages/cli/src/generator.ts index 498b20c0..4e5f5e44 100644 --- a/packages/cli/src/generator.ts +++ b/packages/cli/src/generator.ts @@ -43,16 +43,29 @@ export function escapeComment(comment: string) { return comment.replace(/\*\//g, '*\\/'); } +/** Escape a key if it isn't an identifier literal */ +export function escapeKey(key: string) { + if (/^[a-zA-Z_$][a-zA-Z_$0-9]*$/.test(key)) { + return key; + } + return `"${key}"`; +} + export const generateInterface = (interfaceName: string, fields: IField[]) => { const sortedFields = fields .slice() .sort((a, b) => a.fieldName.localeCompare(b.fieldName)); const contents = sortedFields - .map( - ({ fieldName, fieldType, comment, optional }) => - (comment ? ` /** ${escapeComment(comment)} */\n` : '') + - ` ${fieldName}${optional ? '?' : ''}: ${fieldType};`, - ) + .map(({ fieldName, fieldType, comment, optional }) => { + const lines = []; + if (comment) { + lines.push(` /** ${escapeComment(comment)} */`); + } + const keySuffix = optional ? '?' : ''; + const entryLine = ` ${escapeKey(fieldName)}${keySuffix}: ${fieldType};`; + lines.push(entryLine); + return lines.join('\n'); + }) .join('\n'); return interfaceGen(interfaceName, contents); };