Skip to content

feat: add @pgpmjs/migrate-client workspace package for typed Migrate API access#824

Open
pyramation wants to merge 1 commit intomainfrom
devin/1773568362-migrate-client-workspace
Open

feat: add @pgpmjs/migrate-client workspace package for typed Migrate API access#824
pyramation wants to merge 1 commit intomainfrom
devin/1773568362-migrate-client-workspace

Conversation

@pyramation
Copy link
Contributor

@pyramation pyramation commented Mar 15, 2026

feat: add @pgpmjs/migrate-client workspace package

Summary

Adds a new workspace package at sdk/migrate-client/ that provides a typed GraphQL ORM client for the Constructive Migrate API (db_migrate schema). This package will be consumed by pgpm/core to replace ~1,300 lines of handwritten GraphQL boilerplate in the export flow (on the feature/pgpm-export-graphql branch).

Package contents:

  • schemas/migrate.graphql — static copy of the db_migrate GraphQL schema from constructive-db
  • Generated ORM models: SqlActionModel, MigrateFileModel (findMany/findFirst/create/update/delete)
  • Generated mutations: executeSql, runMigration
  • scripts/generate.ts — regeneration script using @constructive-io/graphql-codegen (devDep only)

Runtime dependencies are minimal: gql-ast, @0no-co/graphql.web, @constructive-io/graphql-types, graphql. No codegen dependency at runtime.

This PR also adds @pgpmjs/migrate-client as a workspace:^ dependency in pgpm/core/package.json, but no code in pgpm/core imports it yet — the actual usage will land via the export PR on feature/pgpm-export-graphql.

Review & Testing Checklist for Human

  • ORM code was copied, not locally generated. The pnpm generate script requires graphile-connection-filter (transitive codegen dep) which wasn't available in the build environment. The committed ORM files were copied from constructive-db's existing generated output. Verify that pnpm generate works in a fully-configured environment and produces identical output.
  • Schema drift. sdk/migrate-client/schemas/migrate.graphql is a one-time copy from constructive-db. If the upstream db_migrate schema changes, this file must be manually re-copied and pnpm generate re-run. Consider whether an automated sync is warranted.
  • Lock file diff is large but cosmetic. The pnpm-lock.yaml diff is ~90% YAML formatting changes (brace style). The substantive additions are only the sdk/migrate-client importer block and the @pgpmjs/migrate-client link in pgpm/core. Spot-check for unexpected dependency changes.
  • Build verification. Run pnpm build from workspace root — sdk/migrate-client and pgpm/core should both compile cleanly. Note: concurrent workspace builds can race (migrate-client's dist gets deleted while core compiles); building migrate-client first avoids this.

Notes


Open with Devin

…API access

- Create sdk/migrate-client/ with typed ORM client generated from migrate.graphql schema
- Models: SqlActionModel, MigrateFileModel with findMany/findFirst/create/update/delete
- Mutations: executeSql, runMigration
- Zero codegen runtime deps (gql-ast, @0no-co/graphql.web, @constructive-io/graphql-types)
- Add pnpm generate script for future regeneration via @constructive-io/graphql-codegen
- Add @pgpmjs/migrate-client as workspace dependency in pgpm/core
@devin-ai-integration
Copy link
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

Copy link
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 6 potential issues.

View 4 additional findings in Devin Review.

Open in Devin Review

name?: string | null;
databaseId?: string | null;
deploy?: string | null;
deps?: string | null;
Copy link
Contributor

Choose a reason for hiding this comment

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

🔴 SqlAction.deps typed as string instead of string[], mismatching the GraphQL schema [String]

The GraphQL schema defines deps: [String] (an array of strings) on the SqlAction type (sdk/migrate-client/schemas/migrate.graphql:277), but the generated TypeScript entity type at line 246 declares deps?: string | null (a single scalar string). This means when the ORM client receives an array of dependency strings from the server, the TypeScript type will be wrong — consumers will treat it as a single string when it's actually an array, leading to runtime data handling bugs (e.g., iterating characters instead of array items).

Suggested change
deps?: string | null;
deps?: string[] | null;
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

name?: string | null;
databaseId?: string | null;
deploy?: string | null;
deps?: string | null;
Copy link
Contributor

Choose a reason for hiding this comment

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

🔴 SqlActionPatch.deps typed as string instead of string[], will send wrong data shape on update

The GraphQL schema's SqlActionPatch input defines deps: [String] (sdk/migrate-client/schemas/migrate.graphql:1206), but the generated TypeScript at line 446 declares deps?: string | null. This means update mutations will send a scalar string for deps instead of an array, which the GraphQL server will reject or misinterpret. Note that CreateSqlActionInput at line 432 correctly uses deps?: string[], making this inconsistency more confusing.

Suggested change
deps?: string | null;
deps?: string[] | null;
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

name?: StringFilter;
databaseId?: UUIDFilter;
deploy?: StringFilter;
deps?: StringFilter;
Copy link
Contributor

Choose a reason for hiding this comment

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

🔴 SqlActionFilter.deps uses StringFilter instead of StringListFilter, mismatching the GraphQL schema

The GraphQL schema declares the deps filter field as StringListFilter (sdk/migrate-client/schemas/migrate.graphql:363), which provides array-specific operations like contains, overlaps, anyEqualTo, etc. However, the generated TypeScript type at line 330 uses StringFilter instead. This means users can't use array-aware filter operations (e.g., checking if deps contains a specific value), and any StringFilter operations sent (like includes, startsWith) will be rejected by the server since it expects StringListFilter fields.

Suggested change
deps?: StringFilter;
deps?: StringListFilter;
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +454 to +460
nameTrgmSimilarity?: number | null;
deployTrgmSimilarity?: number | null;
contentTrgmSimilarity?: number | null;
revertTrgmSimilarity?: number | null;
verifyTrgmSimilarity?: number | null;
actionTrgmSimilarity?: number | null;
searchScore?: number | null;
Copy link
Contributor

Choose a reason for hiding this comment

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

🔴 SqlActionPatch includes non-existent computed fields that server will reject

The generated SqlActionPatch type (lines 454-460) includes nameTrgmSimilarity, deployTrgmSimilarity, contentTrgmSimilarity, revertTrgmSimilarity, verifyTrgmSimilarity, actionTrgmSimilarity, and searchScore. These are read-only computed fields on the SqlAction output type, not part of the SqlActionPatch input type in the schema (sdk/migrate-client/schemas/migrate.graphql:1201-1215). If a user sets any of these fields in an update mutation, the server will return a validation error.

Suggested change
nameTrgmSimilarity?: number | null;
deployTrgmSimilarity?: number | null;
contentTrgmSimilarity?: number | null;
revertTrgmSimilarity?: number | null;
verifyTrgmSimilarity?: number | null;
actionTrgmSimilarity?: number | null;
searchScore?: number | null;
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +357 to +360
| 'DATABASE_ID_ASC'
| 'DATABASE_ID_DESC'
| 'UPLOAD_ASC'
| 'UPLOAD_DESC';
Copy link
Contributor

Choose a reason for hiding this comment

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

🟡 MigrateFileOrderBy includes enum values not present in GraphQL schema

The GraphQL schema's MigrateFileOrderBy enum (sdk/migrate-client/schemas/migrate.graphql:247-253) only defines 5 values: NATURAL, PRIMARY_KEY_ASC, PRIMARY_KEY_DESC, ID_ASC, ID_DESC. The generated TypeScript type (lines 351-360) adds 4 extra values (DATABASE_ID_ASC, DATABASE_ID_DESC, UPLOAD_ASC, UPLOAD_DESC) that don't exist in the schema. Using these values in an orderBy clause will cause the GraphQL server to reject the query with a validation error.

Suggested change
| 'DATABASE_ID_ASC'
| 'DATABASE_ID_DESC'
| 'UPLOAD_ASC'
| 'UPLOAD_DESC';
| 'ID_DESC';
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +366 to +390
| 'ID_DESC'
| 'NAME_ASC'
| 'NAME_DESC'
| 'DATABASE_ID_ASC'
| 'DATABASE_ID_DESC'
| 'DEPLOY_ASC'
| 'DEPLOY_DESC'
| 'DEPS_ASC'
| 'DEPS_DESC'
| 'PAYLOAD_ASC'
| 'PAYLOAD_DESC'
| 'CONTENT_ASC'
| 'CONTENT_DESC'
| 'REVERT_ASC'
| 'REVERT_DESC'
| 'VERIFY_ASC'
| 'VERIFY_DESC'
| 'CREATED_AT_ASC'
| 'CREATED_AT_DESC'
| 'ACTION_ASC'
| 'ACTION_DESC'
| 'ACTION_ID_ASC'
| 'ACTION_ID_DESC'
| 'ACTOR_ID_ASC'
| 'ACTOR_ID_DESC'
Copy link
Contributor

Choose a reason for hiding this comment

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

🟡 SqlActionOrderBy includes 20 extra enum values not present in GraphQL schema

The GraphQL schema's SqlActionOrderBy enum (sdk/migrate-client/schemas/migrate.graphql:725-749) defines 23 values, but the generated TypeScript type (lines 361-404) adds 20 extra values (e.g., NAME_ASC, NAME_DESC, DEPS_ASC, DEPS_DESC, PAYLOAD_ASC, PAYLOAD_DESC, CONTENT_ASC, CONTENT_DESC, REVERT_ASC, REVERT_DESC, VERIFY_ASC, VERIFY_DESC, CREATED_AT_ASC, CREATED_AT_DESC, ACTION_ASC, ACTION_DESC, ACTION_ID_ASC, ACTION_ID_DESC, ACTOR_ID_ASC, ACTOR_ID_DESC). Using any of these will cause the GraphQL server to reject the query.

Prompt for agents
In sdk/migrate-client/src/orm/input-types.ts, the SqlActionOrderBy type union (lines 361-404) should only include values that exist in the GraphQL schema's SqlActionOrderBy enum (sdk/migrate-client/schemas/migrate.graphql lines 725-749). Remove these non-existent values: NAME_ASC, NAME_DESC, DEPS_ASC, DEPS_DESC, PAYLOAD_ASC, PAYLOAD_DESC, CONTENT_ASC, CONTENT_DESC, REVERT_ASC, REVERT_DESC, VERIFY_ASC, VERIFY_DESC, CREATED_AT_ASC, CREATED_AT_DESC, ACTION_ASC, ACTION_DESC, ACTION_ID_ASC, ACTION_ID_DESC, ACTOR_ID_ASC, ACTOR_ID_DESC. Keep only: PRIMARY_KEY_ASC, PRIMARY_KEY_DESC, NATURAL, ID_ASC, ID_DESC, DATABASE_ID_ASC, DATABASE_ID_DESC, DEPLOY_ASC, DEPLOY_DESC, NAME_TRGM_SIMILARITY_ASC, NAME_TRGM_SIMILARITY_DESC, DEPLOY_TRGM_SIMILARITY_ASC, DEPLOY_TRGM_SIMILARITY_DESC, CONTENT_TRGM_SIMILARITY_ASC, CONTENT_TRGM_SIMILARITY_DESC, REVERT_TRGM_SIMILARITY_ASC, REVERT_TRGM_SIMILARITY_DESC, VERIFY_TRGM_SIMILARITY_ASC, VERIFY_TRGM_SIMILARITY_DESC, ACTION_TRGM_SIMILARITY_ASC, ACTION_TRGM_SIMILARITY_DESC, SEARCH_SCORE_ASC, SEARCH_SCORE_DESC.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

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.

1 participant