constructive-graphql-codegen
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseConstructive GraphQL Codegen
Constructive GraphQL 代码生成器
Generate type-safe React Query hooks, Prisma-like ORM client, or inquirerer-based CLI from GraphQL schema files, endpoints, databases, or PGPM modules. Also generates documentation in multiple formats.
从GraphQL Schema文件、端点、数据库或PGPM模块生成类型安全的React Query hooks、类Prisma的ORM客户端,或基于inquirerer的CLI。同时支持生成多种格式的文档。
When to Apply
适用场景
Use this skill when:
- Setting up GraphQL code generation for a PostGraphile backend
- User asks to generate hooks, ORM, CLI, or type-safe GraphQL client
- Exporting a GraphQL schema from a database or endpoint
- Generating documentation (README, AGENTS.md, skill files, MCP tool definitions)
- Implementing features that need to fetch or mutate data
- Using previously generated hooks, ORM, or CLI code
- Regenerating code after schema changes
Important: Always prefer generated code over raw GraphQL queries or SQL.
以下场景适用本工具:
- 为PostGraphile后端配置GraphQL代码生成
- 需要生成hooks、ORM、CLI或类型安全的GraphQL客户端
- 从数据库或端点导出GraphQL Schema
- 生成文档(README、AGENTS.md、技能文件、MCP工具定义)
- 实现需要获取或修改数据的功能
- 使用已生成的hooks、ORM或CLI代码
- Schema变更后重新生成代码
重要提示:优先使用生成的代码,而非原生GraphQL查询或SQL语句。
Recommended Workflow: Schema Export + Schema Directory
推荐工作流:Schema导出 + Schema目录
The recommended approach is a two-step workflow using schema export followed by . This is the most deterministic and portable way to use codegen:
schemaDir推荐方案是分两步的工作流:先导出Schema,再使用。这是使用代码生成器最具确定性和可移植性的方式:
schemaDirStep 1: Export schema(s) to .graphql
files
.graphql步骤1:将Schema导出为.graphql文件
Export your schema from any source (database, PGPM module, endpoint) into a directory of files:
.graphqlbash
undefined从任意源(数据库、PGPM模块、端点)将Schema导出为.graphql文件目录:
bash
undefinedExport from database
从数据库导出
npx @constructive-io/graphql-codegen --schema-only --schemas public --schema-only-output ./schemas --schema-only-filename public.graphql
npx @constructive-io/graphql-codegen --schema-only --schemas public --schema-only-output ./schemas --schema-only-filename public.graphql
Export from PGPM module (via config)
从PGPM模块导出(通过配置)
npx @constructive-io/graphql-codegen --schema-only -c graphql-codegen.config.ts
npx @constructive-io/graphql-codegen --schema-only -c graphql-codegen.config.ts
Export from endpoint
从端点导出
npx @constructive-io/graphql-codegen --schema-only -e https://api.example.com/graphql --schema-only-output ./schemas
Or programmatically:
```typescript
import { generate } from '@constructive-io/graphql-codegen';
// Export from database
await generate({
db: { schemas: ['public'] },
schemaOnly: true,
schemaOnlyOutput: './schemas',
schemaOnlyFilename: 'public.graphql',
});
// Export from PGPM module
await generate({
db: {
pgpm: { modulePath: './packages/my-module' },
schemas: ['app_public'],
},
schemaOnly: true,
schemaOnlyOutput: './schemas',
schemaOnlyFilename: 'app_public.graphql',
});npx @constructive-io/graphql-codegen --schema-only -e https://api.example.com/graphql --schema-only-output ./schemas
或通过编程方式导出:
```typescript
import { generate } from '@constructive-io/graphql-codegen';
// 从数据库导出
await generate({
db: { schemas: ['public'] },
schemaOnly: true,
schemaOnlyOutput: './schemas',
schemaOnlyFilename: 'public.graphql',
});
// 从PGPM模块导出
await generate({
db: {
pgpm: { modulePath: './packages/my-module' },
schemas: ['app_public'],
},
schemaOnly: true,
schemaOnlyOutput: './schemas',
schemaOnlyFilename: 'app_public.graphql',
});Step 2: Generate code from the schema directory
步骤2:从Schema目录生成代码
Point at the directory containing your files. Each file automatically becomes a separate target:
schemaDir.graphqltypescript
// graphql-codegen.config.ts
import { defineConfig } from '@constructive-io/graphql-codegen';
export default defineConfig({
schemaDir: './schemas', // Directory of .graphql files
output: './generated', // Each file becomes ./generated/{name}/
reactQuery: true,
orm: true,
});bash
npx @constructive-io/graphql-codegen -c graphql-codegen.config.tsGiven and , this produces:
schemas/public.graphqlschemas/admin.graphqlgenerated/
public/ # Generated from public.graphql
hooks/
orm/
admin/ # Generated from admin.graphql
hooks/
orm/Why this approach is best:
- Deterministic — files are static, version-controllable artifacts
.graphql - Portable — no live database or endpoint needed at code generation time
- Fast — no network requests or ephemeral database creation during codegen
- Reviewable — schema changes show up as clear diffs in version control
将指向包含.graphql文件的目录,每个文件会自动成为一个独立的目标:
schemaDirtypescript
// graphql-codegen.config.ts
import { defineConfig } from '@constructive-io/graphql-codegen';
export default defineConfig({
schemaDir: './schemas', // .graphql文件所在目录
output: './generated', // 每个文件会生成到./generated/{name}/目录下
reactQuery: true,
orm: true,
});bash
npx @constructive-io/graphql-codegen -c graphql-codegen.config.ts如果存在和,将生成如下结构:
schemas/public.graphqlschemas/admin.graphqlgenerated/
public/ # 从public.graphql生成
hooks/
orm/
admin/ # 从admin.graphql生成
hooks/
orm/该方案的优势:
- 确定性 — .graphql文件是静态的、可版本控制的产物
- 可移植性 — 代码生成时无需依赖实时数据库或端点
- 高效性 — 代码生成过程中无需网络请求或临时数据库创建
- 可评审性 — Schema变更会在版本控制系统中显示为清晰的差异
Quick Start
快速开始
Installation
安装
bash
pnpm add @constructive-io/graphql-codegenbash
pnpm add @constructive-io/graphql-codegenGenerate React Query Hooks
生成React Query Hooks
bash
npx @constructive-io/graphql-codegen --react-query -s ./schemas/public.graphql -o ./generatedbash
npx @constructive-io/graphql-codegen --react-query -s ./schemas/public.graphql -o ./generatedGenerate ORM Client
生成ORM客户端
bash
npx @constructive-io/graphql-codegen --orm -s ./schemas/public.graphql -o ./generatedbash
npx @constructive-io/graphql-codegen --orm -s ./schemas/public.graphql -o ./generatedGenerate CLI
生成CLI
bash
npx @constructive-io/graphql-codegen --cli -s ./schemas/public.graphql -o ./generatedbash
npx @constructive-io/graphql-codegen --cli -s ./schemas/public.graphql -o ./generatedGenerate from Endpoint
从端点生成
bash
npx @constructive-io/graphql-codegen --react-query -e https://api.example.com/graphql -o ./generatedbash
npx @constructive-io/graphql-codegen --react-query -e https://api.example.com/graphql -o ./generatedGenerate from Database
从数据库生成
bash
npx @constructive-io/graphql-codegen --react-query --schemas public,app_public -o ./generatedbash
npx @constructive-io/graphql-codegen --react-query --schemas public,app_public -o ./generatedProgrammatic API
编程式API
Use the function to integrate codegen into your build scripts or tools.
generate()使用函数将代码生成集成到构建脚本或工具中。
generate()Import and Basic Usage
导入与基础用法
typescript
import { generate } from '@constructive-io/graphql-codegen';
// Generate from endpoint
await generate({
endpoint: 'https://api.example.com/graphql',
output: './generated',
reactQuery: true,
orm: true,
});
// Node.js with undici dispatcher (fixes localhost DNS issues)
await generate({
endpoint: 'http://api.localhost:3000/graphql',
output: './generated',
reactQuery: true,
browserCompatible: false, // Use undici with custom dispatcher
});typescript
import { generate } from '@constructive-io/graphql-codegen';
// 从端点生成
await generate({
endpoint: 'https://api.example.com/graphql',
output: './generated',
reactQuery: true,
orm: true,
});
// Node.js环境使用undici调度器(解决localhost DNS问题)
await generate({
endpoint: 'http://api.localhost:3000/graphql',
output: './generated',
reactQuery: true,
browserCompatible: false, // 使用带自定义调度器的undici
});Schema Sources
Schema源
typescript
// From GraphQL endpoint
await generate({
endpoint: 'https://api.example.com/graphql',
headers: { Authorization: 'Bearer token' },
reactQuery: true,
});
// From schema file
await generate({
schemaFile: './schema.graphql',
output: './generated',
orm: true,
});
// From database (explicit schemas)
await generate({
db: { schemas: ['public', 'app_public'] },
reactQuery: true,
});
// From database (auto-discover via API names)
await generate({
db: { apiNames: ['my_api'] },
orm: true,
});
// From PGPM module
await generate({
db: {
pgpm: { modulePath: './packages/my-module' },
schemas: ['public'],
},
reactQuery: true,
});typescript
// 从GraphQL端点
await generate({
endpoint: 'https://api.example.com/graphql',
headers: { Authorization: 'Bearer token' },
reactQuery: true,
});
// 从Schema文件
await generate({
schemaFile: './schema.graphql',
output: './generated',
orm: true,
});
// 从数据库(指定Schema)
await generate({
db: { schemas: ['public', 'app_public'] },
reactQuery: true,
});
// 从数据库(通过API名称自动发现)
await generate({
db: { apiNames: ['my_api'] },
orm: true,
});
// 从PGPM模块
await generate({
db: {
pgpm: { modulePath: './packages/my-module' },
schemas: ['public'],
},
reactQuery: true,
});Generate Options
生成选项
typescript
interface GenerateOptions {
// Schema source (choose one)
endpoint?: string;
schemaFile?: string;
schemaDir?: string; // Directory of .graphql files — auto-expands to multi-target
db?: {
config?: { host, port, database, user, password };
schemas?: string[];
apiNames?: string[]; // Auto-discover schemas from services_public.api_schemas
pgpm?: { modulePath, workspacePath, moduleName };
keepDb?: boolean; // Keep ephemeral DB after introspection (debugging)
};
// Output
output?: string; // Default: './generated/graphql'
// Generators
reactQuery?: boolean; // Default: false
orm?: boolean; // Default: false
cli?: CliConfig | boolean; // Default: false — generate inquirerer CLI
// Schema export (instead of code generation)
schemaOnly?: boolean; // Export schema to .graphql file, skip codegen
schemaOnlyOutput?: string; // Output directory for exported schema
schemaOnlyFilename?: string; // Filename (default: 'schema.graphql')
// Documentation (generated alongside code)
docs?: DocsConfig | boolean; // Default: { readme: true, agents: true, mcp: false, skills: false }
// Node.js HTTP adapter (auto-enabled when cli is true)
nodeHttpAdapter?: boolean; // Default: false
// Filtering
tables?: { include?, exclude?, systemExclude? };
queries?: { include?, exclude?, systemExclude? };
mutations?: { include?, exclude?, systemExclude? };
excludeFields?: string[];
// Authentication
headers?: Record<string, string>;
authorization?: string; // Convenience for Authorization header
// Options
verbose?: boolean;
dryRun?: boolean;
skipCustomOperations?: boolean;
}typescript
interface GenerateOptions {
// Schema源(选其一)
endpoint?: string;
schemaFile?: string;
schemaDir?: string; // .graphql文件目录 — 自动扩展为多目标
db?: {
config?: { host, port, database, user, password };
schemas?: string[];
apiNames?: string[]; // 从services_public.api_schemas自动发现Schema
pgpm?: { modulePath, workspacePath, moduleName };
keepDb?: boolean; // 自省后保留临时数据库(用于调试)
};
// 输出
output?: string; // 默认值: './generated/graphql'
// 生成器
reactQuery?: boolean; // 默认值: false
orm?: boolean; // 默认值: false
cli?: CliConfig | boolean; // 默认值: false — 生成inquirerer CLI
// Schema导出(替代代码生成)
schemaOnly?: boolean; // 将Schema导出为.graphql文件,跳过代码生成
schemaOnlyOutput?: string; // 导出Schema的输出目录
schemaOnlyFilename?: string; // 文件名(默认: 'schema.graphql')
// 文档(与代码同时生成)
docs?: DocsConfig | boolean; // 默认值: { readme: true, agents: true, mcp: false, skills: false }
// Node.js HTTP适配器(启用CLI时自动开启)
nodeHttpAdapter?: boolean; // 默认值: false
// 过滤
tables?: { include?, exclude?, systemExclude? };
queries?: { include?, exclude?, systemExclude? };
mutations?: { include?, exclude?, systemExclude? };
excludeFields?: string[];
// 认证
headers?: Record<string, string>;
authorization?: string; // 便捷设置Authorization头
// 其他选项
verbose?: boolean;
dryRun?: boolean;
skipCustomOperations?: boolean;
}Build Script Example
构建脚本示例
typescript
// scripts/codegen.ts
import { generate } from '@constructive-io/graphql-codegen';
async function main() {
console.log('Generating GraphQL code...');
const result = await generate({
endpoint: process.env.GRAPHQL_ENDPOINT!,
headers: {
Authorization: `Bearer ${process.env.API_TOKEN}`,
},
output: './src/generated',
reactQuery: true,
orm: true,
tables: {
include: ['User', 'Post', 'Comment'],
},
});
if (!result.success) {
console.error('Codegen failed:', result.error);
process.exit(1);
}
console.log('✓ Code generated successfully');
}
main();typescript
// scripts/codegen.ts
import { generate } from '@constructive-io/graphql-codegen';
async function main() {
console.log('生成GraphQL代码...');
const result = await generate({
endpoint: process.env.GRAPHQL_ENDPOINT!,
headers: {
Authorization: `Bearer ${process.env.API_TOKEN}`,
},
output: './src/generated',
reactQuery: true,
orm: true,
tables: {
include: ['User', 'Post', 'Comment'],
},
});
if (!result.success) {
console.error('代码生成失败:', result.error);
process.exit(1);
}
console.log('✓ 代码生成成功');
}
main();CLI Commands
CLI命令
Note: The CLI does not use subcommands. All options are passed directly to .
graphql-codegen| Command | Purpose |
|---|---|
| Generate code (use |
| Generate React Query hooks |
| Generate ORM client |
| Generate inquirerer-based CLI |
| Generate all three |
注意:CLI不使用子命令,所有选项直接传递给。
graphql-codegen| 命令 | 用途 |
|---|---|
| 生成代码(使用 |
| 生成React Query hooks |
| 生成ORM客户端 |
| 生成基于inquirerer的CLI |
| 同时生成以上三种产物 |
Common Options
常用选项
| Option | Description |
|---|---|
| GraphQL endpoint URL |
| Path to GraphQL schema file |
| Directory of |
| PostgreSQL schemas (comma-separated) |
| API names for auto schema discovery |
| Output directory (default: |
| Config file path |
| Generate React Query hooks |
| Generate ORM client |
| Generate inquirerer-based CLI |
| Export schema to |
| Output directory for schema export |
| Filename for exported schema (default: |
| Authorization header |
| Target name in multi-target config |
| Preview without writing |
| Show detailed output |
| 选项 | 说明 |
|---|---|
| GraphQL端点URL |
| GraphQL Schema文件路径 |
| .graphql文件目录(自动多目标) |
| PostgreSQL Schema(逗号分隔) |
| 用于自动发现Schema的API名称 |
| 输出目录(默认: |
| 配置文件路径 |
| 生成React Query hooks |
| 生成ORM客户端 |
| 生成基于inquirerer的CLI |
| 将Schema导出为.graphql文件(不生成代码) |
| Schema导出的输出目录 |
| 导出Schema的文件名(默认: |
| Authorization头 |
| 多目标配置中的目标名称 |
| 预览生成结果,不写入文件 |
| 显示详细输出 |
Configuration File
配置文件
Create a configuration file manually:
File:
graphql-codegen.config.tstypescript
import { defineConfig } from '@constructive-io/graphql-codegen';
// RECOMMENDED: From a directory of .graphql schema files
export default defineConfig({
schemaDir: './schemas',
output: './generated',
reactQuery: true,
orm: true,
});
// From a single schema file
export default defineConfig({
schemaFile: './schemas/public.graphql',
output: './generated',
reactQuery: true,
orm: true,
});
// From GraphQL endpoint
export default defineConfig({
endpoint: 'https://api.example.com/graphql',
output: './generated',
reactQuery: true,
orm: true,
headers: {
Authorization: `Bearer ${process.env.API_TOKEN}`,
},
});
// From database
export default defineConfig({
db: {
schemas: ['public', 'app_public'], // Explicit schemas
// OR
apiNames: ['my_api'], // Auto-discover schemas from API
},
output: './generated',
reactQuery: true,
});
// From PGPM module
export default defineConfig({
db: {
pgpm: { modulePath: './packages/my-module' },
schemas: ['public'],
},
output: './generated',
orm: true,
});手动创建配置文件:
文件:
graphql-codegen.config.tstypescript
import { defineConfig } from '@constructive-io/graphql-codegen';
// 推荐:从.graphql Schema文件目录生成
export default defineConfig({
schemaDir: './schemas',
output: './generated',
reactQuery: true,
orm: true,
});
// 从单个Schema文件生成
export default defineConfig({
schemaFile: './schemas/public.graphql',
output: './generated',
reactQuery: true,
orm: true,
});
// 从GraphQL端点生成
export default defineConfig({
endpoint: 'https://api.example.com/graphql',
output: './generated',
reactQuery: true,
orm: true,
headers: {
Authorization: `Bearer ${process.env.API_TOKEN}`,
},
});
// 从数据库生成
export default defineConfig({
db: {
schemas: ['public', 'app_public'], // 指定Schema
// 或
apiNames: ['my_api'], // 从API自动发现Schema
},
output: './generated',
reactQuery: true,
});
// 从PGPM模块生成
export default defineConfig({
db: {
pgpm: { modulePath: './packages/my-module' },
schemas: ['public'],
},
output: './generated',
orm: true,
});CLI Generation
CLI生成配置
typescript
export default defineConfig({
endpoint: 'https://api.example.com/graphql',
output: './generated',
cli: true, // Generate CLI with default tool name
// OR with options:
cli: {
toolName: 'myapp', // Config stored at ~/.myapp/
entryPoint: true, // Generate runnable index.ts
builtinNames: { // Override infra command names
auth: 'credentials',
context: 'env',
},
},
});When , is auto-enabled (Node.js HTTP adapter for localhost subdomain resolution).
cli: truenodeHttpAdaptertypescript
export default defineConfig({
endpoint: 'https://api.example.com/graphql',
output: './generated',
cli: true, // 使用默认工具名称生成CLI
// 或自定义选项:
cli: {
toolName: 'myapp', // 配置存储在~/.myapp/
entryPoint: true, // 生成可执行的index.ts
builtinNames: { // 覆盖基础命令名称
auth: 'credentials',
context: 'env',
},
},
});当设置时,会自动启用(用于localhost子域名解析的Node.js HTTP适配器)。
cli: truenodeHttpAdapterDocumentation Generation
文档生成配置
typescript
export default defineConfig({
endpoint: 'https://api.example.com/graphql',
output: './generated',
orm: true,
docs: true, // Enable all doc formats
// OR configure individually:
docs: {
readme: true, // README.md — human-readable overview
agents: true, // AGENTS.md — structured for LLM consumption
mcp: false, // mcp.json — MCP tool definitions
skills: true, // skills/ — per-command .md skill files (Devin-compatible)
},
});docs.skillsskills/.mddocs.agentsAGENTS.mddocs.mcpmcp.jsoninputSchematypescript
export default defineConfig({
endpoint: 'https://api.example.com/graphql',
output: './generated',
orm: true,
docs: true, // 启用所有文档格式
// 或单独配置:
docs: {
readme: true, // README.md — 人类可读的概览文档
agents: true, // AGENTS.md — 为LLM设计的结构化文档
mcp: false, // mcp.json — MCP工具定义
skills: true, // skills/ — 每个命令对应一个.md技能文件(兼容Devin)
},
});docs.skillsskills/docs.agentsAGENTS.mddocs.mcpmcp.jsoninputSchemaNode.js HTTP Adapter
Node.js HTTP适配器
typescript
export default defineConfig({
endpoint: 'http://api.localhost:3000/graphql',
output: './generated',
orm: true,
nodeHttpAdapter: true, // Generates node-fetch.ts with NodeHttpAdapter
});The uses / for requests, enabling local development with subdomain-based routing (e.g., ). No global patching required.
NodeHttpAdapternode:httpnode:httpsauth.localhost:3000typescript
import { NodeHttpAdapter } from './orm/node-fetch';
import { createClient } from './orm';
const db = createClient({
adapter: new NodeHttpAdapter(endpoint, headers),
});typescript
export default defineConfig({
endpoint: 'http://api.localhost:3000/graphql',
output: './generated',
orm: true,
nodeHttpAdapter: true, // 生成带有NodeHttpAdapter的node-fetch.ts
});NodeHttpAdapternode:httpnode:httpsauth.localhost:3000typescript
import { NodeHttpAdapter } from './orm/node-fetch';
import { createClient } from './orm';
const db = createClient({
adapter: new NodeHttpAdapter(endpoint, headers),
});Multi-Target Configuration
多目标配置
There are three ways to get multi-target generation:
有三种方式实现多目标生成:
1. Schema directory (recommended)
1. Schema目录(推荐)
schemaDir.graphqltypescript
export default defineConfig({
schemaDir: './schemas', // Contains public.graphql, admin.graphql, etc.
output: './generated', // Produces ./generated/public/, ./generated/admin/, etc.
reactQuery: true,
orm: true,
});schemaDirtypescript
export default defineConfig({
schemaDir: './schemas', // 包含public.graphql、admin.graphql等
output: './generated', // 生成./generated/public/、./generated/admin/等
reactQuery: true,
orm: true,
});2. Explicit multi-target
2. 显式多目标
Define each target explicitly when they have different sources or options:
typescript
export default defineConfig({
public: {
schemaFile: './schemas/public.graphql',
output: './generated/public',
reactQuery: true,
},
admin: {
schemaFile: './schemas/admin.graphql',
output: './generated/admin',
orm: true,
cli: true,
},
});当目标有不同的源或选项时,可显式定义每个目标:
typescript
export default defineConfig({
public: {
schemaFile: './schemas/public.graphql',
output: './generated/public',
reactQuery: true,
},
admin: {
schemaFile: './schemas/admin.graphql',
output: './generated/admin',
orm: true,
cli: true,
},
});3. Auto-expand from multiple API names
3. 从多个API名称自动扩展
When contains multiple entries, each API name automatically becomes a separate target:
db.apiNamestypescript
export default defineConfig({
db: { apiNames: ['public', 'admin'] },
output: './generated', // Produces ./generated/public/, ./generated/admin/
orm: true,
});This queries for each API name to resolve the corresponding PostgreSQL schemas, then generates each target independently.
services_public.api_schemas当包含多个条目时,每个API名称会自动成为一个独立目标:
db.apiNamestypescript
export default defineConfig({
db: { apiNames: ['public', 'admin'] },
output: './generated', // 生成./generated/public/、./generated/admin/
orm: true,
});这会为每个API名称查询以解析对应的PostgreSQL Schema,然后独立生成每个目标。
services_public.api_schemasShared PGPM sources in multi-target
多目标中的共享PGPM源
When multiple targets share the same PGPM module, the codegen automatically deduplicates ephemeral database creation. One ephemeral database is created and reused across all targets that reference the same module, avoiding redundant deploys.
当多个目标共享同一个PGPM模块时,代码生成器会自动去重临时数据库创建。同一个模块对应的所有目标会复用一个临时数据库,避免重复部署。
Using Generated Hooks
使用生成的Hooks
Configure Client (once at app startup)
配置客户端(应用启动时执行一次)
typescript
import { configure } from '@/generated/hooks';
configure({
endpoint: process.env.NEXT_PUBLIC_GRAPHQL_URL!,
headers: { Authorization: `Bearer ${getToken()}` },
});typescript
import { configure } from '@/generated/hooks';
configure({
endpoint: process.env.NEXT_PUBLIC_GRAPHQL_URL!,
headers: { Authorization: `Bearer ${getToken()}` },
});Query Data
查询数据
typescript
import { useUsersQuery } from '@/generated/hooks';
function UserList() {
const { data, isLoading } = useUsersQuery({
first: 10,
filter: { role: { eq: 'ADMIN' } },
});
if (isLoading) return <Spinner />;
return <ul>{data?.users?.nodes.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
}typescript
import { useUsersQuery } from '@/generated/hooks';
function UserList() {
const { data, isLoading } = useUsersQuery({
first: 10,
filter: { role: { eq: 'ADMIN' } },
});
if (isLoading) return <Spinner />;
return <ul>{data?.users?.nodes.map(u => <li key={u.id}>{u.name}</li>)}</ul>;
}Mutate Data
修改数据
typescript
import { useCreateUserMutation } from '@/generated/hooks';
function CreateUser() {
const createUser = useCreateUserMutation();
return (
<button onClick={() => createUser.mutate({ input: { name: 'John' } })}>
Create
</button>
);
}typescript
import { useCreateUserMutation } from '@/generated/hooks';
function CreateUser() {
const createUser = useCreateUserMutation();
return (
<button onClick={() => createUser.mutate({ input: { name: 'John' } })}>
创建用户
</button>
);
}Using Generated CLI
使用生成的CLI
When is set, codegen generates inquirerer-based CLI commands to .
cli: true{output}/cli/当设置时,代码生成器会在目录下生成基于inquirerer的CLI命令。
cli: true{output}/cli/Generated Structure
生成的结构
generated/cli/
commands/ # One file per table + custom operations
users.ts # CRUD commands for users table
posts.ts # CRUD commands for posts table
my-query.ts # Custom query command
command-map.ts # Maps command names to handlers
executor.ts # Command executor with auth context
utils.ts # Shared utilities
node-fetch.ts # NodeHttpAdapter for localhost
index.ts # Entry point (if entryPoint: true)generated/cli/
commands/ # 每个表和自定义操作对应一个文件
users.ts # 用户表的CRUD命令
posts.ts # 帖子表的CRUD命令
my-query.ts # 自定义查询命令
command-map.ts # 命令名称到处理器的映射
executor.ts # 带认证上下文的命令执行器
utils.ts # 共享工具函数
node-fetch.ts # 用于localhost的NodeHttpAdapter
index.ts # 入口文件(如果entryPoint: true)Running the CLI
运行CLI
If is set:
entryPoint: truebash
npx ts-node generated/cli/index.tsOr integrate the command map into your own CLI:
typescript
import { commands } from './generated/cli/command-map';
import { Inquirerer } from 'inquirerer';
const prompter = new Inquirerer();
await commands.users.list(argv, prompter);如果设置了:
entryPoint: truebash
npx ts-node generated/cli/index.ts或将命令映射集成到自己的CLI中:
typescript
import { commands } from './generated/cli/command-map';
import { Inquirerer } from 'inquirerer';
const prompter = new Inquirerer();
await commands.users.list(argv, prompter);Built-in Infrastructure Commands
内置基础命令
The CLI includes infrastructure commands:
- auth (or if name collides) — manage API credentials stored via appstash
credentials - context (or if name collides) — manage endpoint and auth context
env
CLI包含以下基础命令:
- auth(如果名称冲突则为) — 管理存储在appstash中的API凭证
credentials - context(如果名称冲突则为) — 管理端点和认证上下文
env
Using Generated ORM
使用生成的ORM
Create Client
创建客户端
typescript
import { createClient } from '@/generated/orm';
export const db = createClient({
endpoint: process.env.GRAPHQL_URL!,
headers: { Authorization: `Bearer ${process.env.API_TOKEN}` },
});typescript
import { createClient } from '@/generated/orm';
export const db = createClient({
endpoint: process.env.GRAPHQL_URL!,
headers: { Authorization: `Bearer ${process.env.API_TOKEN}` },
});Query Data
查询数据
typescript
const users = await db.user.findMany({
select: { id: true, name: true, email: true },
filter: { role: { eq: 'ADMIN' } },
first: 10,
}).execute().unwrap();typescript
const users = await db.user.findMany({
select: { id: true, name: true, email: true },
filter: { role: { eq: 'ADMIN' } },
first: 10,
}).execute().unwrap();Relations
关联查询
typescript
const posts = await db.post.findMany({
select: {
id: true,
title: true,
author: { select: { id: true, name: true } },
},
}).execute().unwrap();
// posts[0].author.name is fully typedtypescript
const posts = await db.post.findMany({
select: {
id: true,
title: true,
author: { select: { id: true, name: true } },
},
}).execute().unwrap();
// posts[0].author.name是完全类型化的Error Handling
错误处理
typescript
const result = await db.user.findOne({ id: '123' }).execute();
if (result.ok) {
console.log(result.value.name);
} else {
console.error(result.error.message);
}
// Or use helpers
const user = await db.user.findOne({ id }).execute().unwrap(); // throws on error
const user = await db.user.findOne({ id }).execute().unwrapOr(defaultUser);typescript
const result = await db.user.findOne({ id: '123' }).execute();
if (result.ok) {
console.log(result.value.name);
} else {
console.error(result.error.message);
}
// 或使用辅助函数
const user = await db.user.findOne({ id }).execute().unwrap(); // 错误时抛出异常
const user = await db.user.findOne({ id }).execute().unwrapOr(defaultUser);Schema Sources
Schema源优先级
The codegen supports 6 schema source modes. The recommended approach is schema export + (see top of this document).
schemaDir| Priority | Source | Config Key | Best For |
|---|---|---|---|
| 1 (recommended) | Schema directory | | Deterministic, portable, multi-target |
| 2 | Schema file | | Single schema, simple projects |
| 3 | PGPM module (path) | | Schema export from a pgpm module |
| 4 | PGPM workspace | | Schema export from a pgpm workspace |
| 5 | Database | | Schema export from a live database |
| 6 | Endpoint | | Schema export from a running server |
代码生成器支持6种Schema源模式。推荐使用Schema导出 + 的方式(见本文档开头)。
schemaDir| 优先级 | 源 | 配置键 | 最佳适用场景 |
|---|---|---|---|
| 1(推荐) | Schema目录 | | 确定性、可移植性、多目标场景 |
| 2 | Schema文件 | | 单一Schema、简单项目 |
| 3 | PGPM模块(路径) | | 从pgpm模块导出Schema |
| 4 | PGPM工作区 | | 从pgpm工作区导出Schema |
| 5 | 数据库 | | 从实时数据库导出Schema |
| 6 | 端点 | | 从运行中的服务器导出Schema |
From Schema Directory (recommended)
从Schema目录生成(推荐)
bash
npx @constructive-io/graphql-codegen --react-query --orm --schema-dir ./schemas -o ./generatedbash
npx @constructive-io/graphql-codegen --react-query --orm --schema-dir ./schemas -o ./generatedFrom Schema File
从Schema文件生成
bash
npx @constructive-io/graphql-codegen --react-query -s ./schemas/public.graphql -o ./generatedbash
npx @constructive-io/graphql-codegen --react-query -s ./schemas/public.graphql -o ./generatedFrom GraphQL Endpoint
从GraphQL端点生成
bash
npx @constructive-io/graphql-codegen --react-query -e https://api.example.com/graphqlbash
npx @constructive-io/graphql-codegen --react-query -e https://api.example.com/graphqlFrom Database
从数据库生成
bash
undefinedbash
undefinedExplicit schemas
指定Schema
npx @constructive-io/graphql-codegen --orm --schemas public,app_public
npx @constructive-io/graphql-codegen --orm --schemas public,app_public
Auto-discover from API names
通过API名称自动发现
npx @constructive-io/graphql-codegen --react-query --api-names my_api
undefinednpx @constructive-io/graphql-codegen --react-query --api-names my_api
undefinedFrom PGPM Module
从PGPM模块生成
typescript
// In config file — direct path
export default defineConfig({
db: {
pgpm: { modulePath: './packages/my-module' },
schemas: ['public'],
},
reactQuery: true,
});
// In config file — workspace + module name
export default defineConfig({
db: {
pgpm: {
workspacePath: '.',
moduleName: 'my-module',
},
schemas: ['app_public'],
},
orm: true,
});PGPM module sources create an ephemeral database, deploy the module, introspect the schema via PostGraphile, then tear down the database (unless for debugging).
keepDb: truetypescript
// 配置文件中 — 直接路径
export default defineConfig({
db: {
pgpm: { modulePath: './packages/my-module' },
schemas: ['public'],
},
reactQuery: true,
});
// 配置文件中 — 工作区 + 模块名称
export default defineConfig({
db: {
pgpm: {
workspacePath: '.',
moduleName: 'my-module',
},
schemas: ['app_public'],
},
orm: true,
});PGPM模块源会创建一个临时数据库,部署模块,通过PostGraphile自省Schema,然后销毁数据库(调试时可设置保留数据库)。
keepDb: trueSchema Export
Schema导出
Schema export () fetches a schema from any source and writes it as a SDL file without generating any code. This is the recommended first step in the two-step workflow.
schemaOnly: true.graphqlSchema导出模式()会从任意源获取Schema,并将其保存为.graphql SDL文件,不生成任何代码。这是两步工作流中推荐的第一步。
schemaOnly: trueCLI
CLI方式
bash
undefinedbash
undefinedExport from database
从数据库导出
npx @constructive-io/graphql-codegen --schema-only --schemas public --schema-only-output ./schemas --schema-only-filename public.graphql
npx @constructive-io/graphql-codegen --schema-only --schemas public --schema-only-output ./schemas --schema-only-filename public.graphql
Export from endpoint
从端点导出
npx @constructive-io/graphql-codegen --schema-only -e https://api.example.com/graphql --schema-only-output ./schemas
npx @constructive-io/graphql-codegen --schema-only -e https://api.example.com/graphql --schema-only-output ./schemas
Export from PGPM module (via config)
从PGPM模块导出(通过配置)
npx @constructive-io/graphql-codegen --schema-only -c codegen.config.ts
undefinednpx @constructive-io/graphql-codegen --schema-only -c codegen.config.ts
undefinedProgrammatic
编程式方式
typescript
import { generate } from '@constructive-io/graphql-codegen';
const result = await generate({
db: { schemas: ['public'] },
schemaOnly: true,
schemaOnlyOutput: './schemas',
schemaOnlyFilename: 'public.graphql',
});
console.log(result.message); // "Schema exported to ./schemas/public.graphql"typescript
import { generate } from '@constructive-io/graphql-codegen';
const result = await generate({
db: { schemas: ['public'] },
schemaOnly: true,
schemaOnlyOutput: './schemas',
schemaOnlyFilename: 'public.graphql',
});
console.log(result.message); // "Schema已导出到./schemas/public.graphql"Options
选项
| Option | Description | Default |
|---|---|---|
| Enable schema export mode (no code generation) | |
| Output directory for the exported schema | Same as |
| Filename for the exported schema | |
| 选项 | 说明 | 默认值 |
|---|---|---|
| 启用Schema导出模式(不生成代码) | |
| 导出Schema的输出目录 | 与 |
| 导出Schema的文件名 | |
Query Key Factory (React Query)
Query Key工厂(React Query)
Generated hooks include a centralized query key factory for type-safe cache management:
typescript
import { userKeys, invalidate, remove } from '@/generated/hooks';
import { useQueryClient } from '@tanstack/react-query';
const queryClient = useQueryClient();
// Invalidate queries (triggers refetch)
invalidate.user.all(queryClient); // All user queries
invalidate.user.lists(queryClient); // All list queries
invalidate.user.detail(queryClient, id); // Specific user
// Remove from cache (for delete operations)
remove.user(queryClient, userId);
// Track in-flight mutations
import { userMutationKeys } from '@/generated/hooks';
import { useIsMutating } from '@tanstack/react-query';
const isMutating = useIsMutating({ mutationKey: userMutationKeys.all });See for details.
references/query-keys.md生成的Hooks包含一个集中式的Query Key工厂,用于类型安全的缓存管理:
typescript
import { userKeys, invalidate, remove } from '@/generated/hooks';
import { useQueryClient } from '@tanstack/react-query';
const queryClient = useQueryClient();
// 使查询失效(触发重新获取)
invalidate.user.all(queryClient); // 所有用户相关查询
invalidate.user.lists(queryClient); // 所有列表查询
invalidate.user.detail(queryClient, id); // 特定用户查询
// 从缓存中移除(用于删除操作)
remove.user(queryClient, userId);
// 跟踪进行中的修改操作
import { userMutationKeys } from '@/generated/hooks';
import { useIsMutating } from '@tanstack/react-query';
const isMutating = useIsMutating({ mutationKey: userMutationKeys.all });详情请参考。
references/query-keys.mdFilter Syntax
过滤语法
typescript
// Comparison
filter: { age: { eq: 25 } }
filter: { age: { gte: 18, lt: 65 } }
filter: { status: { in: ['ACTIVE', 'PENDING'] } }
// String
filter: { name: { contains: 'john' } }
filter: { email: { endsWith: '.com' } }
// Logical
filter: {
OR: [
{ role: { eq: 'ADMIN' } },
{ role: { eq: 'MODERATOR' } },
],
}typescript
// 比较操作
filter: { age: { eq: 25 } }
filter: { age: { gte: 18, lt: 65 } }
filter: { status: { in: ['ACTIVE', 'PENDING'] } }
// 字符串操作
filter: { name: { contains: 'john' } }
filter: { email: { endsWith: '.com' } }
// 逻辑操作
filter: {
OR: [
{ role: { eq: 'ADMIN' } },
{ role: { eq: 'MODERATOR' } },
],
}Troubleshooting
故障排除
| Issue | Solution |
|---|---|
| No hooks generated | Add |
| No CLI generated | Add |
| Schema not accessible | Verify endpoint URL and auth headers |
Missing | Ensure PostGraphile v5+ with Meta plugin |
| Type errors after regeneration | Delete output directory and regenerate |
| Import errors | Verify generated code exists and paths match |
| Auth errors at runtime | Check |
| Localhost fetch errors (Node.js) | Enable |
| No skill files generated | Set |
| Schema export produces empty file | Verify database/endpoint has tables in the specified schemas |
| Ensure directory contains |
| 问题 | 解决方案 |
|---|---|
| 未生成Hooks | 在配置中添加 |
| 未生成CLI | 在配置中添加 |
| Schema无法访问 | 验证端点URL和认证头 |
缺少 | 确保使用PostGraphile v5+并启用Meta插件 |
| 重新生成后出现类型错误 | 删除输出目录并重新生成 |
| 导入错误 | 验证生成的代码是否存在,路径是否匹配 |
| 运行时认证错误 | 检查 |
| Node.js环境下localhost请求错误 | 启用 |
| 未生成技能文件 | 在配置中设置 |
| Schema导出后文件为空 | 验证数据库/端点的指定Schema中是否包含表 |
| 确保目录中包含.graphql文件(不支持.gql或其他扩展名) |
References
参考文档
For detailed documentation on specific topics only when needed, see references/:
- CLI options and configuration: ,
cli-reference.mdconfig-reference.md - Advanced usage patterns: ,
hooks-patterns.mdorm-patterns.md - Error handling and relations: ,
error-handling.mdrelations.md - Query key factory and cache management:
query-keys.md - Generated output structure: ,
hooks-output.mdorm-output.md
如需特定主题的详细文档,请查看references/目录:
- CLI选项与配置: ,
cli-reference.mdconfig-reference.md - 高级使用模式: ,
hooks-patterns.mdorm-patterns.md - 错误处理与关联查询: ,
error-handling.mdrelations.md - Query Key工厂与缓存管理:
query-keys.md - 生成输出结构: ,
hooks-output.mdorm-output.md