How to use AWS Amplify with Sapper? - amazon-web-services

My goal is to use AWS Amplify in a Sapper project.
Creating a Sapper project from scratch (using webpack) then adding AWS Amplify and running it in dev is a success, but run it in production throws a GraphQL error in the console (Uncaught Error: Cannot use e "__Schema" from another module or realm).
Fixing this error thows another one (Uncaught ReferenceError: process is not defined).
A solution is to upgrade GraphQL from 0.13.0 to 14.0.0 unfortunatly GraphQL 0.13.0 is an AWS Amplify API dependency.
Does anyone know what can be done to get AWS Amplify work with Sapper in production ?
The link to the repo containing the source files is located here: https://github.com/ehemmerlin/sapper-aws-amplify
(Apologies for the long post but I want to be explicit)
Detailled steps
1/ Create a Sapper project using webpack (https://sapper.svelte.dev).
npx degit "sveltejs/sapper-template#webpack" my-app
cd my-app
yarn install
2/ Add AWS Amplify (https://serverless-stack.com/chapters/configure-aws-amplify.html) and lodash
yarn add aws-amplify
yarn add lodash
3/ Configure AWS Amplify (https://serverless-stack.com/chapters/configure-aws-amplify.html)
Create src/config/aws.js config file containing (change the values with yours but works as is for the purpose of this post):
export default {
s3: {
REGION: "YOUR_S3_UPLOADS_BUCKET_REGION",
BUCKET: "YOUR_S3_UPLOADS_BUCKET_NAME"
},
apiGateway: {
REGION: "YOUR_API_GATEWAY_REGION",
URL: "YOUR_API_GATEWAY_URL"
},
cognito: {
REGION: "YOUR_COGNITO_REGION",
USER_POOL_ID: "YOUR_COGNITO_USER_POOL_ID",
APP_CLIENT_ID: "YOUR_COGNITO_APP_CLIENT_ID",
IDENTITY_POOL_ID: "YOUR_IDENTITY_POOL_ID"
}
};
Add the following code to the existing code in src/client.js:
import config from './config/aws';
Amplify.configure({
Auth: {
mandatorySignIn: true,
region: config.cognito.REGION,
userPoolId: config.cognito.USER_POOL_ID,
identityPoolId: config.cognito.IDENTITY_POOL_ID,
userPoolWebClientId: config.cognito.APP_CLIENT_ID
},
Storage: {
region: config.s3.REGION,
bucket: config.s3.BUCKET,
identityPoolId: config.cognito.IDENTITY_POOL_ID
},
API: {
endpoints: [
{
name: "notes",
endpoint: config.apiGateway.URL,
region: config.apiGateway.REGION
},
]
}
});
4/ Test it
In dev (yarn run dev): it works
In production (yarn run build; node __sapper__/build): it throws an error.
Uncaught Error: Cannot use e "__Schema" from another module or realm.
Ensure that there is only one instance of "graphql" in the node_modules
directory. If different versions of "graphql" are the dependencies of other
relied on modules, use "resolutions" to ensure only one version is installed.
https://yarnpkg.com/en/docs/selective-version-resolutions
Duplicate "graphql" modules cannot be used at the same time since different
versions may have different capabilities and behavior. The data from one
version used in the function from another could produce confusing and
spurious results.
5/ Fix it
Following the given link (https://yarnpkg.com/en/docs/selective-version-resolutions) I added this code to package.json file:
"resolutions": {
"aws-amplify/**/graphql": "^0.13.0"
}
6/ Test it
rm -rf node_modules; yarn install
Throws another error in the console (even in dev mode).
Uncaught ReferenceError: process is not defined
at Module../node_modules/graphql/jsutils/instanceOf.mjs (instanceOf.mjs:3)
at \_\_webpack_require\_\_ (bootstrap:63)
at Module../node_modules/graphql/type/definition.mjs (definition.mjs:1)
at \_\_webpack_require\_\_ (bootstrap:63)
at Module../node_modules/graphql/type/validate.mjs (validate.mjs:1)
at \_\_webpack_require\_\_ (bootstrap:63)
at Module../node_modules/graphql/graphql.mjs (graphql.mjs:1)
at \_\_webpack_require\_\_ (bootstrap:63)
at Module../node_modules/graphql/index.mjs (main.js:52896)
at \_\_webpack_require\_\_ (bootstrap:63)
A fix given by this thread (https://github.com/graphql/graphql-js/issues/1536) is to upgrade GraphQL from 0.13.0 to 14.0.0 unfortunatly GraphQL 0.13.0 is an AWS Amplify API dependency.

When building my project (I'm using npm and webpack), I got this warning,
WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults
for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/
which seems to be related to the schema error, as these posts indicate that the quickest fix for the error is to set NODE_ENV to production in your environment (mode is set to the NODE_ENV environment variable in the webpack config):
https://github.com/aws-amplify/amplify-js/issues/1445
https://github.com/aws-amplify/amplify-js/issues/3963
How to do that:
How to set NODE_ENV to production/development in OS X
How can I set NODE_ENV=production on Windows?
Or you can mess with the webpack config directly:
https://gist.github.com/jmannau/8039787e29190f751aa971b4a91a8901
Unfortunately some posts in those GitHub issues point out the environment variable change might not work out for a packaged app, specifically on mobile.
These posts suggest that disabling the mangler might be the next best solution:
https://github.com/graphql/graphql-js/issues/1182
https://github.com/rmosolgo/graphiql-rails/issues/58
For anyone just trying to get the basic Sapper and Amplify setup going, to reproduce this error or otherwise, I build up mine with:
npm install -g #aws-amplify/cli
npx degit "sveltejs/sapper-template#webpack" my-app
npm install
npm install aws-amplify
npm install lodash (Amplify with webpack seems to need this)
amplify configure
npm run build
amplify init (dev environment, VS Code, javascript, no framework, src directory, __sapper__\build distribution directory, default AWS profile. This generates aws-exports.js.
In src/client.js:
import Amplify from 'aws-amplify';
import awsconfig from './aws-exports';
Amplify.configure(awsconfig);
npm run build

Related

Nextauth deployed on AWS Amplify [next-auth][error][CLIENT_FETCH_ERROR]

I am using NextAuth (Cognito Provider) and it is perfectly working on my local machine but when deployed on AWS Amplify, it keeps giving me [next-auth][error][CLIENT_FETCH_ERROR] https://next-auth.js.org/errors#client_fetch_error Unexpected token '<', "<!DOCTYPE "... is not valid JSON and the request https://mydomain.sample-dev.net/api/auth/session is 404
I have followed the documentation and added the required environment variable below:
Executing command: NEXTAUTH_URL=https://mydomain.sample-dev.net
Executing command: NEXTAUTH_SECRET=TestingSecretKey
Executing command: NEXT_PUBLIC_AUTH_SECRET=TestingSecretKey
my pages/api/auth/[...nextauth].ts is
import NextAuth from 'next-auth/next';
import Cognito from 'next-auth/providers/cognito';
export default NextAuth({
providers: [
Cognito({
clientId: process.env.NEXT_PUBLIC_AUTH_CLIENT_ID!,
clientSecret: process.env.NEXT_PUBLIC_AUTH_CLIENT_SECRET!,
issuer: process.env.NEXT_PUBLIC_AUTH_ISSUER!,
idToken: true,
checks: 'nonce',
}),
],
debug: false,
secret: process.env.NEXTAUTH_SECRET || process.env.NEXT_PUBLIC_AUTH_SECRET,
});
any idea on what am I doing wrong or missing?
The [next-auth][error][CLIENT_FETCH_ERROR] error suggests the NEXTAUTH_URL environment variable is not accessible for use as a result of misconfiguration.
In order to resolve the error, you primarily need to define the required environment variables on your AWS Amplify dashboard.
Proceed by select the affected application under App settings, then click on Environment variables and follow the instructions for that purpose.
Then, click on the Build settings (equally under App settings) menu so as to edit your App build specification script and make the environment variables accessible as illustrated below.
build:
commands:
- echo "NEXTAUTH_URL=$NEXTAUTH_URL" >> .env
- npm run build

Publish artifact to AWS CodeArtifact with sbt

I'm trying to publish artifacts to AWS CodeArtifact using sbt, but I'm having some troubles;
Given an sbt project, running the command sbt publish the package is uploaded to the repo but It remains in the Unfinished state. The AWS CodeArtifact documentation says:
Unfinished: The last attempt to publish did not complete. Currently only Maven package versions can have a status of Unfinished. This can occur when the client uploads one or more assets for a package version but does not publish a maven-metadata.xml file for the package that includes that version.
I'm using sbt at version 1.3.3, I'm not using plugins, the property publishMavenStyle is true.
I know that the sbt-maven-resolver (here the repo) solves the issue, but it seems an "unfollowed plugin", and moreover, using it I lose all logs about the publishing process, I don't trust it.
Did anyone have the same issue and have solved it somehow?
Using CodeArtifact with SBT
Setting up SBT with CodeArtifact
Publishing Packages with SBT (also avoiding the artifact being in Unfinished state.)
1. Setting up SBT with CodeArtifact
Create a CodeArtifact repository with a Maven upstream. For this example we're going to use repository maven-test in domain launchops
Open up the Connection Instructions in the console and choose mvn. We will need information from this later.
Copy the command which exports the "CODEARTIFACT_AUTH_TOKEN" environment variable from the console and run it in your environment. This will set the "CODEARTIFACT_AUTH_TOKEN" to be the password for our repository, the username is always aws.
In the build.sbt file import sbt.Credentials:
import sbt.{Credentials}
Now we need to setup the credentials. To do this we're first going to read the CODEARTIFACT_AUTH_TOKEN environment variable:
val repoPass = sys.env.get("CODEARTIFACT_AUTH_TOKEN").getOrElse("")
Next, we're going to use the previously imported sbt.Credentials to setup a new set of Credentials:
credentials += Credentials("launchops/maven-test", "launchops-123456789012.d.codeartifact.us-east-1.amazonaws.com", "aws", repoPass)
The values passed to the Credentials object are ("domain-name/repository-name", "repository hostname without protocol", "username", "password"), with username always being aws and password coming from the repoPass variable we only need to modify the first two to point to our repository.
Now we just need to instruct SBT to use our repository as a resolver. The consoles connection instructions will generate Maven settings, for example:
<repository>
<id>launchops--maven-test</id>
<url>https://launchops-123456789012.d.codeartifact.us-east-1.amazonaws.com/maven/maven-test/</url>
</repository>
We will use these values to create a resolver in our build.sbt file:
resolvers += "launchops--maven-test" at "https://launchops-123456789012.d.codeartifact.us-east-1.amazonaws.com/maven/maven-test"
The format of this is "resolvers += "ID From maven configuration in console" at "Repository URL from maven configuration in console".
To completely disable the use of public Maven repositories (Force CodeArtifact usage) you can add the following line to the build.sbt file:
externalResolvers := Resolver.combineDefaultResolvers(resolvers.value.toVector, mavenCentral = false)
After performing these setups steps you should be able to run sbt update and observe packages being downloaded through CodeArtifact.
Sample build.sbt for reference:
import sbt.{Credentials, Path}
name := "scala-test"
version := "0.3.0"
scalaVersion := "2.12.6"
organization := "com.abc.def"
val repoPass = sys.env.get("CODEARTIFACT_AUTH_TOKEN").getOrElse("")
credentials += Credentials("launchops/maven-test", "launchops-123456789012.d.codeartifact.us-east-1.amazonaws.com", "aws", repoPass)
resolvers += "launchops--maven-test" at "https://launchops-123456789012.d.codeartifact.us-east-1.amazonaws.com/maven/maven-test"
libraryDependencies ++= Seq(
"org.scalatest" %% "scalatest" % "3.0.0" % "test",
"io.nats" % "jnats" % "2.0.0",
"org.json4s" %% "json4s-native" % "3.6.0"
)
2. Publishing Packages
Apart from pulling dependencies, SBT can also be used to publish packages. To have SBT publish to CodeArtifact we first need to set it up in the build.sbt file:
Add the following to the file:
publishMavenStyle := true
publishTo := Some("launchops--maven-test" at "https://launchops-123456789012.d.codeartifact.us-east-1.amazonaws.com/maven/maven-test")
At this point, technically, running sbt publish will push the package to CodeArtifact, however it will end up in Unfinished state. We need to make use of sbt-maven-resolver plugin to help get the package in the correct format: https://github.com/sbt/sbt-maven-resolver
In the project/plugins.sbt file add the following line:
addSbtPlugin("org.scala-sbt" % "sbt-maven-resolver" % "0.1.0")
Now you can run sbt publish and have the package publish to CodeArtifact successfully. If you see an error make sure that you are using a recent version of SBT.
You can achieve the same without using the sbt-maven-resolver plugin by following shariqmaws' answer without the plugin.
The publish will result in an artifact in "unpublished" state.
Then use the aws codeartifact cli to publish it (https://docs.aws.amazon.com/codeartifact/latest/ug/maven-curl.html)

Google Cloud Build error no project active

I am trying to set up Google Cloud Build with a really simple project hosted on firebase, but every time it reaches the deploy stage it tells me:
Error: No project active, but project aliases are available.
Step #2: Run firebase use <alias> with one of these options:
ERROR: build step 2 "gcr.io/host-test-xxxxx/firebase" failed: step exited with non-zero status: 1
I have set the alias to production and my .firebasesrc is:
{
"projects": {
"default": "host-test-xxxxx",
"production": "host-test-xxxxx"
}
I have firebase admin and API Keys Admin permissions on my cloud builder service and I also want to encrypt so I have Cloud KMS CryptoKey Decrypter
I do
firebase login:ci
to generate a token in my terminal and paste this to my .env variable, then generate an alias called production and do
firebase use production
My yaml is:
steps:
# Install
- name: 'gcr.io/cloud-builders/npm'
args: ['install']
# Build
- name: 'gcr.io/cloud-builders/npm'
args: ['run', 'build']
# Deploy
- name: 'gcr.io/host-test-xxxxx/firebase'
args: ['deploy']
and install and build work fine. What is happening here?
Rerunning firebase init does not seem to help.
Update:
building locally then doing firebase deploy does not help either.
Ok the thing that worked was changing the .firebasesrc file to:
{
"projects": {
"default": "host-test-xxxxx"
}
}
and
firebase use --add
and adding an alias called default.

How do i continue working with Amplify on a new machine?

I'm using react native for my project. On my old machine, when i ran amplify status, i had Auth, Api and Storage services listed.
I moved to my new machine, installed node, watchman, brew etc... and then navigated to my react native project and ran: react-native run-ios, and voila, my app is running. All the calls to my AWS Api, Auth and Storage are working perfectly.
Now i can make some amplify commands. Such as amplify status. I tried: amplify env add: here's what i got:
Users-MBP-2:projectname username$ amplify env add
Note: It is recommended to run this command from the root of your app directory
? Do you want to use an existing environment? Yes
? Choose the environment you would like to use: dev
Using default provider awscloudformation
✖ There was an error initializing your environment.
init failed
Error: ENOENT: no such file or directory, open '/Users/username/.aws/credentials'
at Object.openSync (fs.js:462:3)
at Proxy.readFileSync (fs.js:364:35)
at Object.readFileSync (/usr/local/lib/node_modules/#aws-amplify/cli/node_modules/aws-sdk/lib/util.js:95:26)
at IniLoader.parseFile (/usr/local/lib/node_modules/#aws-amplify/cli/node_modules/aws-sdk/lib/shared-ini/ini-loader.js:6:47)
at IniLoader.loadFrom (/usr/local/lib/node_modules/#aws-amplify/cli/node_modules/aws-sdk/lib/shared-ini/ini-loader.js:56:30)
at Config.region (/usr/local/lib/node_modules/#aws-amplify/cli/node_modules/aws-sdk/lib/node_loader.js:100:36)
at Config.set (/usr/local/lib/node_modules/#aws-amplify/cli/node_modules/aws-sdk/lib/config.js:507:39)
at Config.<anonymous> (/usr/local/lib/node_modules/#aws-amplify/cli/node_modules/aws-sdk/lib/config.js:342:12)
at Config.each (/usr/local/lib/node_modules/#aws-amplify/cli/node_modules/aws-sdk/lib/util.js:507:32)
at new Config (/usr/local/lib/node_modules/#aws-amplify/cli/node_modules/aws-sdk/lib/config.js:341:19) {
errno: -2,
syscall: 'open',
code: 'ENOENT',
path: '/Users/username/.aws/credentials'
}
Do you think credentials info needs to be brought/configured to my new machine?
When i run amplify configure project it's like doing an amplify init and building a project from scratch. I'm being asked:
? Enter a name for the project: ProjectName
? Choose your default editor: Visual Studio Code
? Choose the type of app that you're building javascript
Please tell us about your project
? What javascript framework are you using (Use arrow keys)
angular
ember
ionic
react
❯ react-native
vue
none
etc....
I also already have a region, username and accessKey, secretAccess key etc..
I do not want to replace or ruin anything in my current backend or current project! Whats going on?
Ensure amplify-cli is installed and you're logged in with your AWS details.
npm install -g #aws-amplify/cli
amplify configure
Running amplify configure is mainly to give the cli knowledge of your AWS account so subsequent commands can have access to things.
If you get amplify: command not found errors try restarting your terminal. If still no luck, you will need to check amplify has been added to your PATH variable.
Run amplify env add , but choose an existing environment. This will let you choose the environment you created on your other machine so you can pull those settings down to your new machine.
amplify env add
? Do you want to use an existing environment? Yes
Production
Follow up with:
amplify pull
You don't need to run amplify add auth again or anything. All of that will pull down automatically after you've done the above.
You DO NOT need to do all config again, but some for sure
You have to install amplify cli npm install -g #aws-amplify/cli
use amplify pull
https://docs.amplify.aws/cli/start#amplify-pull
Follow the rest of steps -
-- provide the accessKeyId, secretAccessKey
-- region
-- select amplify project
and then rest of app related thing like IDE, directory......
I tried every solution then I found this. (in MacBook)
% sudo -i
Password:
~ root# npm install -g #aws-amplify/cli
-- Ctrl+D to exist from Root user
% amplify pull --appId xxxx --envName yyyy.
Note: To get --appId xxxx --envName yyyy
Log in to the AWS console. Choose AWS Amplify. Click your app. Go to Backend
environments. Find the backend environment you wish to pull. Click
Edit backend. See top right then click 'Local setup instructions
' ( amplify pull --appId
YOUR_APP_ID --envName YOUR_ENV_NAME )
Waiting until it request to verify your amplify.
✔ Successfully received Amplify Studio tokens.
? Choose your default editor: Visual Studio Code
? Choose the type of app that you're building javascript
Please tell us about your project
? What javascript framework are you using react
? Source Directory Path: src
? Distribution Directory Path: build
? Build Command: npm run-script build
? Start Command: npm run-script start
✔ Synced UI components.
? Do you plan on modifying this backend? Yes
⠴ Building resource api/xxxx✅ GraphQL schema compiled successfully.
Edit your schema at ....
✔ Successfully pulled backend environment yyyy from the cloud.
✅
Successfully pulled backend environment staging from the cloud.
Run 'amplify pull' to sync future upstream changes.
% amplify pull
% npm install
% npm start
Hope this help every one!!
Happy Coding :)

How to setup Sentry to AWS lambda functions? Many errors

Trying to setup Sentry to a service with lambda functions - AWS.
I have followed the instructions on serverless-sentry-lib and it works for local environment but not for prod.
1-Have installed raven and serverless-sentry-lib
npm install --save raven
npm install --save serverless-sentry-lib
Basically this is what I have in my serverless.yml:
provider:
environment:
# SLS_DEBUG:"*"
SENTRY_ENVIRONMENT: "${opt:stage, self:provider.stage}"
SENTRY_DSN: "https://xxxxxx#sentry.io/xxxxxx"
plugins:
- serverless-delete-loggroups
- serverless-plugin-typescript
- serverless-plugin-existing-s3
# - serverless-sentry
- serverless-sentry-lib
# - serverless-plugin-optimize
And this is how I send the error:
myFunction.ts
import * as Raven from 'raven';
Raven.config('https://xxxxxxxx#sentry.io/xxxxxxx').install();
That code works good in Local but when I try to push to Serverless AWS lambda I get the follow error:
Serverless: s3 --> initiate requests ...
Error --------------------------------------------------
... Unable to validate the following destination configurations
For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable.
Checking this post and setting SLS_DEBUG to "*":
SLS_DEBUG:"*"
SENTRY_ENVIRONMENT: "${opt:stage, self:provider.stage}"
SENTRY_DSN: "https://xxxxxx#sentry.io/xxxxxx"
And I still have the same error. It did not disappear.
Does someone have any clue what is going on wit this settings?