Skip to content

Commit d0ba2da

Browse files
authored
Merge pull request #751 from constructive-io/devin/1772231767-postgres-comments-codegen
feat(codegen): render PostgreSQL comments as JSDoc + add @constructive-io/react package
2 parents 0deec31 + 5c32547 commit d0ba2da

File tree

1,522 files changed

+214997
-7643
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,522 files changed

+214997
-7643
lines changed

graphql/codegen/src/core/codegen/hooks-docs-generator.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -66,22 +66,22 @@ export function generateHooksReadme(
6666
for (const table of tables) {
6767
const { singularName, pluralName } = getTableNames(table);
6868
lines.push(
69-
`| \`${getListQueryHookName(table)}\` | Query | List all ${pluralName} |`,
69+
`| \`${getListQueryHookName(table)}\` | Query | ${table.description || `List all ${pluralName}`} |`,
7070
);
7171
if (hasValidPrimaryKey(table)) {
7272
lines.push(
73-
`| \`${getSingleQueryHookName(table)}\` | Query | Get one ${singularName} |`,
73+
`| \`${getSingleQueryHookName(table)}\` | Query | ${table.description || `Get one ${singularName}`} |`,
7474
);
7575
}
7676
lines.push(
77-
`| \`${getCreateMutationHookName(table)}\` | Mutation | Create a ${singularName} |`,
77+
`| \`${getCreateMutationHookName(table)}\` | Mutation | ${table.description || `Create a ${singularName}`} |`,
7878
);
7979
if (hasValidPrimaryKey(table)) {
8080
lines.push(
81-
`| \`${getUpdateMutationHookName(table)}\` | Mutation | Update a ${singularName} |`,
81+
`| \`${getUpdateMutationHookName(table)}\` | Mutation | ${table.description || `Update a ${singularName}`} |`,
8282
);
8383
lines.push(
84-
`| \`${getDeleteMutationHookName(table)}\` | Mutation | Delete a ${singularName} |`,
84+
`| \`${getDeleteMutationHookName(table)}\` | Mutation | ${table.description || `Delete a ${singularName}`} |`,
8585
);
8686
}
8787
}
@@ -220,7 +220,7 @@ export function generateHooksAgentsDocs(
220220

221221
lines.push(`### HOOK: ${getListQueryHookName(table)}`);
222222
lines.push('');
223-
lines.push(`List all ${pluralName}.`);
223+
lines.push(`${table.description || `List all ${pluralName}`}.`);
224224
lines.push('');
225225
lines.push('```');
226226
lines.push(`TYPE: query`);
@@ -244,7 +244,7 @@ export function generateHooksAgentsDocs(
244244
if (hasValidPrimaryKey(table)) {
245245
lines.push(`### HOOK: ${getSingleQueryHookName(table)}`);
246246
lines.push('');
247-
lines.push(`Get a single ${singularName} by ${pk.name}.`);
247+
lines.push(`${table.description || `Get a single ${singularName} by ${pk.name}`}.`);
248248
lines.push('');
249249
lines.push('```');
250250
lines.push(`TYPE: query`);
@@ -269,7 +269,7 @@ export function generateHooksAgentsDocs(
269269

270270
lines.push(`### HOOK: ${getCreateMutationHookName(table)}`);
271271
lines.push('');
272-
lines.push(`Create a new ${singularName}.`);
272+
lines.push(`${table.description || `Create a new ${singularName}`}.`);
273273
lines.push('');
274274
lines.push('```');
275275
lines.push('TYPE: mutation');
@@ -284,7 +284,7 @@ export function generateHooksAgentsDocs(
284284
if (hasValidPrimaryKey(table)) {
285285
lines.push(`### HOOK: ${getUpdateMutationHookName(table)}`);
286286
lines.push('');
287-
lines.push(`Update an existing ${singularName}.`);
287+
lines.push(`${table.description || `Update an existing ${singularName}`}.`);
288288
lines.push('');
289289
lines.push('```');
290290
lines.push('TYPE: mutation');
@@ -298,7 +298,7 @@ export function generateHooksAgentsDocs(
298298

299299
lines.push(`### HOOK: ${getDeleteMutationHookName(table)}`);
300300
lines.push('');
301-
lines.push(`Delete a ${singularName}.`);
301+
lines.push(`${table.description || `Delete a ${singularName}`}.`);
302302
lines.push('');
303303
lines.push('```');
304304
lines.push('TYPE: mutation');
@@ -374,7 +374,7 @@ export function getHooksMcpTools(
374374

375375
tools.push({
376376
name: `hooks_${lcFirst(pluralName)}_query`,
377-
description: `React Query hook to list all ${pluralName}`,
377+
description: table.description || `React Query hook to list all ${pluralName}`,
378378
inputSchema: {
379379
type: 'object',
380380
properties: {
@@ -389,7 +389,7 @@ export function getHooksMcpTools(
389389
if (hasValidPrimaryKey(table)) {
390390
tools.push({
391391
name: `hooks_${lcFirst(singularName)}_query`,
392-
description: `React Query hook to get a single ${singularName} by ${pk.name}`,
392+
description: table.description || `React Query hook to get a single ${singularName} by ${pk.name}`,
393393
inputSchema: {
394394
type: 'object',
395395
properties: {
@@ -405,7 +405,7 @@ export function getHooksMcpTools(
405405

406406
tools.push({
407407
name: `hooks_create_${lcFirst(singularName)}_mutation`,
408-
description: `React Query mutation hook to create a ${singularName}`,
408+
description: table.description || `React Query mutation hook to create a ${singularName}`,
409409
inputSchema: {
410410
type: 'object',
411411
properties: Object.fromEntries(
@@ -431,7 +431,7 @@ export function getHooksMcpTools(
431431
if (hasValidPrimaryKey(table)) {
432432
tools.push({
433433
name: `hooks_update_${lcFirst(singularName)}_mutation`,
434-
description: `React Query mutation hook to update a ${singularName}`,
434+
description: table.description || `React Query mutation hook to update a ${singularName}`,
435435
inputSchema: {
436436
type: 'object',
437437
properties: {
@@ -446,7 +446,7 @@ export function getHooksMcpTools(
446446

447447
tools.push({
448448
name: `hooks_delete_${lcFirst(singularName)}_mutation`,
449-
description: `React Query mutation hook to delete a ${singularName}`,
449+
description: table.description || `React Query mutation hook to delete a ${singularName}`,
450450
inputSchema: {
451451
type: 'object',
452452
properties: {
@@ -511,7 +511,7 @@ export function generateHooksSkills(
511511
fileName: `skills/${lcFirst(singularName)}.md`,
512512
content: buildSkillFile({
513513
name: `hooks-${lcFirst(singularName)}`,
514-
description: `React Query hooks for ${table.name} data operations`,
514+
description: table.description || `React Query hooks for ${table.name} data operations`,
515515
language: 'typescript',
516516
usage: [
517517
`${getListQueryHookName(table)}({ selection: { fields: { ${selectFields} } } })`,

graphql/codegen/src/core/codegen/mutations.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ export function generateCreateMutationHook(
202202
useMutationResultType(resultType(sRef()), createVarType),
203203
);
204204
addJSDocComment(o1, [
205-
`Mutation hook for creating a ${typeName}`,
205+
table.description || `Mutation hook for creating a ${typeName}`,
206206
'',
207207
'@example',
208208
'```tsx',
@@ -314,7 +314,7 @@ export function generateCreateMutationHook(
314314
return {
315315
fileName: getCreateMutationFileName(table),
316316
content: generateHookFileCode(
317-
`Create mutation hook for ${typeName}`,
317+
table.description || `Create mutation hook for ${typeName}`,
318318
statements,
319319
),
320320
};
@@ -433,7 +433,7 @@ export function generateUpdateMutationHook(
433433
useMutationResultType(resultType(sRef()), updateVarType),
434434
);
435435
addJSDocComment(o1, [
436-
`Mutation hook for updating a ${typeName}`,
436+
table.description || `Mutation hook for updating a ${typeName}`,
437437
'',
438438
'@example',
439439
'```tsx',
@@ -574,7 +574,7 @@ export function generateUpdateMutationHook(
574574
return {
575575
fileName: getUpdateMutationFileName(table),
576576
content: generateHookFileCode(
577-
`Update mutation hook for ${typeName}`,
577+
table.description || `Update mutation hook for ${typeName}`,
578578
statements,
579579
),
580580
};
@@ -686,7 +686,7 @@ export function generateDeleteMutationHook(
686686
useMutationResultType(resultType(sRef()), deleteVarType),
687687
);
688688
addJSDocComment(o1, [
689-
`Mutation hook for deleting a ${typeName} with typed selection`,
689+
table.description || `Mutation hook for deleting a ${typeName} with typed selection`,
690690
'',
691691
'@example',
692692
'```tsx',
@@ -821,7 +821,7 @@ export function generateDeleteMutationHook(
821821
return {
822822
fileName: getDeleteMutationFileName(table),
823823
content: generateHookFileCode(
824-
`Delete mutation hook for ${typeName}`,
824+
table.description || `Delete mutation hook for ${typeName}`,
825825
statements,
826826
),
827827
};

graphql/codegen/src/core/codegen/orm/custom-ops-generator.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@
77
import * as t from '@babel/types';
88

99
import type { CleanArgument, CleanOperation } from '../../../types/schema';
10-
import { generateCode } from '../babel-ast';
10+
import { addJSDocComment, generateCode } from '../babel-ast';
1111
import { NON_SELECT_TYPES, getSelectTypeName } from '../select-helpers';
1212
import {
1313
getTypeBaseName,
1414
isTypeRequired,
1515
scalarToTsType,
1616
typeRefToTsType,
1717
} from '../type-resolver';
18-
import { getGeneratedFileHeader, ucFirst } from '../utils';
18+
import { getGeneratedFileHeader, stripSmartComments, ucFirst } from '../utils';
1919

2020
export interface GeneratedCustomOpsFile {
2121
fileName: string;
@@ -109,6 +109,7 @@ function createImportDeclaration(
109109

110110
function createVariablesInterface(
111111
op: CleanOperation,
112+
comments: boolean = true,
112113
): t.ExportNamedDeclaration | null {
113114
if (op.args.length === 0) return null;
114115

@@ -120,6 +121,10 @@ function createVariablesInterface(
120121
t.tsTypeAnnotation(parseTypeAnnotation(typeRefToTsType(arg.type))),
121122
);
122123
prop.optional = optional;
124+
const argDescription = stripSmartComments(arg.description, comments);
125+
if (argDescription) {
126+
addJSDocComment(prop, argDescription.split('\n'));
127+
}
123128
return prop;
124129
});
125130

@@ -129,7 +134,12 @@ function createVariablesInterface(
129134
null,
130135
t.tsInterfaceBody(props),
131136
);
132-
return t.exportNamedDeclaration(interfaceDecl);
137+
const exportDecl = t.exportNamedDeclaration(interfaceDecl);
138+
const opDescription = stripSmartComments(op.description, comments);
139+
if (opDescription) {
140+
addJSDocComment(exportDecl, [`Variables for ${op.name}`, opDescription]);
141+
}
142+
return exportDecl;
133143
}
134144

135145
function parseTypeAnnotation(typeStr: string): t.TSType {
@@ -400,6 +410,7 @@ function buildOperationMethod(
400410
*/
401411
export function generateCustomQueryOpsFile(
402412
operations: CleanOperation[],
413+
comments: boolean = true,
403414
): GeneratedCustomOpsFile {
404415
const statements: t.Statement[] = [];
405416

@@ -444,7 +455,7 @@ export function generateCustomQueryOpsFile(
444455

445456
// Generate variable interfaces
446457
for (const op of operations) {
447-
const varInterface = createVariablesInterface(op);
458+
const varInterface = createVariablesInterface(op, comments);
448459
if (varInterface) statements.push(varInterface);
449460
}
450461

@@ -482,6 +493,7 @@ export function generateCustomQueryOpsFile(
482493
*/
483494
export function generateCustomMutationOpsFile(
484495
operations: CleanOperation[],
496+
comments: boolean = true,
485497
): GeneratedCustomOpsFile {
486498
const statements: t.Statement[] = [];
487499

@@ -526,7 +538,7 @@ export function generateCustomMutationOpsFile(
526538

527539
// Generate variable interfaces
528540
for (const op of operations) {
529-
const varInterface = createVariablesInterface(op);
541+
const varInterface = createVariablesInterface(op, comments);
530542
if (varInterface) statements.push(varInterface);
531543
}
532544

graphql/codegen/src/core/codegen/orm/docs-generator.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ export function getOrmMcpTools(
320320

321321
tools.push({
322322
name: `orm_${lcFirst(singularName)}_findMany`,
323-
description: `List all ${table.name} records via ORM`,
323+
description: table.description || `List all ${table.name} records via ORM`,
324324
inputSchema: {
325325
type: 'object',
326326
properties: {
@@ -338,7 +338,7 @@ export function getOrmMcpTools(
338338

339339
tools.push({
340340
name: `orm_${lcFirst(singularName)}_findOne`,
341-
description: `Get a single ${table.name} record by ${pk.name}`,
341+
description: table.description || `Get a single ${table.name} record by ${pk.name}`,
342342
inputSchema: {
343343
type: 'object',
344344
properties: {
@@ -360,7 +360,7 @@ export function getOrmMcpTools(
360360
}
361361
tools.push({
362362
name: `orm_${lcFirst(singularName)}_create`,
363-
description: `Create a new ${table.name} record`,
363+
description: table.description || `Create a new ${table.name} record`,
364364
inputSchema: {
365365
type: 'object',
366366
properties: createProps,
@@ -382,7 +382,7 @@ export function getOrmMcpTools(
382382
}
383383
tools.push({
384384
name: `orm_${lcFirst(singularName)}_update`,
385-
description: `Update an existing ${table.name} record`,
385+
description: table.description || `Update an existing ${table.name} record`,
386386
inputSchema: {
387387
type: 'object',
388388
properties: updateProps,
@@ -392,7 +392,7 @@ export function getOrmMcpTools(
392392

393393
tools.push({
394394
name: `orm_${lcFirst(singularName)}_delete`,
395-
description: `Delete a ${table.name} record by ${pk.name}`,
395+
description: table.description || `Delete a ${table.name} record by ${pk.name}`,
396396
inputSchema: {
397397
type: 'object',
398398
properties: {
@@ -461,7 +461,7 @@ export function generateOrmSkills(
461461
fileName: `skills/${lcFirst(singularName)}.md`,
462462
content: buildSkillFile({
463463
name: `orm-${lcFirst(singularName)}`,
464-
description: `ORM operations for ${table.name} records`,
464+
description: table.description || `ORM operations for ${table.name} records`,
465465
language: 'typescript',
466466
usage: [
467467
`db.${lcFirst(singularName)}.findMany({ select: { id: true } }).execute()`,

graphql/codegen/src/core/codegen/orm/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export interface GenerateOrmResult {
6565
*/
6666
export function generateOrm(options: GenerateOrmOptions): GenerateOrmResult {
6767
const { tables, customOperations, sharedTypesPath } = options;
68+
const commentsEnabled = options.config.codegen?.comments !== false;
6869
const files: GeneratedFile[] = [];
6970

7071
// Use shared types when a sharedTypesPath is provided (unified output mode)
@@ -138,6 +139,7 @@ export function generateOrm(options: GenerateOrmOptions): GenerateOrmResult {
138139
usedInputTypes,
139140
tables,
140141
usedPayloadTypes,
142+
commentsEnabled,
141143
);
142144
files.push({
143145
path: inputTypesFile.fileName,
@@ -147,13 +149,14 @@ export function generateOrm(options: GenerateOrmOptions): GenerateOrmResult {
147149

148150
// 5. Generate custom operations (if any)
149151
if (hasCustomQueries && customOperations?.queries) {
150-
const queryOpsFile = generateCustomQueryOpsFile(customOperations.queries);
152+
const queryOpsFile = generateCustomQueryOpsFile(customOperations.queries, commentsEnabled);
151153
files.push({ path: queryOpsFile.fileName, content: queryOpsFile.content });
152154
}
153155

154156
if (hasCustomMutations && customOperations?.mutations) {
155157
const mutationOpsFile = generateCustomMutationOpsFile(
156158
customOperations.mutations,
159+
commentsEnabled,
157160
);
158161
files.push({
159162
path: mutationOpsFile.fileName,

0 commit comments

Comments
 (0)