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

Attempting to use Amplify in an Appsync Typescript custom handler not working #13982

Open
3 tasks done
mmixan opened this issue Nov 2, 2024 · 3 comments
Open
3 tasks done
Labels
feature-request Request a new feature GraphQL Related to GraphQL API issues pending-maintainer-response Issue is pending a response from the Amplify team.

Comments

@mmixan
Copy link

mmixan commented Nov 2, 2024

Before opening, please confirm:

JavaScript Framework

Next.js

Amplify APIs

GraphQL API

Amplify Version

v6

Amplify Categories

auth, api

Backend

Amplify Gen 2

Environment information

# Put output below this line
System:
    OS: Windows 11 10.0.26100
    CPU: (32) x64 13th Gen Intel(R) Core(TM) i9-13900HX
    Memory: 13.22 GB / 31.70 GB
  Binaries:
    Node: 20.5.1 - C:\Program Files\nodejs\node.EXE
    npm: 9.8.0 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Chromium (130.0.2849.46)
    Internet Explorer: 11.0.26100.1882
  npmPackages:
    %name%:  0.1.0 
    @ampproject/toolbox-optimizer:  undefined ()
    @aws-amplify/backend: ^1.2.1 => 1.2.2 
    @aws-amplify/backend-cli: ^1.2.6 => 1.2.7 
    @aws-amplify/ui-react: ^6.1.13 => 6.5.3 
    @aws-amplify/ui-react-internal:  undefined ()
    @aws-amplify/ui-react-server:  undefined ()
    @babel/core:  undefined ()
    @babel/runtime:  7.22.5
    @edge-runtime/cookies:  4.0.2
    @edge-runtime/ponyfill:  2.4.1
    @edge-runtime/primitives:  4.0.2
    @hapi/accept:  undefined ()
    @mswjs/interceptors:  undefined ()
    @napi-rs/triples:  undefined ()
    @next/font:  undefined ()
    @next/react-dev-overlay:  undefined ()
    @nextui-org/button: 2.0.38 => 2.0.38
    @nextui-org/code: 2.0.33 => 2.0.33
    @nextui-org/input: 2.2.5 => 2.2.5
    @nextui-org/kbd: 2.0.34 => 2.0.34
    @nextui-org/link: 2.0.35 => 2.0.35
    @nextui-org/listbox: 2.1.27 => 2.1.27
    @nextui-org/navbar: 2.0.37 => 2.0.37
    @nextui-org/snippet: 2.0.43 => 2.0.43
    @nextui-org/switch: 2.0.34 => 2.0.34
    @nextui-org/system: 2.2.6 => 2.2.6
    @nextui-org/theme: 2.2.11 => 2.2.11
    @opentelemetry/api:  undefined ()
    @react-aria/ssr: 3.9.4 => 3.9.4 (3.9.6)
    @react-aria/visually-hidden: 3.8.12 => 3.8.12
    @stylistic/eslint-plugin-js: ^2.8.0 => 2.9.0
    @testing-library/jest-dom: ^6.6.2 => 6.6.2
    @testing-library/react: ^16.0.1 => 16.0.1
    @testing-library/user-event: ^14.5.2 => 14.5.2
    @types/http-errors: ^2.0.4 => 2.0.4
    @types/node: 20.5.7 => 20.5.7 (20.16.11)
    @types/react: 18.3.3 => 18.3.3
    @types/react-dom: 18.3.0 => 18.3.0
    @typescript-eslint/eslint-plugin: 7.2.0 => 7.2.0
    @typescript-eslint/parser: 7.2.0 => 7.2.0
    @vercel/nft:  undefined ()
    @vercel/og:  0.6.2
    @vitest/coverage-v8: ^2.1.3 => 2.1.3
    acorn:  undefined ()
    amphtml-validator:  undefined ()
    anser:  undefined ()
    arg:  undefined ()
    assert:  undefined ()
    async-retry:  undefined ()
    async-sema:  undefined ()
    autoprefixer: 10.4.19 => 10.4.19
    aws-amplify: ^6.4.0 => 6.6.2
    aws-amplify/adapter-core:  undefined ()
    aws-amplify/analytics:  undefined ()
    aws-amplify/analytics/kinesis:  undefined ()
    aws-amplify/analytics/kinesis-firehose:  undefined ()
    aws-amplify/analytics/personalize:  undefined ()
    aws-amplify/analytics/pinpoint:  undefined ()
    aws-amplify/api:  undefined ()
    aws-amplify/api/server:  undefined ()
    aws-amplify/auth:  undefined ()
    aws-amplify/auth/cognito:  undefined ()
    aws-amplify/auth/cognito/server:  undefined ()
    aws-amplify/auth/enable-oauth-listener:  undefined ()
    aws-amplify/auth/server:  undefined ()
    aws-amplify/data:  undefined ()
    aws-amplify/data/server:  undefined ()
    aws-amplify/datastore:  undefined ()
    aws-amplify/in-app-messaging:  undefined ()
    aws-amplify/in-app-messaging/pinpoint:  undefined ()
    aws-amplify/push-notifications:  undefined ()
    aws-amplify/push-notifications/pinpoint:  undefined ()
    aws-amplify/storage:  undefined ()
    aws-amplify/storage/s3:  undefined ()
    aws-amplify/storage/s3/server:  undefined ()
    aws-amplify/storage/server:  undefined ()
    aws-amplify/utils:  undefined ()
    aws-cdk: ^2 => 2.159.1
    aws-cdk-lib: ^2 => 2.159.1
    babel-packages:  undefined ()
    browserify-zlib:  undefined ()
    browserslist:  undefined ()
    buffer:  undefined ()
    bytes:  undefined ()
    ci-info:  undefined ()
    cli-select:  undefined ()
    client-only:  0.0.1
    clsx: 2.1.1 => 2.1.1 (1.2.1)
    comment-json:  undefined ()
    compression:  undefined ()
    conf:  undefined ()
    constants-browserify:  undefined ()
    constructs: ^10.3.0 => 10.3.0
    content-disposition:  undefined ()
    content-type:  undefined ()
    cookie:  undefined ()
    cross-spawn:  undefined ()
    crypto-browserify:  undefined ()
    css.escape:  undefined ()
    data-uri-to-buffer:  undefined ()
    dayjs: ^1.11.13 => 1.11.13
    debug:  undefined ()
    devalue:  undefined ()
    domain-browser:  undefined ()
    edge-runtime:  undefined ()
    esbuild: ^0.23.1 => 0.23.1 (0.21.5)
    eslint: ^8.57.0 => 8.57.1
    eslint-config-next: ^14.2.13 => 14.2.15
    eslint-config-prettier: ^8.2.0 => 8.10.0
    eslint-plugin-import: ^2.26.0 => 2.31.0
    eslint-plugin-jsx-a11y: ^6.4.1 => 6.10.0
    eslint-plugin-node: ^11.1.0 => 11.1.0
    eslint-plugin-prettier: ^5.1.3 => 5.2.1
    eslint-plugin-react: ^7.23.2 => 7.37.1
    eslint-plugin-react-hooks: ^4.6.0 => 4.6.2
    eslint-plugin-testing-library: ^6.4.0 => 6.4.0
    eslint-plugin-unused-imports: ^3.2.0 => 3.2.0
    eslint-plugin-vitest: ^0.5.4 => 0.5.4
    events:  undefined ()
    find-cache-dir:  undefined ()
    find-up:  undefined ()
    framer-motion: ~11.1.1 => 11.1.9
    fresh:  undefined ()
    get-orientation:  undefined ()
    glob:  undefined ()
    gzip-size:  undefined ()
    http-errors: ^2.0.0 => 2.0.0
    http-proxy:  undefined ()
    http-proxy-agent:  undefined ()
    https-browserify:  undefined ()
    https-proxy-agent:  undefined ()
    icss-utils:  undefined ()
    ignore-loader:  undefined ()
    image-size:  undefined ()
    intl-messageformat: ^10.5.0 => 10.7.0
    is-animated:  undefined ()
    is-docker:  undefined ()
    is-wsl:  undefined ()
    jest-worker:  undefined ()
    jsdom: ^25.0.1 => 25.0.1
    json5:  undefined ()
    jsonwebtoken:  undefined ()
    loader-runner:  undefined ()
    loader-utils:  undefined ()
    lodash.curry:  undefined ()
    lru-cache:  undefined ()
    micromatch:  undefined ()
    mini-css-extract-plugin:  undefined ()
    nanoid:  undefined ()
    native-url:  undefined ()
    neo-async:  undefined ()
    next: 14.1.1 => 14.1.1
    next-themes: ^0.2.1 => 0.2.1
    node-fetch:  undefined ()
    node-html-parser:  undefined ()
    ora:  undefined ()
    os-browserify:  undefined ()
    p-limit:  undefined ()
    path-browserify:  undefined ()
    platform:  undefined ()
    postcss: 8.4.38 => 8.4.38 (8.4.31, 8.4.47)
    postcss-flexbugs-fixes:  undefined ()
    postcss-modules-extract-imports:  undefined ()
    postcss-modules-local-by-default:  undefined ()
    postcss-modules-scope:  undefined ()
    postcss-modules-values:  undefined ()
    postcss-preset-env:  undefined ()
    postcss-safe-parser:  undefined ()
    postcss-scss:  undefined ()
    postcss-value-parser:  undefined ()
    process:  undefined ()
    punycode:  undefined ()
    querystring-es3:  undefined ()
    raw-body:  undefined ()
    react: ^18 => 18.3.1
    react-builtin:  undefined ()
    react-dom: ^18 => 18.3.1
    react-dom-builtin:  undefined ()
    react-dom-experimental-builtin:  undefined ()
    react-experimental-builtin:  undefined ()
    react-is:  18.2.0
    react-refresh:  0.12.0
    react-server-dom-turbopack-builtin:  undefined ()
    react-server-dom-turbopack-experimental-builtin:  undefined ()
    react-server-dom-webpack-builtin:  undefined ()
    react-server-dom-webpack-experimental-builtin:  undefined ()
    regenerator-runtime:  0.13.4
    sass-loader:  undefined ()
    scheduler-builtin:  undefined ()
    scheduler-experimental-builtin:  undefined ()
    schema-utils:  undefined ()
    semver:  undefined ()
    send:  undefined ()
    server-only:  0.0.1
    setimmediate:  undefined ()
    shell-quote:  undefined ()
    source-map:  undefined ()
    stacktrace-parser:  undefined ()
    stream-browserify:  undefined ()
    stream-http:  undefined ()
    string-hash:  undefined ()
    string_decoder:  undefined ()
    strip-ansi:  undefined ()
    superstruct:  undefined ()
    tailwind-variants: 0.1.20 => 0.1.20
    tailwindcss: 3.4.3 => 3.4.3
    tar:  undefined ()
    terser:  undefined ()
    text-table:  undefined ()
    timers-browserify:  undefined ()
    tsx: ^4.19.0 => 4.19.1
    tty-browserify:  undefined ()
    typescript: ^5.6.2 => 5.6.2 (4.4.4, 4.9.5)
    ua-parser-js:  undefined ()
    unistore:  undefined ()
    util:  undefined ()
    vitest: ^2.1.3 => 2.1.3
    vm-browserify:  undefined ()
    watchpack:  undefined ()
    web-vitals:  undefined ()
    webpack:  undefined ()
    webpack-sources:  undefined ()
    ws:  undefined ()
    zod:  undefined ()
  npmGlobalPackages:
    corepack: 0.19.0
    nextui-cli: 0.3.4
    npm: 9.8.0


Describe the bug

I have been working with the new Gen 2 Amplify stuff recently and really liking it. I am specifically working on trying to move into custom handlers for the Appsync/GraphQL stuff to add custom business logic into those operations.

From the front-end, everything works fine when using code like client.models.XXX.get or client.mutations.XXX, but when I attempt to use those things in my custom handler I am having problems.

First, I tried this approach:

import type { Schema } from '@/amplify/data/resource'
import { generateClient } from 'aws-amplify/data'
import { Amplify } from 'aws-amplify'
import outputs from '@/amplify_outputs.json'
import { Game } from '@/models/game'

Amplify.configure(outputs)
const client = generateClient<Schema>()

export const createGame = async (): Promise<Game> => {
  const { errors, data } = await client.mutations.createNewGame()
  ...

This works great in development but throws the following errors during build:

2024-10-31T03:11:13.154Z [INFO]: # Executing command: npx ampx pipeline-deploy --branch $AWS_BRANCH --app-id $AWS_APP_ID
2024-10-31T03:11:28.361Z [INFO]: SyntaxError: TypeScript validation check failed.
Resolution: Fix the syntax and type errors in your backend definition.
Cause: amplify/data/createGameHandler.ts(6,21): error TS2307: Cannot find module '../../amplify_outputs.json' or its corresponding type declarations.

I tried using TS ignore approaches and tried relative and absolute path changes but nothing seemed to allow the code to find the amplify_outputs.json file during build.

So next, using https://docs.amplify.aws/react/build-a-backend/data/custom-business-logic/connect-bedrock/ as an example, I was attempting to remove the need for Amplify.configure() in the Handler, so I moved to a solution like this:

import type { Schema } from './resource'
import { generateClient } from 'aws-amplify/data'
import { Game } from '@/models/game'

const client = generateClient<Schema>()

export const handler: Schema['createNewGame']['functionHandler'] = async () => {
  const { errors, data } = await client.mutations.createNewGame()
  ...

This allows the build to work, but during runtime I receive the following error in the browser console:

message: "Client could not be generated. This is likely due to `Amplify.configure()` not being called prior to `generateClient()` or because the configuration passed to `Amplify.configure()` is missing GraphQL provider configuration."

Expected behavior

I would expect either of the above solutions to work, because either the amplify_outputs.json file is available during build and runtime, or that the amplify_outputs.json file is not required in the handler and therefore code is not required at runtime to initialize Amplfy.

Reproduction steps

  1. Use the https://docs.amplify.aws/react/start/ guide to create a basic Amplify App.
  2. Create a custom model in the data/resource file.
  3. Add a custom handler that requires access to the client.models or client.mutations functions.
  4. Note that things work well in development, but you encounter issues in build or runtime in production.

Code Snippet

// data/resource.ts
const schema = a.schema({
  Game: a
    .model({
       ....
    })
    .authorization((allow) => [ allow.publicApiKey() ]),

  createNewGame: a
    .mutation()
    .returns(a.ref('Game'))
    .authorization((allow) => [ allow.publicApiKey() ])
    .handler(a.handler.function(defineFunction({
      entry: './createGameHandler.ts',
    }))),


// data/createGameHandler.ts
import type { Schema } from './resource'
import { generateClient } from 'aws-amplify/data'
import { Game } from '@/models/game'

const client = generateClient<Schema>()

export const handler: Schema['createNewGame']['functionHandler'] = async () => {
  // custom business logic here
  const { errors, data } = await client.models.Game.create({})
  ...

Log output

// Put your logs below this line


aws-exports.js

No response

Manual configuration

No response

Additional configuration

No response

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

@github-actions github-actions bot added pending-triage Issue is pending triage pending-maintainer-response Issue is pending a response from the Amplify team. labels Nov 2, 2024
@cwomack cwomack added the GraphQL Related to GraphQL API issues label Nov 4, 2024
@chrisbonifacio
Copy link
Member

chrisbonifacio commented Nov 4, 2024

Hi @mmixan we're still in the process of adding model based graphql operations support for lambda. in the meantime, we have this documentation for accessing your graphql api using a client.graphql approach rather than client.models.

please follow this doc and let us know if you run into any issues:

https://docs.amplify.aws/react/build-a-backend/data/customize-authz/grant-lambda-function-access-to-api/#access-the-api-using-aws-amplify

i've marked this as a feature request and will circle back once we release it

@github-actions github-actions bot removed the pending-maintainer-response Issue is pending a response from the Amplify team. label Nov 4, 2024
@chrisbonifacio chrisbonifacio added feature-request Request a new feature pending-maintainer-response Issue is pending a response from the Amplify team. and removed pending-triage Issue is pending triage pending-maintainer-response Issue is pending a response from the Amplify team. labels Nov 4, 2024
@jflaflamme
Copy link

Wish I had seen this post 2 days ago. Spent some several hours on this.
Looking forward for the updated doc.

@github-actions github-actions bot added the pending-maintainer-response Issue is pending a response from the Amplify team. label Nov 6, 2024
@mmixan
Copy link
Author

mmixan commented Nov 6, 2024

Thank you @chrisbonifacio !
I had seen that doc before, but was hoping there was something easier to work with.
I spent some time with that article the other day and it made sense, but I am struggling a bit with one line:
endpoint: env.<amplifyData>_GRAPHQL_ENDPOINT, // replace with your defineData name

Can you give a concrete example of what that would look like in practice? I have the generated code exported into a folder near the custom handler, but I am not following how to get to the URL in doc. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request Request a new feature GraphQL Related to GraphQL API issues pending-maintainer-response Issue is pending a response from the Amplify team.
Projects
None yet
Development

No branches or pull requests

4 participants