-
Notifications
You must be signed in to change notification settings - Fork 189
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: Support apiId(Multiple cloudformation stacks) #597
base: master
Are you sure you want to change the base?
Conversation
src/resources/Api.ts
Outdated
} | ||
// if ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You might have forgotten to remove this comment.
@HumbleBeck I have the same need, first thank you for your work and this is already helping me.
And I'm getting this error in the other stacks:
Checkking the generated CF and getting on all the resolvers Do you think you can have a look at it? Or am I doing something wrong? |
hey @Hideman85, indeed, I think I've missed this part thank you Just pushed a commit, it should fix it. |
@@ -2,9 +2,9 @@ import { CfnWafRuleStatement, IntrinsicFunction } from './cloudFormation'; | |||
|
|||
export type AppSyncConfig = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If most of the parameters are ignored when using apiId you should define type like this to avoid misusage of the config, it can be nice for those who use this type in their serverless.ts:
export type BaseAppSyncConfig = {
dataSources: Record<string, DataSourceConfig>;
resolvers: Record<string, ResolverConfig>;
pipelineFunctions: Record<string, PipelineFunctionConfig>;
substitutions?: Substitutions;
caching?: CachingConfig;
};
export type NewAppSyncConfig = BaseAppSyncConfig & {
name: string;
schema: string[];
authentication: Auth;
additionalAuthentications: Auth[];
domain?: DomainConfig;
apiKeys?: Record<string, ApiKeyConfig>;
xrayEnabled?: boolean;
logging?: LoggingConfig;
waf?: WafConfig;
tags?: Record<string, string>;
};
export type ExistingAppSyncConfig = BaseAppSyncConfig & {
apiId: string | IntrinsicFunction;
};
export type AppSyncConfig = NewAppSyncConfig | ExistingAppSyncConfig;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree on this and it joins what I commented earlier.
The same should happen in the validation json schema.
I would use something like a union.
export type BaseAppSyncConfig = {
dataSources: Record<string, DataSourceConfig>;
resolvers: Record<string, ResolverConfig>;
pipelineFunctions: Record<string, PipelineFunctionConfig>;
substitutions?: Substitutions;
caching?: CachingConfig;
};
export type FullAppSyncConfig = BaseAppSyncConfig & {
name: string;
schema: string[];
authentication: Auth;
additionalAuthentications: Auth[];
domain?: DomainConfig;
apiKeys?: Record<string, ApiKeyConfig>;
xrayEnabled?: boolean;
logging?: LoggingConfig;
waf?: WafConfig;
tags?: Record<string, string>;
};
export type SharedAppSyncConfig = BaseAppSyncConfig & {
apiId: string;
};
export type AppSyncConfig = FullAppSyncConfig | SharedAppSyncConfig
(not tested, might need adjustments)
Thanks all for the great feedback and this PR I will take everything into consideration and have a look at this as soon as I can |
@bboure Sorry to disturb you, have you considered merging this fix for now? Right now I'm using the fork in our flow and this add quite some overhead in our process. This would be awesome to have this released 🙏 |
@bboure +1 for getting this merged in. my use case is that I have a large AppSync API with v1 of this plugin. we are upgrading to v2 and, at the same time, splitting the API into "services" and using thank you @HumbleBeck for the awesome work 🙏 |
Sorry, I'll try to have a look at this over the weekend. Meanwhile, AWS released support for merged APIs. I would like to have a look at it too I think both are probably good to support but I'd like to understand how they fit together, etc. Thanks for the work and your patience |
@bboure OH WOW 😲 I did not hear about the new "merged API" functionality. AppSync finally has a solution for "schema federation" like Apollo. I'm going to have to dig into the blog post over the weekend. Totally agree that it would be great to support both. |
hey @bboure -- sorry to bug you again 😅 wondering if you were able to put some thought toward this PR or if you had a different approach in mind. |
> Note: you should never specify this parameter if you're managing your AppSync through this plugin since it results in removing your API. | ||
|
||
### Schema | ||
After specifying this parameter, you need to manually keep your schema up to date or from the main stack where your root AppSync API is defined. The plugin is not taking into account schema property due to AppSync limitation and inability to merge schemas across multiple stacks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This whole section is confusing and probably not necessary.
Instead, we should add clear guidelines on how and why you should use the apiId
parameters.
A bit like described here for API Gateway.
@@ -410,6 +421,10 @@ class ServerlessAppsyncPlugin { | |||
async getIntrospection() { | |||
const apiId = await this.getApiId(); | |||
|
|||
if (typeof apiId !== 'string') { | |||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just returning is probably not good enough.
I would show a warning.
In fact I would probably not allow calling any of these commands (assoc domain, etc) from a "child" service stack.
Please call this command from the service where the AppSync API is created.
@@ -377,6 +384,10 @@ class ServerlessAppsyncPlugin { | |||
async gatherData() { | |||
const apiId = await this.getApiId(); | |||
|
|||
if (typeof apiId !== 'string') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (typeof apiId !== 'string') { | |
if (!apiId) { |
if for some reason, apiId
is an empty string, it probably does not make sense to continue either.
- waf | ||
- tags | ||
`); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd just validate this.
i.e. don't allow these fields is present in the config along with apiId
The validator will take care of showing the warning/error (depending on configuration)
endpointResource.Properties, | ||
this.compileAuthenticationProvider(this.config.authentication), | ||
); | ||
if (this.config.authentication) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
authentication
is always required in this context.
There is probably some TS magic to do (i.e. a type union type or something)
} | ||
|
||
hasPipelineFunction(name: string) { | ||
return name in this.config.pipelineFunctions; | ||
return name in (this.config.pipelineFunctions || {}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand why you made those optional, but I'd rather keep them as required.
If you look here, those are actually already optional from a config point of view.
Then, getAppSyncConfig()
makes sure to fill them with empty {}
if needed for when it's injected in the compiler.
@@ -2,9 +2,9 @@ import { CfnWafRuleStatement, IntrinsicFunction } from './cloudFormation'; | |||
|
|||
export type AppSyncConfig = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree on this and it joins what I commented earlier.
The same should happen in the validation json schema.
I would use something like a union.
export type BaseAppSyncConfig = {
dataSources: Record<string, DataSourceConfig>;
resolvers: Record<string, ResolverConfig>;
pipelineFunctions: Record<string, PipelineFunctionConfig>;
substitutions?: Substitutions;
caching?: CachingConfig;
};
export type FullAppSyncConfig = BaseAppSyncConfig & {
name: string;
schema: string[];
authentication: Auth;
additionalAuthentications: Auth[];
domain?: DomainConfig;
apiKeys?: Record<string, ApiKeyConfig>;
xrayEnabled?: boolean;
logging?: LoggingConfig;
waf?: WafConfig;
tags?: Record<string, string>;
};
export type SharedAppSyncConfig = BaseAppSyncConfig & {
apiId: string;
};
export type AppSyncConfig = FullAppSyncConfig | SharedAppSyncConfig
(not tested, might need adjustments)
}, | ||
required: ['name', 'authentication'], | ||
required: ['name'], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
as mentioned above, we should have 2 schemas: one for a usual appsync config (main api or single stack) and one for "external API" which only accepts supporters fields.
This way, authentication
can remain required in single stack scenarios or for main stack and be "forbidden" for sub stacks
Thank you for your patience, I had a look at the PR. It looks good but I left some comments for improvements. Espscially on typing and validation. A few more thoughts/questions:
The same goes for pipeline functions.
Thank you all for the effort! |
cc: @HumbleBeck ☝️ Check out the comments left on the PR. |
@bboure I can volunteer to help with this part.
my vote on this is no, because as you said, passing the name as-is works. also sharing the same data source between stacks smells like an anti-pattern (unless using single-table design with DynamoDB, which I have not seen people do when using AppSync) |
I am interested in this feature, I'd vote yes for the DynamoDB single tables, I feel like this is a very important use case |
Hey guys, Thanks for waiting. I was occupied with chores. I'll review the comments by EOW. Meanwhile, can I ask you, @morficus, to help me with documentation/guide? I'll drop this part from my PR. |
I'm really interested in this feature! we can't update our library until this is finished. Just out of curiosity, @HumbleBeck were you able to move forward with your PR? Thanks a lot everyone for the great effort! |
@HumbleBeck +1 for getting this merged in. |
What is the status of this @HumbleBeck ? |
@bboure @HumbleBeck did this fell under the table? I don't know if I can help somehow, besides having no knowledge at all |
Closes #595