Skip to content

chore: upgrade to Houdini 2.0 / houdini-svelte 3.0#514

Draft
rbjornstad wants to merge 26 commits into
mainfrom
poc/houdini-upgrade
Draft

chore: upgrade to Houdini 2.0 / houdini-svelte 3.0#514
rbjornstad wants to merge 26 commits into
mainfrom
poc/houdini-upgrade

Conversation

@rbjornstad

@rbjornstad rbjornstad commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Upgrades Houdini from 1.x to 2.0.1 and houdini-svelte from 2.x to 3.0.1.

Key Changes

Houdini 2.0 Migration

  • Non-exhaustive types: Houdini 2.0 adds a { __typename: "non-exhaustive; don't match this" } catch-all variant to every interface/union result type. Used exhaustive() utility and index-based {#each} keys where needed.
  • Flat fragment types: Fragment types on interfaces are now flat objects with nullable type-keyed properties instead of discriminated unions. Added runtime flatten helper in ActivityLogListItem and updated ActivityLogEntry type.
  • Runtime URL config: HoudiniClient no longer accepts url — moved to houdini.config.js (url: '/graphql').
  • Explicit __typename: Houdini 2.0 no longer auto-injects __typename into store values for inline fragments. Added explicitly to queries that rely on it.
  • verbatimModuleSyntax workaround: Disabled in tsconfig due to Houdini codegen bug (emits import {} instead of import type {}). Added TODO to re-enable once fixed upstream.
  • Type assertion for SSE subscription: Added cast for handlers.next due to GraphQLError type mismatch between graphql-sse and Houdini's re-exported type.

Files Changed

  • houdini.config.js — added top-level url: '/graphql', restored forceRunesMode: true
  • tsconfig.json — disabled verbatimModuleSyntax, added isolatedModules
  • package.json / pnpm-lock.yaml — dependency upgrades
  • src/client.ts — type assertion for SSE handlers
  • src/routes/userInfo.gql — explicit __typename
  • src/routes/+layout.svelte, +layout.ts — compatibility fixes
  • src/lib/utils/houdini.ts — new exhaustive() utility
  • src/lib/domain/activity/shared/texts/types.ts — updated ActivityLogEntry for flat fragment types
  • src/lib/domain/list-items/ActivityLogListItem.svelte — runtime flatten for text components
  • Various components — non-exhaustive type fixes

Known Issues

  • Houdini codegen bug: .houdini/graphql/inputs.ts uses import {} instead of import type {} — tracked upstream
  • Other queries using __typename on unions may need explicit __typename added (same pattern as userInfo.gql fix)

Testing

  • pnpm run check passes (0 errors in user code)
  • Dev server runs successfully with nais api proxy
  • Page header renders correctly after explicit __typename fix

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Upgrades the app’s GraphQL toolchain to Houdini 2.0.x / houdini-svelte 3.0.x and applies the required migration changes across routes and UI components (non-exhaustive variants, flat interface-fragment shapes, explicit __typename, and updated type imports).

Changes:

  • Bumped Houdini + related dependencies and adjusted build/runtime configuration (Houdini config URL, TS compiler flags, workspace pnpm settings, Docker base image).
  • Updated queries/components to handle Houdini 2.0’s non-exhaustive union/interface variants and masking behavior (more inline-fragment field selection, exhaustive() helper, index keys in {#each} where needed).
  • Refactored issue/activity log UI code to work with flat interface-fragment result shapes and Houdini runtime types.

Reviewed changes

Copilot reviewed 69 out of 72 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tsconfig.json Disables verbatimModuleSyntax (workaround for Houdini codegen) and enables isolatedModules.
src/routes/userInfo.gql Adds explicit __typename on me selection.
src/routes/team/[team]/valkey/create/+page.svelte Switches Houdini $houdini-generated route props typing to SvelteKit $types.
src/routes/team/[team]/valkey/+page.ts Moves filter type import to $houdini/graphql/inputs.
src/routes/team/[team]/unleash/+page.svelte Replaces local GraphQLError type with houdini/runtime’s GraphQLError.
src/routes/team/[team]/settings/service_accounts/[serviceAccountID]/token/create/+page.svelte Switches to $types props typing.
src/routes/team/[team]/settings/service_accounts/[serviceAccountID]/binding/add/+page.svelte Switches to $types props typing.
src/routes/team/[team]/settings/confirm_delete/+page.svelte Uses QueryResult from houdini/runtime instead of $houdini.
src/routes/team/[team]/settings/+page.svelte Uses QueryResult from houdini/runtime instead of $houdini.
src/routes/team/[team]/secrets/+page.ts Moves filter type import to $houdini/graphql/inputs.
src/routes/team/[team]/repositories/+page.ts Moves filter type import to $houdini/graphql/inputs.
src/routes/team/[team]/postgres/+page.ts Moves filter type import to $houdini/graphql/inputs.
src/routes/team/[team]/opensearch/create/+page.svelte Switches to $types props typing.
src/routes/team/[team]/opensearch/+page.ts Moves filter type import to $houdini/graphql/inputs.
src/routes/team/[team]/members/AddMember.svelte Moves input type import to $houdini/graphql/inputs.
src/routes/team/[team]/kafka/+page.ts Moves filter type import to Houdini inputs (note: currently uses .js extension).
src/routes/team/[team]/jobs/+page.ts Moves filter type import to $houdini/graphql/inputs.
src/routes/team/[team]/issues/+page.ts Moves filter type import to $houdini/graphql/inputs.
src/routes/team/[team]/configs/+page.ts Moves filter type import to $houdini/graphql/inputs.
src/routes/team/[team]/buckets/+page.ts Moves filter type import to $houdini/graphql/inputs.
src/routes/team/[team]/bigquery/+page.ts Moves filter type import to $houdini/graphql/inputs.
src/routes/team/[team]/applications/+page.ts Moves filter type import to $houdini/graphql/inputs.
src/routes/team/[team]/alerts/query.gql Duplicates fields into the concrete inline fragment selections for masked typing.
src/routes/team/[team]/alerts/PrometheusAlarmDetail.svelte Moves ValueOf to houdini/runtime.
src/routes/team/[team]/alerts/+page.ts Moves filter type import to $houdini/graphql/inputs.
src/routes/team/[team]/activity-log/+page.ts Moves filter type import to $houdini/graphql/inputs.
src/routes/team/[team]/[env]/valkey/[valkey]/edit/+page.svelte Switches to $types props typing.
src/routes/team/[team]/[env]/valkey/[valkey]/edit/+page.server.ts Moves input type import to $houdini/graphql/inputs.
src/routes/team/[team]/[env]/valkey/[valkey]/delete/+page.svelte Switches to $types props typing.
src/routes/team/[team]/[env]/postgres/[postgres]/delete/+page.svelte Switches to $types props typing.
src/routes/team/[team]/[env]/opensearch/[opensearch]/edit/+page.svelte Switches to $types props typing and reorders imports.
src/routes/team/[team]/[env]/opensearch/[opensearch]/edit/+page.server.ts Moves input type import to $houdini/graphql/inputs.
src/routes/team/[team]/[env]/opensearch/[opensearch]/delete/+page.svelte Switches to $types props typing.
src/routes/team/[team]/[env]/job/[job]/logs/query.gql Reworks log destination selections for Houdini 2.0 masking/non-exhaustive behavior.
src/routes/team/[team]/[env]/job/[job]/logs/JobLogs.svelte Replaces manual $props() typing with generated $result type.
src/routes/team/[team]/[env]/job/[job]/issues/+page.ts Moves filter type import to $houdini/graphql/inputs.
src/routes/team/[team]/[env]/job/[job]/activity-log/+page.ts Moves filter type import to $houdini/graphql/inputs.
src/routes/team/[team]/[env]/app/[app]/utilization/query.gql Adjusts interface inline fragments to include needed shared fields per variant.
src/routes/team/[team]/[env]/app/[app]/utilization/+page.svelte Uses new exhaustive() helper and updates field access from aliased shapes.
src/routes/team/[team]/[env]/app/[app]/resize/+page.svelte Switches to $types props typing.
src/routes/team/[team]/[env]/app/[app]/logs/Logs.svelte Uses generated $result type and switches {#each} keys to indexes for safety.
src/routes/team/[team]/[env]/app/[app]/issues/+page.ts Moves filter type import to $houdini/graphql/inputs.
src/routes/team/[team]/[env]/app/[app]/image/+page.svelte Switches to $types props typing.
src/routes/team/[team]/[env]/app/[app]/activity-log/+page.ts Moves filter type import to $houdini/graphql/inputs.
src/routes/deployments/+page.ts Moves filter type import to $houdini/graphql/inputs.
src/routes/admin/userSyncLog/query.gql Refactors inline fragments for masking (but currently omits __typename).
src/routes/admin/userSyncLog/+page.svelte Uses exhaustive() and index keys for iteration over union/interface results.
src/routes/admin/teams/+page.ts Moves filter type import to $houdini/graphql/inputs.
src/routes/admin/service_accounts/[serviceAccountID]/token/create/+page.svelte Switches to $types props typing.
src/routes/admin/service_accounts/[serviceAccountID]/binding/add/+page.svelte Switches to $types props typing.
src/routes/admin/+layout.svelte Switches to $types props typing.
src/routes/+layout.svelte Switches to $types props typing.
src/lib/utils/houdini.ts Adds exhaustive() + Exhaustive<T> helper for Houdini non-exhaustive variants.
src/lib/domain/vulnerability/SuppressFinding.svelte Moves ValueOf to houdini/runtime.
src/lib/domain/vulnerability/BulkSuppressCVE.svelte Moves ValueOf to houdini/runtime.
src/lib/domain/list-items/IssueListItem.svelte Updates issue fragment handling for flat interface-fragment types.
src/lib/domain/list-items/DeploymentWithTeamListItem.svelte Moves ValueOf to houdini/runtime.
src/lib/domain/list-items/DeploymentListItem.svelte Moves ValueOf to houdini/runtime.
src/lib/domain/list-items/ActivityLogListItem.svelte Adds runtime flattening to adapt flat interface fragment data for text components.
src/lib/domain/issues/CriticalIssueRow.svelte Updates issue discrimination logic for flat interface-fragment types.
src/lib/domain/activity/TeamActivityCard.svelte Moves ActivityLogFilter input type to $houdini/graphql/inputs.
src/lib/domain/activity/shared/texts/types.ts Refactors ActivityLogEntry<T> typing to match flat type-keyed fragment shape.
src/lib/domain/activity/shared/texts/PostgresDeletedActivityLogEntryText.svelte Broadens prop typing to ActivityLogEntryFragment$data to fit new fragment shape.
src/lib/domain/activity/shared/texts/DefaultText.svelte Broadens prop typing to ActivityLogEntryFragment$data to fit new fragment shape.
src/client.ts Removes per-client URL config and adds a type assertion for SSE handler compatibility.
src/app.d.ts Adds global GraphQLErrorExtensions.code typing.
pnpm-workspace.yaml Updates pnpm workspace build allowances and minimum release age exclusions for Houdini packages.
package.json Updates dependency versions, including Houdini 2.0.1 / houdini-svelte 3.0.1.
pnpm-lock.yaml Lockfile updates corresponding to dependency upgrades.
houdini.config.js Sets url: '/graphql' and adjusts plugin config for new Houdini/houdini-svelte behavior.
Dockerfile Switches base image from Alpine to the default Node image.
AGENTS.md Documents Houdini 2.0 migration rules (non-exhaustive types + interface fragments).

Comment thread src/routes/team/[team]/kafka/+page.ts Outdated
Comment thread src/routes/admin/userSyncLog/query.gql
Comment thread src/routes/admin/userSyncLog/query.gql
Comment thread src/routes/admin/userSyncLog/query.gql
Comment thread src/lib/domain/list-items/IssueListItem.svelte
Comment thread src/lib/domain/issues/CriticalIssueRow.svelte

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 69 out of 72 changed files in this pull request and generated 2 comments.

Comment thread src/routes/team/[team]/[env]/job/[job]/logs/query.gql
Comment thread src/routes/admin/userSyncLog/+page.svelte Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 69 out of 72 changed files in this pull request and generated 4 comments.

Comment thread src/routes/team/[team]/[env]/app/[app]/utilization/query.gql
Comment thread src/routes/team/[team]/[env]/app/[app]/logs/Logs.svelte Outdated
Comment thread pnpm-workspace.yaml
Comment thread houdini.config.js

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 72 out of 75 changed files in this pull request and generated 3 comments.

Comment thread src/lib/domain/list-items/ActivityLogListItem.svelte
Comment thread package.json
Comment thread houdini.config.js
@rbjornstad rbjornstad force-pushed the poc/houdini-upgrade branch from c4bb46f to 5b3c979 Compare June 29, 2026 14:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 72 out of 74 changed files in this pull request and generated 3 comments.

Comment on lines +202 to +206
const enumLike = activeTypeName
.replace(/Issue$/, '')
.replace(/([a-z])([A-Z])/g, '$1_$2')
.toUpperCase();
return issueTypeLabel(typeName);
return issueTypeLabel(enumLike);
Comment thread package.json
Comment on lines +42 to +43
"houdini": "2.0.2",
"houdini-svelte": "3.0.1",
Comment thread AGENTS.md
Comment on lines +258 to +266
1. **No `__typename`** — use the type-keyed nullable properties as discriminators:

```typescript
// Wrong — __typename doesn't exist on the flat fragment type
if ($data.__typename === 'DeprecatedIngressIssue') { ... }

// Correct — check the nullable type-keyed property
if ($data.DeprecatedIngressIssue) { ... }
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants