Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Sync codegen behavior implementation - modify and integrate #892

Closed
wants to merge 6 commits into from

Conversation

stocaaro
Copy link
Member

@stocaaro stocaaro commented Oct 8, 2024

Description of changes

This change translates the vendored code for codegen, adapting it so that it isn't async. Steps to adapt the code have been made as simple as possible where complexity is captured in related code to make upgrades as easy as possible as we maintain this. Directions are documented.

  • Document and apply the MAINTENANCE.md adaptations to the @graphql-codegen/core fork
  • Add a bunch of derived types to support sync codegen
  • Add sync preset/plugin implementation
  • Fix test errors caused by how jest hoisting works with mocks

Commits

  1. Copy the @graphql-codegen/core file across
  2. Modify libraries to expose codegenSync behavior

Codegen Paramaters Changed or Added

Adding

const c = codegenSync(...);
// which is the same as
const c = await codegen(...);

Description of how you validated changes

Checklist

  • PR description included
  • yarn test passes
  • Tests are changed or added
  • Relevant documentation is changed or added (and PR referenced)
  • Breaking changes to existing customers are released behind a feature flag or major version update
  • Changes are tested using sample applications for all relevant platforms (iOS/android/flutter/Javascript) that use the feature added/modified
  • Changes are tested on windows. Some Node functions (such as path) behave differently on windows.
  • Changes adhere to the GraphQL Spec and supports the GraphQL types type, input, enum, interface, union and scalar types.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@@ -25,7 +25,7 @@
"@aws-amplify/graphql-docs-generator": "4.2.1",
"@aws-amplify/graphql-generator": "0.4.6",
"@aws-amplify/graphql-types-generator": "3.6.0",
"@graphql-codegen/core": "2.6.6",
"@graphql-codegen/core": "^2.6.6",
Copy link
Member Author

Choose a reason for hiding this comment

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

We had multiple versions in our node_modules, this consolidates down to a single version which makes it easier to detect if we upgrade.

"watch": "tsc -w",
"test": "jest",
"test-watch": "jest --watch",
"extract-api": "ts-node ../../scripts/extract-api.ts"
"extract-api": "ts-node ../../scripts/extract-api.ts",
"check-codegen-version": "bash ./scripts/check-codegen-version.sh"
Copy link
Member Author

Choose a reason for hiding this comment

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

Adding a command that makes sure our vendor code matches our dependency during the build process

For the code forked here most of the complexity of adapting `codegen` to be non-async is captured in type changes surfaced by `@aws-amplify/appsync-modelgen-plugin` as `SyncTypes`. If these base types change when we update the package, our derived types to support Sync execution may need to change as well

These are the steps needed to adapt the `graphql-codegen-core` code to run non-async and adhere to the adapted `SyncTypes`:
Copy link
Member Author

Choose a reason for hiding this comment

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

Following these instructions with the current target version will result in the same diff proposed with this change give or take minor details or points where discretion is involved (such as how to handle resolving options).

Comment on lines +6 to +18
export type SyncPluginMap<Obj extends PluginMapContainer> = Omit<Obj, 'pluginMap'> & {
pluginMap: {
[name: string]: Omit<Obj['pluginMap'][string], 'plugin'> & {
plugin: (
...args: Parameters<Obj['pluginMap'][string]['plugin']>
) => Awaited<ReturnType<Obj['pluginMap'][string]['plugin']>>;
};
};
};

export type SyncCache<Obj extends CacheContainer> = Omit<Obj, 'cache'> & {
cache?: (<T>(namespace: string, key: string, factory: () => T) => T) | undefined
};
Copy link
Member Author

Choose a reason for hiding this comment

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

These two helper types do most of the lifting here. They unwrap the Promise/Await type expectations so that the types can be used for sync versions of the target behavior.

Awaited behavior is used/allowed for:

  • Plugin execution
  • Profilers
  • Caches

test(`basic ${target}`, async () => {
const generators = ['generateModels', 'generateModelsSync'] as const;

async function runGenerator(generator: (typeof generators)[number], options: GenerateModelsOptions) {
Copy link
Member Author

Choose a reason for hiding this comment

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

Rather than have two copies of the tests, here we use a string to run th same tests for both the sync and async versions.

test('does not fail on custom directives', async () => {
const targets: ModelsTarget[] = ['java', 'swift', 'javascript', 'typescript', 'dart', 'introspection'];
targets.forEach(target => {
test(`both generates generate the same basic ${target}`, async () => {
Copy link
Member Author

Choose a reason for hiding this comment

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

Make sure the sync/async behavior is the same and remains the same.

@stocaaro stocaaro closed this Oct 10, 2024
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