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

fix(api-graphql): generate client.models has no properties #12935

Merged
merged 6 commits into from
Feb 7, 2024

Conversation

HuiSF
Copy link
Member

@HuiSF HuiSF commented Feb 1, 2024

Description of changes

Amplify.configure() and generateClient() calls order can be randomly bundled by script bundler when they are located in separate files, as from the code path perspective they don't have a dependent relationship, however, generateClient() is actually depending on Amplify.configure() to get a valid GraphQL provider configuration. To resolve this, this PR added functionality to generateClient as the following:

  • When generateClient gets called, if it can get a valid GraphQL provider configuration, it generates the properties for client.models.
  • Otherwise, it sets up a listener to the core Hub event: configure, when the listener receives a valid GraphQL provider configuration, it generates the properties for client.models. The listener modifies client.models by reference.

Issue #, if available

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)

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

@HuiSF HuiSF requested review from a team as code owners February 1, 2024 17:09
@HuiSF HuiSF requested a review from iartemiev February 1, 2024 17:10
packages/api-graphql/src/internals/generateClient.ts Outdated Show resolved Hide resolved
Comment on lines 41 to 61
if (!config.API?.GraphQL) {
client.models = emptyModels as ModelTypes<never>;
generateModelsPropertyOnAmplifyConfigure<T>(client);
} else {
client.models = generateModelsProperty<T>(
client,
config.API?.GraphQL,
);
}
Copy link
Member

Choose a reason for hiding this comment

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

In the case where we register the listener, it looks like it subscribes to config changes perpetually. I'm curious if this breaks expectations if a customer intends to create a client and then re-configure another one with another API.

On the other hand, if we don't intend to support that pattern, it makes sense to subscribe to config updates either way, IMO:

  1. Generate models, defaulting to empty object if not configured.
  2. Start listening for config changes.

An unlikely edge, I imagine. But I'm eager for clear-cut definition of the intended behavior that reconciles the differences.

@HuiSF HuiSF force-pushed the hui/fix/api-graphql/empty-client-models branch from 65568ef to 3feedac Compare February 2, 2024 22:25
@HuiSF HuiSF requested a review from a team as a code owner February 2, 2024 22:36
@HuiSF HuiSF requested a review from svidgen February 2, 2024 22:42
@HuiSF HuiSF force-pushed the hui/fix/api-graphql/empty-client-models branch from 2589636 to 17e7554 Compare February 5, 2024 17:50
@HuiSF HuiSF force-pushed the hui/fix/api-graphql/empty-client-models branch from 17e7554 to a3f531d Compare February 5, 2024 18:19
iartemiev
iartemiev previously approved these changes Feb 5, 2024
Copy link
Member

@iartemiev iartemiev left a comment

Choose a reason for hiding this comment

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

LGTM. Left 1 nit and 1 question; neither are blocking.

expect(() => {
client.models.Todo.create({ name: 'todo' });
}).toThrow(
'Could not generate client. This is likely due to Amplify.configure() not being called prior to generateClient().',
Copy link
Member

Choose a reason for hiding this comment

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

Nit: could we expand on this error message? It may be a bit confusing since in this example configure was actually called, it's just missing a GraphQL configuration.

Something like: "... This is likely due to Amplify.configure() not being called prior to generateClient() or because the configuration passed to Amplify.configure() is missing GraphQL values"

Comment on lines +97 to +101
get() {
throw new Error(
'Could not generate client. This is likely due to Amplify.configure() not being called prior to generateClient().',
);
},
Copy link
Member

Choose a reason for hiding this comment

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

script bundlers may randomly arrange their orders in the production bundle

Is it possible to have a race condition here, causing the error to get thrown because a customer accesses client.models.* before the configure hub event fired?

For example, I call Amplify.configure() with a valid config in one file and then in another:

const client = generateClient<Schema>();
const data = await client.models.Post.list();

If the bundler arranges the files in such a way that the above snippet gets called first, will the customer see an error thrown?

Copy link
Member Author

Choose a reason for hiding this comment

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

The race condition is going to happen when someone makes back-to-back calls exactly like this at the module level. For calls made at the module level, we would need to do the following in the same file to maintain the order of calls:

Amplify.configure();
const client = generateClient<Schema>();
const data = await client.models.Post.list();

Let's discuss.

Copy link
Member

Choose a reason for hiding this comment

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

Sounds good. Let's summarize in the PR description:

  1. Which usage patterns does this fix resolve?
  2. What are the remaining sharp edges?

Copy link
Member

Choose a reason for hiding this comment

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

Discussed offline. Approving

@iartemiev iartemiev dismissed their stale review February 6, 2024 13:56

Dismissing approval pending discussion

@HuiSF HuiSF merged commit 5e30055 into main Feb 7, 2024
30 checks passed
@HuiSF HuiSF deleted the hui/fix/api-graphql/empty-client-models branch February 7, 2024 20:36
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.

4 participants