Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
29 changes: 17 additions & 12 deletions docs/plan/graphile-v5-migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -296,11 +296,11 @@ These packages exist on `develop-v5` but have no source code (only `dist/` and `

| Package | Complexity | Notes | Priority |
|---------|------------|-------|----------|
| `graphile-pg-type-mappings` | Low | Maps custom PG types (email, url, etc.) to GraphQL scalars | High - should inline into settings |
| `graphile-pg-type-mappings` | Low | Maps custom PG types (email, url, etc.) to GraphQL scalars | **Complete** — inlined as `PgTypeMappingsPreset` |
| `graphile-postgis` | High | PostGIS types and filters | Medium |
| `graphile-i18n` | Medium | Language/locale support | Low |
| `graphile-upload-plugin` | Medium | File upload handling | Low |
| `graphile-search-plugin` | Medium | Search functionality | Low |
| `graphile-search-plugin` | Medium | Search functionality | **Complete** — merged to develop-v5 |
| `graphile-plugin-connection-filter-postgis` | High | PostGIS filter operators (depends on graphile-postgis) | Medium |
| `graphile-plugin-fulltext-filter` | Medium | Full-text search filters | Low |
| `graphile-sql-expression-validator` | Low | SQL expression validation | Low |
Expand All @@ -313,11 +313,11 @@ These packages exist on `develop-v5` but have no source code (only `dist/` and `
4. **Phase 5d:** Meta schema (`MetaSchemaPreset`) - **DONE**
5. **Phase 5e:** Many-to-many (community v5 plugin) - **DONE**
6. **Phase 5f:** Tsvector codec (`TsvectorCodecPreset`) - **DONE**
7. **Phase 5g:** PG type mappings (inline into settings) - **TODO**
7. **Phase 5g:** PG type mappings (inlined as `PgTypeMappingsPreset`) - **DONE**
8. **Phase 5h:** PostGIS (requires full port) - **TODO**
9. **Phase 5i:** i18n (requires full port) - **TODO**
10. **Phase 5j:** Upload (requires full port) - **TODO**
11. **Phase 5k:** Search (requires full port) - **TODO**
11. **Phase 5k:** Search (merged to develop-v5) - **DONE**

## Phase 6: Test Migration

Expand Down Expand Up @@ -364,17 +364,21 @@ describe.skip('Server integration tests', () => {
3. **Server tests** - Skip initially, re-enable incrementally
4. **Plugin tests** - Use `@constructive-io/graphql-test` with ConstructivePreset

## Phase 7: Codegen Updates
## Phase 7: Codegen Updates

### 7.1 Update `graphql/codegen`
### 7.1 Update `graphql/codegen` — **COMPLETE**

The codegen package uses PostGraphile introspection to generate types. This needs to be updated to use v5's introspection API.
The codegen package has been fully migrated to v5. It now uses standard GraphQL introspection (no `_meta` dependency) and generates ORM-first output with React Query hooks delegating to ORM contracts. See `graphql/codegen/docs/V5-HANDOVER.md` for full details.

**Reference:** `graphile repo's packages/codegen`
Key results:
- 230 unit tests pass, 75 snapshots
- `findOne` collection fallback for `NoUniqueLookupPreset` schemas
- `selection` API for hooks with strict typing and contextual autocomplete
- Search/fulltext entities handled generically via Connection detection

### 7.2 Codegen Migration Details
### 7.2 Codegen Migration Details (Historical)

The current codegen (`graphql/codegen`) uses v4-based schema building via `buildSchemaSDLFromDatabase`. This needs to be updated to use v5's `makeSchema()` with `ConstructivePreset`.
The original codegen (`graphql/codegen`) used v4-based schema building via `buildSchemaSDLFromDatabase`. This has been replaced with standard introspection that works with any v5 preset.

**Current v4 approach (graphql/codegen/src/core/introspect/source/database.ts):**
```typescript
Expand Down Expand Up @@ -477,18 +481,19 @@ const introspection = introspectionFromSchema(schema);
- [x] graphile-plugin-connection-filter (using community package)

#### Packages requiring v5 port
- [ ] graphile-pg-type-mappings (high priority - inline into settings)
- [x] graphile-pg-type-mappings (inlined as `PgTypeMappingsPreset`)
- [ ] graphile-postgis
- [ ] graphile-i18n
- [ ] graphile-upload-plugin
- [ ] graphile-search-plugin
- [x] graphile-search-plugin (merged to develop-v5)
- [ ] graphile-plugin-connection-filter-postgis
- [ ] graphile-plugin-fulltext-filter
- [ ] graphile-sql-expression-validator

### Phase 7: Re-enable
- [x] Re-enable middleware (api.ts refactored to use direct SQL)
- [x] Re-enable tests (server-test passing)
- [x] Codegen v5 migration complete (230 tests, ORM + React Query verified)
- [ ] Full integration testing

## Key API Differences (v4 vs v5)
Expand Down
117 changes: 117 additions & 0 deletions docs/plan/graphql-codegen-v5-migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# GraphQL Codegen PostGraphile v5 Migration Plan

## Goal
Migrate `graphql/codegen` to be fully compatible with PostGraphile v5 on branch `develop-v5`, while using `main` as the source-of-truth baseline for codegen architecture and behavior.

## Scope
- In scope:
- `graphql/codegen` only
- Validation against the v5-compatible backend in `packages/server` on `develop-v5`
- Out of scope:
- Refactoring other packages in this pass
- Reworking `packages/server` internals (already migrated by backend work)

## Key Constraints
- Baseline for codegen must come from `main`, not existing `develop-v5` codegen state.
- PostGraphile v5 server contract lives in `packages/server` on `develop-v5`.
- ORM and React Query output modes must both pass verification.
- Keep the current architectural direction:
- React Query output mode delegates to ORM runtime core
- Strong TypeScript correctness and autocomplete behavior are mandatory

## Branch Strategy
1. Start from `origin/develop-v5`.
2. Create a dedicated migration branch on top (e.g. `feat/codegen-v5-on-develop-v5`).
3. Replace `graphql/codegen` contents with `origin/main` version (explicit override baseline).
4. Apply only required v5 compatibility patches on top.

## Migration Workstreams

### 1) Baseline Override ✅
- Copy `graphql/codegen` from `main` into the new branch.
- Keep all non-codegen files from `develop-v5` unchanged.
- Resolve lockfile/package drift only where needed for codegen build/test.

### 2) GraphQL 16 / AST Compatibility ✅
- Ensure GraphQL operation/kind enum usage is compatible with v5/GraphQL 16 expectations.
- Audit and patch any remaining string-literal AST node usages that break typing/runtime.
- Confirm template-copied runtime files are also compatible (especially query-builder template paths).

### 3) Codegen-to-Server Contract Alignment (v5) ✅
- Remove v4-only assumptions in codegen DB schema build calls.
- Align schema-fetch/introspection behavior with v5 server exposure.
- Verify source mode behavior:
- endpoint-based codegen
- schema-file codegen
- db-backed codegen (where applicable)

### 4) `findOne` Refactor for v5 Unique Lookup Changes ✅
- Problem:
- v5 preset usage may remove unique/single lookup query fields.
- Required behavior:
- Generated `findOne` API remains available for consumers.
- Internally it must not depend on dedicated single-row GraphQL query fields.
- Planned approach:
- Build `findOne` via collection query + filter + `first: 1`, then map first node/null.
- Make table metadata/query-name typing reflect optional absence of single query field.
- Ensure custom operation separation logic does not assume single query existence.

### 5) Type System and DX Safeguards ✅
- Preserve the current selection-first API and strict select validation.
- Keep React Query options pass-through behavior distinct from GraphQL selection args.
- Re-validate overload signatures and inference behavior for nested selection autocomplete.
- Ensure no regressions in ORM-generated types and RQ-generated hook signatures.

## Verification Matrix

### A. Unit/Snapshot/Type Tests (`graphql/codegen`)
- Run package tests and snapshot updates as needed.
- Add/adjust tests for:
- no-single-query schema scenarios
- `findOne` fallback behavior
- strict select typing and nested autocomplete constraints
- React Query option typing interplay with selection args

### B. Integration Against v5 Backend (`packages/server`)
- On `develop-v5`, spin up v5 backend from `packages/server` for local endpoint testing.
- Generate code from live endpoint and verify:
- ORM output compiles and runtime smoke tests pass
- React Query output compiles and hook typechecks pass

### C. Downstream Dependents of Codegen
- Verify direct dependents that consume generated outputs and/or CLI path:
- `packages/cli`
- `examples/codegen-integration`
- local test app package used for codegen validation in this repo (if present on branch)

## Suggested Commit Slicing
1. `chore(codegen): override develop-v5 codegen with main baseline`
2. `fix(codegen): align graphql16 and v5 schema build contracts`
3. `refactor(codegen): decouple findOne from single-query fields`
4. `test(codegen): add v5 unique-lookup and type safety coverage`
5. `docs(codegen): document v5 assumptions and migration notes`

## Risks and Mitigations
- Risk: Hidden assumptions about unique lookup fields in generated runtime.
- Mitigation: explicit no-single-query tests + endpoint integration checks.
- Risk: GraphQL 16 AST typing/runtime mismatch in template-generated files.
- Mitigation: audit both generator code and copied templates.
- Risk: Regressions in selection/autocomplete behavior.
- Mitigation: keep strict type tests and nested-selection inference tests as merge gates.

## Post-Migration Hardening

Completed after all 5 workstreams:
- Removed stale `--browserCompatible` CLI option from `packages/cli`
- Updated all `_meta` references to "standard introspection" in comments/docstrings
- Marked legacy v4 exports (`QueryBuilder`, `MetaObject`, generators) as `@deprecated`
- Added search/fulltext entity detection test coverage
- Added multi-entity `findOne` collection fallback test (NoUniqueLookupPreset scenario)
- Post-rebase verification: 230 tests pass, 75 snapshots, build clean

## Definition of Done
- ✅ `graphql/codegen` baseline from `main` is active on top of `develop-v5`.
- ✅ Codegen builds/tests/typechecks pass (230 tests, 75 snapshots).
- ✅ Endpoint-based generation against local `packages/server` v5 instance succeeds.
- ✅ ORM and React Query outputs both pass compile + type-level verification.
- ✅ No unresolved contract gaps between generated code and v5 backend schema shape.
32 changes: 32 additions & 0 deletions graphql/codegen/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Code Generation Rules

## 1. Only AST-based code generation

All per-schema/per-table code generation MUST use Babel AST (`@babel/types` + `generateCode()`).
Never use `lines.push()`, string concatenation, or template literals to build generated TypeScript code.

Reference implementations:
- `src/core/codegen/orm/model-generator.ts` — per-table ORM model classes
- `src/core/codegen/orm/client-generator.ts` — createClient factory
- `src/core/codegen/orm/custom-ops-generator.ts` — custom query/mutation operations

## 2. Never any string-based concatenation

No `lines.push(...)`, no backtick template literals containing code, no string `+` operators
for building generated source files. If you find yourself writing `lines.push(\`import ...\`)`,
stop and use `t.importDeclaration(...)` instead.

## 3. Giant templates must be actual files that get copied

Static runtime code that does not vary per-schema belongs in `src/core/codegen/templates/`
as real `.ts` files. These are read at codegen time via `readTemplateFile()` and written
to the output directory with only the header replaced.

This gives you:
- Syntax highlighting and IDE support while editing templates
- A clear boundary between "code that generates code" and "code that IS the output"

Reference implementations:
- `src/core/codegen/templates/orm-client.ts`
- `src/core/codegen/templates/query-builder.ts`
- `src/core/codegen/templates/select-types.ts`
27 changes: 27 additions & 0 deletions graphql/codegen/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,33 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

# [3.3.0](https://github.com/constructive-io/constructive/compare/@constructive-io/graphql-codegen@3.2.1...@constructive-io/graphql-codegen@3.3.0) (2026-02-09)

### Bug Fixes

- **codegen-cli:** honor source flags and config overrides ([4fac2c1](https://github.com/constructive-io/constructive/commit/4fac2c18346c9cd24a6d6fb213b4ef29d21854e8))
- **codegen:** convert string concatenation to Babel AST and template-copy patterns ([d2e7480](https://github.com/constructive-io/constructive/commit/d2e748028fa4e1271cb35e1366a1018f1ad957b9))
- **codegen:** prune stale generated files ([1534338](https://github.com/constructive-io/constructive/commit/15343383668467b4461a86b183c527b7362973b2))

### Features

- **codegen:** add fire-and-forget overload for delete hooks (clientMutationId default) ([6cce350](https://github.com/constructive-io/constructive/commit/6cce350b4e8079e10de87751621c4a16561f41f9))
- **graphql-codegen:** unify ORM and RQ selection core ([b5eb861](https://github.com/constructive-io/constructive/commit/b5eb861201bca561c0604b6e3e74ee3689a25da7))

## [3.2.1](https://github.com/constructive-io/constructive/compare/@constructive-io/graphql-codegen@3.2.0...@constructive-io/graphql-codegen@3.2.1) (2026-02-02)

**Note:** Version bump only for package @constructive-io/graphql-codegen

# [3.2.0](https://github.com/constructive-io/constructive/compare/@constructive-io/graphql-codegen@3.1.4...@constructive-io/graphql-codegen@3.2.0) (2026-01-29)

### Features

- **codegen:** add getHeaders callback for dynamic request headers ([374a91d](https://github.com/constructive-io/constructive/commit/374a91d4b4413c290ee7cd9cb433f7f14d38e4be))

## [3.1.4](https://github.com/constructive-io/constructive/compare/@constructive-io/graphql-codegen@3.1.3...@constructive-io/graphql-codegen@3.1.4) (2026-01-28)

**Note:** Version bump only for package @constructive-io/graphql-codegen

## [3.1.3](https://github.com/constructive-io/constructive/compare/@constructive-io/graphql-codegen@3.1.2...@constructive-io/graphql-codegen@3.1.3) (2026-01-27)

**Note:** Version bump only for package @constructive-io/graphql-codegen
Expand Down
59 changes: 25 additions & 34 deletions graphql/codegen/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,6 @@ interface GraphQLSDKConfigTarget {
// Generator flags
reactQuery?: boolean; // Generate React Query hooks (output: {output}/hooks)
orm?: boolean; // Generate ORM client (output: {output}/orm)
browserCompatible?: boolean; // Generate browser-compatible code (default: true)
// Set to false for Node.js with localhost DNS fix

// Table filtering (for CRUD operations from _meta)
tables?: {
Expand Down Expand Up @@ -661,7 +659,7 @@ Filter patterns support wildcards:

The CLI provides a convenient way to run code generation from the command line.

### `graphql-sdk generate`
### `graphql-codegen`

Generate React Query hooks and/or ORM client from various sources.

Expand All @@ -682,62 +680,55 @@ Database Options (for pgpm modes):
Generator Options:
--react-query Generate React Query hooks
--orm Generate ORM client
-t, --target <name> Target name in config file
-o, --output <dir> Output directory
-t, --target <name> Target name (for multi-target configs)
-a, --authorization <token> Authorization header value
--browser-compatible Generate browser-compatible code (default: true)
Set to false for Node.js with localhost DNS fix
--skip-custom-operations Only generate table CRUD operations
--dry-run Preview without writing files
--keep-db Keep ephemeral database after generation (pgpm modes)
-v, --verbose Show detailed output

Watch Mode Options:
-w, --watch Watch for schema changes and regenerate
--poll-interval <ms> Polling interval in milliseconds (default: 5000)
--debounce <ms> Debounce delay in milliseconds (default: 500)
--touch <path> Touch file after regeneration
--no-clear Don't clear console on regeneration
--keep-db Keep ephemeral database after generation (pgpm modes)
-h, --help Show help message
--version Show version number
```

Examples:

```bash
# Generate React Query hooks from an endpoint
npx graphql-sdk generate --endpoint https://api.example.com/graphql --output ./generated --react-query
npx @constructive-io/graphql-codegen --endpoint https://api.example.com/graphql --output ./generated --react-query

# Generate ORM client from an endpoint
npx graphql-sdk generate --endpoint https://api.example.com/graphql --output ./generated --orm
npx @constructive-io/graphql-codegen --endpoint https://api.example.com/graphql --output ./generated --orm

# Generate both React Query hooks and ORM client
npx graphql-sdk generate --endpoint https://api.example.com/graphql --output ./generated --react-query --orm
npx @constructive-io/graphql-codegen --endpoint https://api.example.com/graphql --output ./generated --react-query --orm

# Generate from a PGPM module
npx graphql-sdk generate --pgpm-module-path ./packages/my-module --schemas public --react-query
# Generate from schema file
npx @constructive-io/graphql-codegen --schema-file ./schema.graphql --output ./generated --react-query

# Generate using apiNames for automatic schema discovery
npx graphql-sdk generate --pgpm-module-path ./packages/my-module --api-names my_api --react-query --orm
```
# Generate from database with schemas
npx @constructive-io/graphql-codegen --schemas public,app_public --output ./generated --react-query

### `graphql-sdk init`
# Generate from database with API names
npx @constructive-io/graphql-codegen --api-names my_api --output ./generated --orm

Create a configuration file.
# Use config file
npx @constructive-io/graphql-codegen --config ./graphql-codegen.config.ts

```bash
Options:
-f, --format <format> Config format: ts, js, json (default: ts)
-o, --output <path> Output path for config file
# Generate specific target from multi-target config
npx @constructive-io/graphql-codegen --config ./graphql-codegen.config.ts --target admin
```

### `graphql-sdk introspect`
### Using with Constructive CLI

Inspect schema without generating code.
The `@constructive-io/cli` package includes the codegen command:

```bash
Options:
-e, --endpoint <url> GraphQL endpoint URL
--json Output as JSON
-v, --verbose Show detailed output
# Install Constructive CLI
npm install -g @constructive-io/cli

# Run codegen via cnc
cnc codegen --endpoint http://localhost:5555/graphql --output ./codegen --react-query
```

## Architecture
Expand Down
Loading