Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
ecc607b
refactor: use ORM mode as core for RQ mode
yyyyaaa Feb 5, 2026
b5eb861
feat(graphql-codegen): unify ORM and RQ selection core
yyyyaaa Feb 7, 2026
4fac2c1
fix(codegen-cli): honor source flags and config overrides
yyyyaaa Feb 7, 2026
3639dc4
feat(test-codegen-app): add local codegen validation app
yyyyaaa Feb 7, 2026
7497345
ci: ignore test-codegen-app changes
yyyyaaa Feb 7, 2026
283ddfa
ci: ignore test package
yyyyaaa Feb 7, 2026
d2e7480
fix(codegen): convert string concatenation to Babel AST and template-…
pyramation Feb 7, 2026
13c06df
refactor(cli): simplify arg parsing with generic transforms, remove -…
pyramation Feb 7, 2026
5eb1b8e
refactor(codegen): remove default selects entirely (Path A)
pyramation Feb 7, 2026
8387056
chore: update makage to 0.1.12 (fix ENOTEMPTY race condition)
pyramation Feb 8, 2026
6cce350
feat(codegen): add fire-and-forget overload for delete hooks (clientM…
pyramation Feb 8, 2026
1485b96
chore(ci): add examples/codegen-integration and clean workflows (remo…
pyramation Feb 8, 2026
c4ecef3
chore: fix codegen runner, add missing deps, update build filters for…
pyramation Feb 8, 2026
fe2308a
fix: keep test-codegen-app exclusion alongside examples filter in build
pyramation Feb 8, 2026
1f2d244
fix(ci): add build step to examples-integration workflow for workspac…
pyramation Feb 8, 2026
a9bf4dd
chore(ci): remove all paths-ignore and build filter hacks; rename tes…
pyramation Feb 8, 2026
fd0f8e2
chore: remove redundant codegen options (already defaults)
pyramation Feb 8, 2026
5c0b123
refactor(codegen): remove dead maxFieldDepth code and enforce trailin…
pyramation Feb 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/workflows/examples-integration.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Examples Integration
on:
pull_request:
branches: [ main, v1 ]
paths:
- 'examples/**'
- 'graphql/codegen/**'
workflow_dispatch:

jobs:
examples-types:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- uses: pnpm/action-setup@v2
with:
version: 10
- run: pnpm install
- name: Build codegen and dependencies
run: pnpm run build
- run: pnpm -r --filter @constructive-io/examples-codegen-integration run test:codegen
144 changes: 81 additions & 63 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,22 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Build & Development Commands

```bash
# Install dependencies
pnpm install

# Build all packages
pnpm build

# Build all packages (dev mode - faster, no optimizations)
pnpm build:dev

# Lint all packages (auto-fix enabled)
pnpm lint

# Clean build artifacts
pnpm clean

# Update dependencies interactively
pnpm deps
pnpm install # Install dependencies
pnpm build # Build all packages
pnpm build:dev # Build all packages (dev mode - faster, no optimizations)
pnpm lint # Lint all packages (auto-fix enabled)
pnpm clean # Clean build artifacts
pnpm deps # Update dependencies interactively (pnpm up -r -i -L)
```

### Per-Package Commands

Navigate to any package directory (e.g., `cd pgpm/cli`) and run:
From any package directory (e.g., `cd pgpm/cli`):

```bash
pnpm build # Build the package
pnpm build # Build the package (uses makage)
pnpm lint # Lint with auto-fix
pnpm test # Run tests
pnpm test # Run tests (Jest)
pnpm test:watch # Run tests in watch mode
pnpm dev # Run in development mode (where available)
```
Expand All @@ -41,54 +30,74 @@ pnpm dev # Run in development mode (where available)
```bash
cd packages/cli
pnpm test -- path/to/test.test.ts
# or with pattern matching:
pnpm test -- --testNamePattern="test name pattern"
```

### Publishing

Lerna with independent versioning and conventional commits. Publishing only from `main` branch:

```bash
npx lerna version # Bump versions
npx lerna publish # Publish to npm
```

## Project Architecture

This is a **pnpm monorepo** using Lerna for versioning/publishing. The workspace is organized into domain-specific directories:
A **pnpm monorepo** with Lerna for versioning. PostgreSQL-first framework: design your database schema, manage it with pgpm, and get a production-ready GraphQL API automatically via PostGraphile.

### Data Flow

```
PostgreSQL (schema + RLS policies, managed by pgpm migrations)
PostGraphile (graphql/server + graphile/* plugins)
GraphQL Schema (auto-generated from database)
graphql/codegen (--react-query mode OR --orm mode)
React Query Hooks or Prisma-like ORM Client
```

### Core Package Groups
### Workspace Groups

| Directory | Purpose |
|-----------|---------|
| `pgpm/` | PostgreSQL Package Manager - CLI, core engine, types |
| `graphql/` | GraphQL layer - server, codegen, React hooks, testing |
| `graphile/` | PostGraphile plugins - filters, i18n, meta-schema, PostGIS |
| `postgres/` | PostgreSQL utilities - introspection, testing, seeding, AST |
| `packages/` | Shared utilities - CLI, ORM, query builder |
| `uploads/` | File streaming - S3, ETags, content-type detection |
| `jobs/` | Job scheduling and worker infrastructure |
| `pgpm/` | PostgreSQL Package Manager - CLI (`pgpm`), core engine, types, env, logger |
| `graphql/` | GraphQL layer - server, codegen, query builder, explorer, AST utilities |
| `graphile/` | PostGraphile plugins - filters, i18n, meta-schema, PostGIS, search, uploads, settings |
| `postgres/` | PostgreSQL utilities - introspection, testing (pgsql-test), seeding, AST, query context |
| `packages/` | Shared utilities - CLI (`cnc`), ORM base, query builder, server utils, client |
| `uploads/` | File streaming - S3/MinIO, ETags, content-type detection, UUID hashing |
| `jobs/` | Knative job scheduling - worker, scheduler, service, functions |
| `functions/` | Knative cloud functions (e.g., send-email-link) |

### Key Packages
### Key Packages & CLIs

**pgpm (PostgreSQL Package Manager)**
- `pgpm/cli` - Main CLI tool (`pgpm` command)
- `pgpm/core` - Migration engine, dependency resolution, deployment
**`pgpm` CLI** (`pgpm/cli`) - PostgreSQL Package Manager. Commands: `init`, `add`, `deploy`, `revert`, `verify`, `plan`, `install`, `export`, `docker`, `dump`, `tag`. Manages SQL migrations in Sqitch-compatible format with dependency resolution.

**GraphQL Stack**
- `graphql/server` - Express + PostGraphile API server
- `graphql/codegen` - SDK generator (React Query hooks or Prisma-like ORM)
- `graphql/query` - Fluent GraphQL query builder
**`cnc` CLI** (`packages/cli`, binary: `cnc` or `constructive`) - Full dev toolkit. Commands: `server` (start PostGraphile), `explorer` (GraphiQL UI), `codegen` (generate SDK), `get-graphql-schema`, `jobs`, `context`, `auth`, `execute`.

**Testing Infrastructure**
- `postgres/pgsql-test` - Isolated PostgreSQL test environments with transaction rollback
- `graphile/graphile-test` - GraphQL testing utilities
**`graphql/codegen`** - Generates type-safe clients from GraphQL schema or endpoint:
- `--react-query` mode: TanStack Query v5 hooks with query key factories
- `--orm` mode: Prisma-like fluent API with `InferSelectResult<T, S>` type inference, discriminated union error handling (`.unwrap()`, `.unwrapOr()`)
- Sources: GraphQL endpoint URL, .graphql schema file, or direct database introspection

### Testing Pattern
**`graphql/server`** - Express + PostGraphile. Supports multi-endpoint routing via subdomain/host detection (schema builder with app-public/auth/admin sub-endpoints). Uses `LISTEN/NOTIFY` for schema cache invalidation.

Tests use `pgsql-test` for database testing with per-test transaction rollback:
**`graphile/graphile-settings`** - Centralizes all PostGraphile plugin config: connection filters, full-text search, PostGIS, i18n, meta-schema, many-to-many, search, upload plugin. Single `getGraphileSettings(opts)` entry point.

```typescript
import { getConnections } from 'pgsql-test';
**`packages/query-builder`** - Fluent SQL query builder for SELECT/INSERT/UPDATE/DELETE with JOINs, WHERE, GROUP BY. Schema-qualified tables.

let db, teardown;
### Testing Infrastructure

beforeAll(async () => {
({ db, teardown } = await getConnections());
});
**`postgres/pgsql-test`** - Isolated PostgreSQL test environments with per-test transaction rollback:

```typescript
import { getConnections } from 'pgsql-test';
let db, teardown;
beforeAll(async () => ({ db, teardown } = await getConnections()));
beforeEach(() => db.beforeEach());
afterEach(() => db.afterEach());
afterAll(() => teardown());
Expand All @@ -100,26 +109,35 @@ test('example', async () => {
});
```

**`graphile/graphile-test`** - GraphQL testing with PostGraphile snapshot support.

### Job System

Background jobs use Knative: jobs are added to `app_jobs.jobs` table → `knative-job-worker` polls and picks up → POSTs to Knative function URL → function executes (e.g., send email) → returns status.

### Database Configuration

Tests require PostgreSQL. Standard PG environment variables:
- `PGHOST` (default: localhost)
- `PGPORT` (default: 5432)
- `PGUSER` (default: postgres)
- `PGPASSWORD` (default: password)
Tests require PostgreSQL. Standard PG env vars:
- `PGHOST` (default: localhost), `PGPORT` (default: 5432)
- `PGUSER` (default: postgres), `PGPASSWORD` (default: password)

For S3/MinIO tests: `MINIO_ENDPOINT`, `AWS_ACCESS_KEY`, `AWS_SECRET_KEY`, `AWS_REGION`

### Build System
## Build System

- Uses `makage` for TypeScript compilation (handles both CJS and ESM output)
- Jest with ts-jest for testing
- ESLint with TypeScript support
- Each package has its own `tsconfig.json` extending root config
- **makage** compiles TypeScript to both CJS and ESM, outputs to `dist/`
- `makage build --dev` for faster dev builds
- Some packages use `copyfiles` for non-TS assets (SQL files, templates)
- Jest with `ts-jest` preset per-package (`jest.config.js` in each package)

### Code Conventions
## Code Conventions

- TypeScript with `strict: true` (but `strictNullChecks: false`)
- Target: ES2022, Module: CommonJS
- Packages publish to npm from `dist/` directory
- TypeScript with `strict: true` but `strictNullChecks: false`
- Target: ES2022, Module: CommonJS, ModuleResolution: node
- 2-space indent, single quotes, semicolons required, no trailing commas
- Imports auto-sorted by `simple-import-sort`, unused imports auto-removed
- `@typescript-eslint/no-explicit-any`: allowed (turned off)
- Unused var pattern: prefix with `_` (e.g., `_unused`)
- Workspace dependencies use `workspace:^` protocol
- Packages publish from `dist/` directory
- GraphQL pinned to `15.10.1` via overrides
1 change: 1 addition & 0 deletions examples/codegen-integration/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
src/generated/
14 changes: 14 additions & 0 deletions examples/codegen-integration/codegen.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { defineConfig } from "@constructive-io/graphql-codegen";

export default defineConfig({
endpoint: "http://example.local/graphql", // not used for fixture run
output: "src/generated",
reactQuery: true,
orm: true,
codegen: {
maxFieldDepth: 2,
skipQueryField: true
},
// Use the example schema fixtures baked into the repo
schemaFile: "../../graphql/codegen/examples/example.schema.graphql"
});
24 changes: 24 additions & 0 deletions examples/codegen-integration/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "@constructive-io/examples-codegen-integration",
"version": "0.0.0",
"private": true,
"scripts": {
"codegen": "tsx scripts/codegen-runner.ts",
"test:types": "pnpm run codegen && tsc --noEmit",
"test:codegen": "pnpm run codegen"
},
"dependencies": {
"@0no-co/graphql.web": "^1.2.0",
"@tanstack/react-query": "^5.90.20",
"gql-ast": "workspace:^",
"graphql": "15.10.1",
"react": "^19.2.3",
"react-dom": "^19.2.3"
},
"devDependencies": {
"@constructive-io/graphql-codegen": "workspace:^",
"@constructive-io/graphql-types": "workspace:^",
"tsx": "^4.20.3",
"typescript": "^5.1.6"
}
}
22 changes: 22 additions & 0 deletions examples/codegen-integration/scripts/codegen-runner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import path from 'path';
import { generate } from '../../../graphql/codegen/src/core/generate';

const root = path.resolve(__dirname, '..');

async function run() {
const result = await generate({
schemaFile: path.resolve(root, '../../graphql/codegen/examples/example.schema.graphql'),
output: path.resolve(root, 'src/generated'),
reactQuery: true,
orm: true
});

if (!result.success) {
console.error(result.message);
process.exit(1);
}

console.log(result.message);
}

run();
2 changes: 2 additions & 0 deletions examples/codegen-integration/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Placeholder file so tsc has something to include
export {};
14 changes: 14 additions & 0 deletions examples/codegen-integration/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "Bundler",
"strict": true,
"jsx": "react-jsx",
"skipLibCheck": true,
"noEmit": true,
"baseUrl": ".",
"paths": {}
},
"include": ["src", "codegen.config.ts"]
}
2 changes: 1 addition & 1 deletion functions/send-email-link/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"build:dev": "makage build --dev"
},
"devDependencies": {
"makage": "^0.1.10"
"makage": "^0.1.12"
},
"dependencies": {
"@constructive-io/knative-job-fn": "workspace:^",
Expand Down
2 changes: 1 addition & 1 deletion functions/simple-email/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"build:dev": "makage build --dev"
},
"devDependencies": {
"makage": "^0.1.10"
"makage": "^0.1.12"
},
"dependencies": {
"@constructive-io/knative-job-fn": "workspace:^",
Expand Down
2 changes: 1 addition & 1 deletion graphile/graphile-cache/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
},
"devDependencies": {
"@types/pg": "^8.16.0",
"makage": "^0.1.10",
"makage": "^0.1.12",
"nodemon": "^3.1.10",
"ts-node": "^10.9.2"
},
Expand Down
2 changes: 1 addition & 1 deletion graphile/graphile-i18n/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"@types/accept-language-parser": "^1.5.4",
"@types/pg": "^8.16.0",
"graphile-test": "workspace:^",
"makage": "^0.1.10",
"makage": "^0.1.12",
"pgsql-test": "workspace:^"
},
"dependencies": {
Expand Down
2 changes: 1 addition & 1 deletion graphile/graphile-many-to-many/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"devDependencies": {
"graphile-test": "workspace:^",
"graphql": "15.10.1",
"makage": "^0.1.10",
"makage": "^0.1.12",
"pgsql-test": "workspace:^",
"postgraphile": "^4.14.1"
}
Expand Down
2 changes: 1 addition & 1 deletion graphile/graphile-meta-schema/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"@graphile-contrib/pg-many-to-many": "^1.0.0",
"graphile-test": "workspace:^",
"graphql-tag": "2.12.6",
"makage": "^0.1.10",
"makage": "^0.1.12",
"pgsql-test": "workspace:^"
},
"dependencies": {
Expand Down
2 changes: 1 addition & 1 deletion graphile/graphile-pg-type-mappings/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"graphile-postgis": "workspace:^",
"graphile-test": "workspace:^",
"graphql-tag": "2.12.6",
"makage": "^0.1.10",
"makage": "^0.1.12",
"pgsql-test": "workspace:^"
},
"dependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"@types/pg": "^8.16.0",
"graphile-test": "workspace:^",
"graphql": "15.10.1",
"makage": "^0.1.10",
"makage": "^0.1.12",
"pg": "^8.17.1",
"pgsql-test": "workspace:^",
"postgraphile": "^4.14.1"
Expand Down
2 changes: 1 addition & 1 deletion graphile/graphile-plugin-connection-filter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"@graphile-contrib/pg-simplify-inflector": "^6.1.0",
"@types/pg": "^8.16.0",
"graphile-test": "workspace:^",
"makage": "^0.1.10",
"makage": "^0.1.12",
"pg": "^8.17.1",
"pgsql-test": "workspace:^"
}
Expand Down
2 changes: 1 addition & 1 deletion graphile/graphile-plugin-fulltext-filter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"devDependencies": {
"graphile-test": "workspace:^",
"graphql": "15.10.1",
"makage": "^0.1.10",
"makage": "^0.1.12",
"pgsql-test": "workspace:^"
}
}
Loading