원클릭으로
api-create-gql-query
// Add a new GraphQL query endpoint with type safety, GraphORM integration, and tests
// Add a new GraphQL query endpoint with type safety, GraphORM integration, and tests
Add a new GraphQL mutation to an existing schema in daily-api with validation, resolvers, and tests
Create a new background worker in daily-api with full type safety, infrastructure config, and tests
Wraps any prompt with a reminder to respect CLAUDE.md files
Format TypeORM migrations with beautifully formatted SQL code. Use this skill after generating migrations to ensure consistent SQL formatting.
Local environment management - run SQL queries, set up fake payments, reset test data. Use when the user needs help with local database operations or test data setup.
| name | api-create-gql-query |
| description | Add a new GraphQL query endpoint with type safety, GraphORM integration, and tests |
| argument-hint | [query name and purpose] |
You are adding a new GraphQL query endpoint for daily-api. Follow this skill step by step.
Before writing any code, read these files for code style rules and GraphQL conventions:
AGENTS.md (project root) — code style, architecture, best practicessrc/graphorm/AGENTS.md — GraphORM patterns for N+1 preventionThese are the source of truth for all code style decisions. Do not deviate from them.
Before writing any code, ask the user the following questions in this order:
Which schema file does this query belong in?
Check existing files in src/schema/ (e.g., posts.ts, users.ts, keywords.ts, campaigns.ts, sources.ts, organizations.ts, etc.) and src/graphql.ts imports. Use an existing domain file if the query fits, or create a new one if it represents a new domain.
What does the query return? One of:
- (a) Single entity —
graphorm.queryOne<T>()/graphorm.queryOneOrFail<T>()- (b) List of entities —
graphorm.query<T>()- (c) Paginated list (Relay-style) —
graphorm.queryPaginated<T>()
Check existing GQL types in the target schema file and src/schema/common.ts for reusable types (PageInfo, ConnectionArgs, scalars like DateTime, JSONObject).
What parameters does the query accept?
For every String argument, ask what it represents so the correct Zod validator is chosen (e.g., z.uuid() for IDs, z.email() for emails, z.url() for URLs, z.string().min(1) for free text). All query input parameters must be validated with a Zod schema — this is not optional.
What auth level is needed? One of:
- (a) Public (no auth) — resolver uses
Context- (b) Authenticated — resolver uses
AuthContext, add@authdirective- (c) Moderator-only — add
@auth(requires: [MODERATOR])directive- (d) Plus subscriber — add
@feedPlusdirective
What data should the query return and what filtering/sorting is needed?
Before creating new types, check:
src/schema/common.ts — shared types (PageInfo, connection patterns, scalars)src/entity/ — existing TypeORM entities that map to the desired return typesrc/graphorm/index.ts — existing GraphORM type configurationssrc/common/schema/ — existing Zod schemas that already validate similar inputOnly create new types if nothing reusable exists.
Mandatory for all queries that accept input arguments.
Create or update a Zod schema in src/common/schema/ with Schema suffix. This project uses Zod 4.x — primitive validators are top-level: z.email(), z.uuid(), z.url() (not z.string().email()).
| GQL Type | Use Case | Zod Validator |
|---|---|---|
String! | ID (UUID) | z.uuid() |
String! | ID (non-UUID) | z.string().min(1) |
String! | z.email() | |
String! | URL | z.url() |
String! | Free text | z.string().min(1) |
String (nullable) | Any | appropriate validator with .nullish() |
Int / Int! | Number | z.number().int() with .min()/.max() |
Boolean | Flag | z.boolean() |
Rules:
z.infer<typeof schema> at point of useString args, ask the user what the value represents before choosing a validatorIf new types are needed, add a TypeScript type (not interface — per AGENTS.md) for the GQL return type in the schema file.
Exception: some existing schema files already use interface — follow the pattern in the specific file being modified.
Add to the typeDefs template literal (using /* GraphQL */ tag) in the schema file:
extend type Query { ... } with the new query field and auth directivesFor paginated queries, define Edge and Connection types following the pattern in src/schema/campaigns.ts.
All queries must use GraphORM (not TypeORM repositories). Wrap resolvers in traceResolvers(). Validate input with the Zod schema from Step 2 using schema.parse(args). Pass true as the 4th argument for read replica when eventual consistency is acceptable. Filter at the database level via the builder callback, not in JavaScript.
Reference examples:
src/schema/keywords.ts → keyword, src/schema/campaigns.ts → campaignByIdsrc/schema/keywords.ts → randomPendingKeywordsrc/schema/campaigns.ts → campaignsListIf the query returns a new entity type or needs custom field mappings, add configuration to src/graphorm/index.ts. Define requiredColumns, field transforms, custom relations as needed. Reference src/graphorm/AGENTS.md for patterns.
Skip if using an already-configured entity type.
Only needed when creating a new schema file.
In src/graphql.ts:
import * as newDomain from './schema/newDomain'newDomain.typeDefs to the typeDefs arraynewDomain.resolvers to the merge() callCreate or update test file in __tests__/. Reference: __tests__/keywords.ts for the full test structure.
Use the initializeGraphQLTesting + MockContext + GraphQLTestClient pattern from __tests__/helpers.
Test cases to include:
toMatchObject/toEqual)Run with: NODE_ENV=test npx jest __tests__/<test-file>.ts --testEnvironment=node --runInBand
| Purpose | Path |
|---|---|
| GraphQL schema & resolvers | src/schema/<domain>.ts |
| Schema registration | src/graphql.ts |
| GraphORM configuration | src/graphorm/index.ts |
| Shared GQL types | src/schema/common.ts |
| Entity definitions | src/entity/ |
| Zod validation schemas | src/common/schema/ |
| Test file | __tests__/<domain>.ts |
| GraphORM docs | src/graphorm/AGENTS.md |
| Code style reference | AGENTS.md |
When the user invokes this skill:
AGENTS.md and src/graphorm/AGENTS.md for contextString argument, ask what it represents so the right Zod validator is chosen.src/schema/keywords.ts for simple queries, src/schema/campaigns.ts for paginated) rather than relying solely on templatespnpm run build && pnpm run lint