I have a cyclic dependency issue, but, I feel like...
# help
s
I have a cyclic dependency issue, but, I feel like the deploy for this would work. Since the cloudformation distribution is created, then the custom resource for the next site replaces the template string. The issue is just that a token for auth node, and a token for site node both need to exist before either takes a dependency on the other. Is there any clever way to bind this?
Cyclic dependency is between site and auth
f
oh hmm.. thinking..
s
Oh, sorry, fixed with this:
Copy code
const customResourceProps: CognitoCustomResource = {
      service: 'CognitoIdentityServiceProvider',
      action: 'updateUserPoolClient',
      physicalResourceId: PhysicalResourceId.of(
        'UniqueIdentityReference-000100'
      ),
      parameters: {
        ClientId: String(auth.cognitoUserPoolClient?.userPoolClientId),
        UserPoolId: String(auth.cognitoUserPool?.userPoolId),
        CallbackURLs: [
          `https://${site.cfDistribution.distributionDomainName}/api/auth/callback/cognito`,
        ],
        LogoutURLs: [`https://${site.cfDistribution.distributionDomainName}`],
      },
    };

    // Replace OAuth callback URLs
    new AwsCustomResource(this, 'API1', {
      onCreate: customResourceProps,
      onUpdate: customResourceProps,
      policy: AwsCustomResourcePolicy.fromSdkCalls({
        resources: AwsCustomResourcePolicy.ANY_RESOURCE,
      }),
    });
Not the nicest but worked for this use case
f
Ah through a custom resource to replace the callback urls?
s
Yeah
Next one is trickier though, need to use the url of the cloudfront distribution in an env var
Copy code
// Deploy the next JS Site
    const site = new sst.NextjsSite(this, 'Site', {
      path: 'src/frontend/site',
      environment: {
        // site ? this ? difficult one
        NEXTAUTH_URL: `https://${site.cfDistribution.distributionDomainName}`,
      },
    });
Maybe needs a callback function that would pass in the construct and allow accessing the internal readonly props
Copy code
// Deploy the next JS Site
    const site = new sst.NextjsSite(this, 'Site', {
      path: 'src/frontend/site',
      environment: {
        // site ? this ? difficult one
        NEXTAUTH_URL: (self: Construct) => `https://${self.cfDistribution.distributionDomainName}`,
      },
    });
Is this possible?
f
Oh nice, thats pretty smart 🤓
Lemme do some quick digging and see if CDK has any recommendations for working around this type of provlems
s
Bumping this one, not sure if you have had any thoughts. Vercel expose the following, which cannot be configured: https://vercel.com/docs/concepts/projects/environment-variables#system-environment-variables If the custom resource did something similar, where system environment variables could be mapped to custom names, I think that would fit my usecase
f
Hey @Simon Reilly sorry about slowing getting back to this.
interesting.. do you mean we can automatically set things like the distribution url as a default environment variable for NextjsSite?
s
I think that is one option. Vercel allows you to select their system env vars from a drop down and point your own variable name at them.
I took a look at the NextJSSite construct. Because of the dependency tree it is complex to know the distribution URL of cloudformation, before the deploy of the updated code. One thought is to do the cfnDistribution deploy, and custom domain, then perform the edge lambda deploy and additional behaviour deploy, so the URL can be known. Or some kind of second lambda code update, after the distribution is deployed. There's probably a few options
I gave this a try, based on the docs touting that you can add behaviours after creation.
Lambda@Edge functions can also be associated with additional behaviors, either at or after Distribution creation time.
I got a circular dependency, which to me means, addBehavior is just updating the distribution node, not creating a custom resource that modifies it after deploy â˜šī¸
f
Hey Simon, I gave this some thoughts, would this work?
Copy code
const site = new sst.NextjsSite(this, 'Site', {
      path: 'src/frontend/site',
      environment: {
        NEXTAUTH_URL: sst.NextjsSite.DISTRIBUTION_DOMAIN_NAME,
      },
    });
Essentially NextjsSite provides a bunch of static constants
s
Yeah, that would be ace 👍 Do you have some implementation ideas? Just curious 😄